]> git.sur5r.net Git - openldap/commitdiff
Sync with HEAD
authorKurt Zeilenga <kurt@openldap.org>
Thu, 6 Jun 2002 17:54:12 +0000 (17:54 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Thu, 6 Jun 2002 17:54:12 +0000 (17:54 +0000)
32 files changed:
clients/tools/ldapmodify.c
doc/devel/args
doc/man/man1/ldapmodify.1
libraries/libldap/cache.c
libraries/libldap/compare.c
libraries/libldap/controls.c
libraries/libldap/cyrus.c
libraries/libldap/dnssrv.c
libraries/libldap/getentry.c
libraries/libldap/ldap-int.h
libraries/libldap/messages.c [new file with mode: 0644]
libraries/libldap/references.c
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/attribute.c
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/bind.c
servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/compare.c
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/dn2entry.c
servers/slapd/back-bdb/filterindex.c
servers/slapd/back-bdb/group.c
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/modify.c
servers/slapd/back-bdb/modrdn.c
servers/slapd/back-bdb/operational.c
servers/slapd/back-bdb/passwd.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/referral.c
servers/slapd/back-bdb/search.c
servers/slapd/daemon.c
servers/slapd/slap.h

index f55cb80aa15d2bc2bf83bfc057d768979e58e4b8..427952c5fa027e43b57a931f692257a0a923287f 100644 (file)
@@ -103,12 +103,14 @@ usage( const char *prog )
 "      specified by \"-f file\".\n"
 "Add or modify options:\n"
 "  -a         add values (default%s)\n"
+"  -c         continuous operation mode (do not stop on errors)\n"
+"  -f file    read operations from `file'\n"
 "  -F         force all changes records to be used\n"
+"  -S file    write skipped modifications to `file'\n"
 
 "Common options:\n"
 "  -d level   set LDAP debugging level to `level'\n"
 "  -D binddn  bind DN\n"
-"  -f file    read operations from `file'\n"
 "  -h host    LDAP server\n"
 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
 "  -I         use SASL Interactive mode\n"
@@ -138,10 +140,11 @@ usage( const char *prog )
 int
 main( int argc, char **argv )
 {
-    char               *infile, *rbuf, *start;
-    FILE               *fp;
+    char               *infile, *rejfile, *rbuf, *start, *rejbuf;
+    FILE               *fp, *rejfp;
+       char            *matched_msg = NULL, *error_msg = NULL;
        int             rc, i, authmethod, version, want_bindpw, debug, manageDSAit, referrals;
-       int count;
+       int count, len;
 
     if (( prog = strrchr( argv[ 0 ], *LDAP_DIRSEP )) == NULL ) {
        prog = argv[ 0 ];
@@ -156,12 +159,13 @@ main( int argc, char **argv )
     ldapadd = ( strncmp( prog, "ldapadd", sizeof("ldapadd")-1 ) == 0 );
 
     infile = NULL;
+    rejfile = NULL;
     not = verbose = want_bindpw = debug = manageDSAit = referrals = 0;
     authmethod = -1;
        version = -1;
 
     while (( i = getopt( argc, argv, "acrf:F"
-               "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z" )) != EOF )
+               "Cd:D:h:H:IkKMnO:p:P:QR:S:U:vw:WxX:Y:Z" )) != EOF )
        {
        switch( i ) {
        /* Modify Options */
@@ -403,6 +407,13 @@ main( int argc, char **argv )
                return( EXIT_FAILURE );
 #endif
                break;
+       case 'S':       /* skipped modifications to file */
+               if( rejfile != NULL ) {
+                       fprintf( stderr, "%s: -S previously specified\n", prog );
+                       return EXIT_FAILURE;
+               }
+               rejfile = strdup( optarg );
+               break;
        case 'U':
 #ifdef HAVE_CYRUS_SASL
                if( sasl_authc_id != NULL ) {
@@ -539,6 +550,15 @@ main( int argc, char **argv )
        if ( argc != optind )
        usage( prog );
 
+    if ( rejfile != NULL ) {
+       if (( rejfp = fopen( rejfile, "w" )) == NULL ) {
+           perror( rejfile );
+           return( EXIT_FAILURE );
+       }
+    } else {
+       rejfp = NULL;
+    }
+
     if ( infile != NULL ) {
        if (( fp = fopen( infile, "r" )) == NULL ) {
            perror( infile );
@@ -671,6 +691,7 @@ main( int argc, char **argv )
                        ldap_perror( ld, "ldap_bind" );
                        return( EXIT_FAILURE );
                }
+
        }
 
     }
@@ -707,10 +728,33 @@ main( int argc, char **argv )
 
        start = rbuf;
 
+       if ( rejfp ) {
+               len = strlen( rbuf );
+               if (( rejbuf = (char *)malloc( len+1 )) == NULL ) {
+                       perror( "realloc" );
+                       exit( EXIT_FAILURE );
+               }
+               memcpy( rejbuf, rbuf, len+1 );
+       }
+
     rc = process_ldif_rec( start, count );
 
-       if( rc )
-               fprintf( stderr, "ldif_record() = %d\n", rc );
+       if ( rc && rejfp ) {
+               fprintf(rejfp, "# Error: %s (%d)", ldap_err2string(rc), rc);
+
+               ldap_get_option(ld, LDAP_OPT_MATCHED_DN, &matched_msg);
+               if ( matched_msg != NULL && *matched_msg != '\0' ) {
+                       fprintf( rejfp, ", matched DN: %s", matched_msg );
+               }
+
+               ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &error_msg);
+               if ( error_msg != NULL && *error_msg != '\0' ) {
+                       fprintf( rejfp, ", additional info: %s", error_msg );
+               }
+               fprintf( rejfp, "\n%s\n", rejbuf );
+       }
+               if (rejfp) 
+                       free( rejbuf );
                free( rbuf );
     }
 
@@ -718,6 +762,10 @@ main( int argc, char **argv )
                ldap_unbind( ld );
     }
 
+    if ( rejfp != NULL ) {
+           fclose( rejfp );
+    }
+
        return( rc );
 }
 
index ea02cfa4f42b29bc149ef7cb40d1ddf91ba19b60..e000234440bafbba36332d93f384a1ed179576e1 100644 (file)
@@ -1,6 +1,6 @@
 Tools           ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
 ldapdelete       *CDE *HI*K M*OPQR  U*WXYZ  cdef*h**k *n*p*    vwx*
-ldapmodify       *CDEF*HI*K M*OPQR  U*WXYZabcdef*h**k *n*p*r t vwx*
+ldapmodify       *CDEF*HI*K M*OPQRS U*WXYZabcdef*h**k *n*p*r t vwx*
 ldapmodrdn       *CDE *HI*K M*OPQR  U*WXYZ  cdef*h**k *n*p*rs  vwx*
 ldappasswd      A*CDE *HI*   *O QRS U*WXYZa  de *h**  * * * s  vwx*  
 ldapsearch      A*CDE *HI*KLM*OPQRSTU*WXYZab*def*h**kl*n*p* stuvwx*z
index 3ffbe59a92f63c27156d2ad78e69edb06a2bb692..139753363277a7a1d0f0658884a00e6c5d5e949c 100644 (file)
-.TH LDAPMODIFY 1 "13 November 1995" "U-M LDAP LDVERSION"
+.TH LDAPMODIFY 1 "20 August 2001" "OpenLDAP LDVERSION"
+.\" $OpenLDAP$
+.\" Copyright 1998-2002 The OpenLDAP Foundation All Rights Reserved.
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
 .SH NAME
-ldapmodify, ldapadd \- ldap modify entry and ldap add entry tools
+ldapmodify, ldapadd \- LDAP modify entry and LDAP add entry tools
 .SH SYNOPSIS
 .B ldapmodify
-.B [\-a]
-.B [\-b]
-.B [\-c]
-.B [\-r]
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-d debuglevel]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [\-f file]
+[\c
+.BR \-a ]
+[\c
+.BR \-c ]
+[\c
+.BI \-S \ file\fR]
+.[\c
+.BR \-C ]
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BR \-M[M] ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-H \ ldapuri\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BR \-O \ security-properties ]
+[\c
+.BR \-I ]
+[\c
+.BR \-Q ]
+[\c
+.BI \-U \ authcid\fR]
+[\c
+.BR \-x ]
+[\c
+.BI \-X \ authzid\fR]
+[\c
+.BI \-Y \ mech\fR]
+[\c
+.BR \-Z[Z] ]
+[\c
+.BI \-f \ file\fR]
 .LP
 .B ldapadd
-.B [\-b]
-.B [\-c]
-.B [\-r]
-.B [\-n]
-.B [\-v]
-.B [\-k]
-.B [\-K]
-.B [\-d debuglevel]
-.B [\-D binddn]
-.B [\-w passwd]
-.B [\-h ldaphost]
-.B [\-p ldapport]
-.B [\-f file]
+[\c
+.BR \-c ]
+[\c
+.BI \-S \ file\fR]
+[\c
+.BR \-C ]
+[\c
+.BR \-n ]
+[\c
+.BR \-v ]
+[\c
+.BR \-k ]
+[\c
+.BR \-K ]
+[\c
+.BR \-M[M] ]
+[\c
+.BI \-d \ debuglevel\fR]
+[\c
+.BI \-D \ binddn\fR]
+[\c
+.BR \-W ]
+[\c
+.BI \-w \ passwd\fR]
+[\c
+.BI \-h \ ldaphost\fR]
+[\c
+.BI \-p \ ldapport\fR]
+[\c
+.BI \-P \ 2\fR\||\|\fI3\fR]
+[\c
+.BR \-O \ security-properties ]
+[\c
+.BR \-I ]
+[\c
+.BR \-Q ]
+[\c
+.BI \-U \ authcid\fR]
+[\c
+.BR \-x ]
+[\c
+.BI \-X \ authzid\fR]
+[\c
+.BI \-Y \ mech\fR]
+[\c
+.BR \-Z[Z] ]
+[\c
+.BI \-f \ file\fR]
 .SH DESCRIPTION
 .B ldapmodify
 is a shell-accessible interface to the
@@ -56,10 +133,8 @@ is to modify existing entries.  If invoked as
 .BR ldapadd ,
 this flag is always set.
 .TP
-.B \-b
-Assume that any values that start with a `/' are binary values and that
-the actual value is in a file whose path is specified in the place where
-values normally appear.
+.B \-C
+Automatically chase referrals.
 .TP
 .B \-c
 Continuous operation mode.  Errors are reported, but
@@ -67,8 +142,10 @@ Continuous operation mode.  Errors are reported, but
 will continue with modifications.  The default is to exit after
 reporting an error.
 .TP
-.B \-r
-Replace existing values by default.
+.BI \-S \ file
+Add or change records which where skipped due to an error are written to \fIfile\fP 
+and the error message returned by the server is added as a comment. Most useful in 
+conjunction with -c.
 .TP
 .B \-n
 Show what would be done, but don't actually modify entries.  Useful for
@@ -78,14 +155,14 @@ debugging in conjunction with -v.
 Use verbose mode, with many diagnostics written to standard output.
 .TP
 .B \-k
-Use Kerberos authentication instead of simple authentication.  It is
+Use Kerberos IV authentication instead of simple authentication.  It is
 assumed that you already have a valid ticket granting ticket.  You must
-compile with KERBEROS defined for this option to have any effect.
+compile with Kerberos support for this option to have any effect.
 .TP
 .B \-K
-Same as \-k, but only does step 1 of the kerberos bind.  This is useful
+Same as \-k, but only does step 1 of the Kerberos IV bind.  This is useful
 when connecting to a slapd and there is no x500dsa.hostname principal
-registered with your kerberos servers.
+registered with your Kerberos Domain Controller(s).
 .TP
 .B \-F
 Force application of all changes regardless of the contents of input
@@ -94,36 +171,85 @@ lines that begin with
 (by default, replica: lines are compared against the LDAP server host
 and port in use to decide if a replog record should actually be applied).
 .TP
-.B \-d debuglevel
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
+.BI \-d \ debuglevel
 Set the LDAP debugging level to \fIdebuglevel\fP.
 .B ldapmodify
 must be compiled with LDAP_DEBUG defined for this option to have any effect.
 .TP
-.B \-f file
+.BI \-f \ file
 Read the entry modification information from \fIfile\fP instead of from
 standard input.
 .TP
-.B \-D binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
-a string-represented DN as defined in RFC 1779.
+.B \-x 
+Use simple authentication instead of SASL.
+.TP
+.BI \-D \ binddn
+Use the Distinguished Name \fIbinddn\fP to bind to the LDAP directory.
 .TP
-.B \-w passwd
+.B \-W
+Prompt for simple authentication.
+This is used instead of specifying the password on the command line.
+.TP
+.BI \-w \ passwd
 Use \fIpasswd\fP as the password for simple authentication.
 .TP
-.B \-h ldaphost
+.BI \-H \ ldapuri
+Specify URI(s) referring to the ldap server(s).
+.TP
+.BI \-h \ ldaphost
 Specify an alternate host on which the ldap server is running.
+Deprecated in favor of -H.
 .TP
-.B \-p ldapport
+.BI \-p \ ldapport
 Specify an alternate TCP port where the ldap server is listening.
+Deprecated in favor of -H.
+.TP
+.BI \-P \ 2\fR\||\|\fI3
+Specify the LDAP protocol version to use.
+.TP
+.BI \-O \ security-properties
+Specify SASL security properties.
+.TP
+.B \-I
+Enable SASL Interactive mode.  Always prompt.  Default is to prompt
+only as needed.
+.TP
+.B \-Q
+Enable SASL Quiet mode.  Never prompt.
+.TP
+.BI \-U \ authcid
+Specify the authentication ID for SASL bind. The form of the ID
+depends on the actual SASL mechanism used.
+.TP
+.BI \-X \ authzid
+Specify the requested authorization ID for SASL bind.
+.I authzid
+must be one of the following formats:
+.B dn:\c
+.I <distinguished name>
+or
+.B u:\c
+.I <username>
+.TP
+.BI \-Y \ mech
+Specify the SASL mechanism to be used for authentication. If it's not
+specified, the program will choose the best mechanism the server knows.
+.TP
+.B \-Z[Z]
+Issue StartTLS (Transport Layer Security) extended operation. If you use
+.B \-ZZ\c
+, the command will require the operation to be successful.
 .SH INPUT FORMAT
 The contents of \fIfile\fP (or standard input if no \-f flag is given on
 the command line) should conform to the format defined in
 .BR slapd.replog (5),
 with the exceptions noted below.
 .LP
-If the first line of a record consists of a decimal number (entry id),
-it is ignored.
-.LP
 Lines that begin with "replica:" are matched against the LDAP server host
 and port in use to decide if a particular replog record should be applied.
 Any other lines that precede the "dn:" line are ignored.
@@ -138,8 +264,10 @@ flag is set (or if the program was invoked as
 and "modify" otherwise.
 .LP
 If changetype is "modify" and no "add:", "replace:", or "delete:" lines
-appear, the default is "replace" if the -r flag is set and "add"
-otherwise.
+appear, the default is "replace" for and "add"
+.BR ldapmodify (1)
+for
+.BR ldapadd (1).
 .LP
 Note that the above exceptions to the
 .BR slapd.replog (5)
@@ -149,56 +277,22 @@ entries to be used as input to
 .I ldapmodify
 or
 .I ldapadd.
-.SH ALTERNATIVE INPUT FORMAT
-An alternative input format is supported for compatibility with older
-versions of
-.I ldapmodify.
-This format consists of one or more entries separated by blank lines,
-where each entry looks like:
-.LP
-.nf
-    Distinguished Name (DN)
-    attr=value
-    [attr=value ...]
-.fi
-.LP
-where \fIattr\fP is the name of the attribute and \fIvalue\fP is the
-value.
-.LP
-By default, values are added.  If the
-.RI \- r
-command line flag is
-given, the default is to replace existing values with the new one.
-Note that it is permissible for a given attribute to appear more than
-once (for example, to add more than one value for an attribute).  Also
-note that you can use a trailing `\\' to continue values across lines and
-preserve newlines in the value itself (this is useful for modifying
-QUIPU iattr attributes among others).
-.LP
-.I attr
-should be preceded by a \fB-\fP to remove a value.  The `=' and
-value should be omitted to remove an entire attribute.
-.LP
-.I attr
-should be preceded by a \fB+\fP to add a value in the presence of the
-\-r flag.
-.LP
 .SH EXAMPLES
 Assuming that the file
 .B /tmp/entrymods
 exists and has the contents:
 .LP
 .nf
-    dn: cn=Modify Me, o=University of Michigan, c=US
+    dn: cn=Modify Me,dc=example,dc=com
     changetype: modify
     replace: mail
-    mail: modme@terminator.rs.itd.umich.edu
+    mail: modme@OpenLDAP.org
     -
     add: title
     title: Grand Poobah
     -
     add: jpegPhoto
-    jpegPhoto: /tmp/modme.jpeg
+    jpegPhoto:< file://tmp/modme.jpeg
     -
     delete: description
     -
@@ -207,12 +301,12 @@ exists and has the contents:
 the command:
 .LP
 .nf
-    ldapmodify -b -r -f /tmp/entrymods
+    ldapmodify -f /tmp/entrymods
 .fi
 .LP
 will replace the contents of the "Modify Me" entry's
 .I mail
-attribute with the value "modme@terminator.rs.itd.umich.edu", add a
+attribute with the value "modme@example.com", add a
 .I title
 of "Grand Poobah", and the contents of the file "/tmp/modme.jpeg"
 as a
@@ -220,36 +314,19 @@ as a
 and completely remove the
 .I description
 attribute.
-The same modifications as above can be performed using the older
-.I ldapmodify
-inout format:
-.LP
-.nf
-    cn=Modify Me, o=University of Michigan, c=US
-    mail=modme@terminator.rs.itd.umich.edu
-    +title=Grand Poobah
-    +jpegPhoto=/tmp/modme.jpeg
-    -description
-.fi
-.LP
-and the command:
-.LP
-.nf
-    ldapmodify -b -r -f /tmp/entrymods
-.fi
 .LP
 Assuming that the file
 .B /tmp/newentry
 exists and has the contents:
 .LP
 .nf
-    dn: cn=Barbara Jensen, o=University of Michigan, c=US
+    dn: cn=Barbara Jensen,dc=example,dc=com
     objectClass: person
     cn: Barbara Jensen
     cn: Babs Jensen
     sn: Jensen
     title: the world's most famous mythical manager
-    mail: bjensen@terminator.rs.itd.umich.edu
+    mail: bjensen@example.com
     uid: bjensen
 .LP
 the command:
@@ -267,7 +344,7 @@ Assuming that the file
 exists and has the contents:
 .LP
 .nf
-    dn: cn=Barbara Jensen, o=University of Michigan, c=US
+    dn: cn=Barbara Jensen,dc=example,dc=com
     changetype: delete
 .LP
 the command:
@@ -278,24 +355,24 @@ the command:
 .LP
 will remove Babs Jensen's entry.
 .SH DIAGNOSTICS
-Exit status is 0 if no errors occur.  Errors result in a non-zero exit
-status and a diagnostic message being written to standard error.
+Exit status is zero if no errors occur.  Errors result in a non-zero
+exit status and a diagnostic message being written to standard error.
 .SH "SEE ALSO"
 .BR ldapadd (1),
 .BR ldapdelete (1),
 .BR ldapmodrdn (1),
 .BR ldapsearch (1),
+.BR ldap.conf (5),
 .BR ldap (3),
 .BR ldap_add (3),
 .BR ldap_delete (3),
 .BR ldap_modify (3),
 .BR ldap_modrdn (3),
 .BR slapd.replog (5)
-.LP
-Kille, S.,
-.IR "A String Representation of Distinguished Names",
-.SM RFC
-1779,
-ISODE Consortium, March 1995.
-.SH BUGS
-There is no interactive mode, but there probably should be.
+.SH AUTHOR
+The OpenLDAP Project <http://www.openldap.org/>
+.SH ACKNOWLEDGEMENTS
+.B     OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B     OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.  
index ccfc763092d3973aac0e8100edb35cceeb2ccba9..83e6e7953cbe9b0ff8da07f23f52149eb1999bf9 100644 (file)
@@ -37,6 +37,9 @@ static void           uncache_entry_or_req LDAP_P(( LDAP *ld, LDAP_CONST char *dn, ber_in
 int
 ldap_enable_cache( LDAP *ld, long timeout, ber_len_t maxmem )
 {
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifndef LDAP_NOCACHE
        if ( ld->ld_cache == NULL ) {
                if (( ld->ld_cache = (LDAPCache *)LDAP_MALLOC( sizeof( LDAPCache )))
@@ -62,6 +65,9 @@ ldap_enable_cache( LDAP *ld, long timeout, ber_len_t maxmem )
 void
 ldap_disable_cache( LDAP *ld )
 {
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifndef LDAP_NOCACHE
        if ( ld->ld_cache != NULL ) {
                ld->ld_cache->lc_enabled = 0;
@@ -74,6 +80,9 @@ ldap_disable_cache( LDAP *ld )
 void
 ldap_set_cache_options( LDAP *ld, unsigned long opts )
 {
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifndef LDAP_NOCACHE
        if ( ld->ld_cache != NULL ) {
                ld->ld_cache->lc_options = opts;
@@ -85,6 +94,9 @@ ldap_set_cache_options( LDAP *ld, unsigned long opts )
 void
 ldap_destroy_cache( LDAP *ld )
 {
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifndef LDAP_NOCACHE
        if ( ld->ld_cache != NULL ) {
                ldap_flush_cache( ld );
@@ -102,6 +114,9 @@ ldap_flush_cache( LDAP *ld )
        int             i;
        LDAPMessage     *m, *next;
 
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "cache", LDAP_LEVEL_ENTRY, "ldap_flush_cache\n" ));
 #else
@@ -134,6 +149,9 @@ ldap_flush_cache( LDAP *ld )
 void
 ldap_uncache_request( LDAP *ld, int msgid )
 {
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifndef LDAP_NOCACHE
 #ifdef NEW_LOGGING
        LDAP_LOG (( "cache", LDAP_LEVEL_ARGS, 
@@ -152,6 +170,10 @@ ldap_uncache_request( LDAP *ld, int msgid )
 void
 ldap_uncache_entry( LDAP *ld, LDAP_CONST char *dn )
 {
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( dn != NULL );
+
 #ifndef LDAP_NOCACHE
 #ifdef NEW_LOGGING
        LDAP_LOG (( "cache", LDAP_LEVEL_ARGS, 
@@ -240,6 +262,9 @@ ldap_add_request_to_cache( LDAP *ld, ber_tag_t msgtype, BerElement *request )
        LDAPMessage     *new;
        ber_len_t       len;
 
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "cache", LDAP_LEVEL_ENTRY, "ldap_add_request_to_cache\n" ));
 #else
@@ -288,6 +313,10 @@ ldap_add_result_to_cache( LDAP *ld, LDAPMessage *result )
        LDAPMessage     *m, **mp, *req, *new, *prev;
        int             err, keep;
 
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( result != NULL );
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "cache", LDAP_LEVEL_ARGS, 
                "ldap_add_result_to_cache: id %ld, type %ld\n",
@@ -447,6 +476,10 @@ ldap_check_cache( LDAP *ld, ber_tag_t msgtype, BerElement *request )
        int             first, hash;
        time_t  c_time;
 
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( request != NULL );
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "cache", LDAP_LEVEL_ENTRY, "ldap_check_cache\n" ));
 #else
index 83d7ec125e934325daa614f8e27b0f6f3b25576c..4af59d01b8d15842a6a5f44db0244028d1a04c66 100644 (file)
@@ -131,6 +131,8 @@ ldap_compare(
        int msgid;
        struct berval bvalue;
 
+       assert( value != NULL );
+
        bvalue.bv_val = (char *) value;
        bvalue.bv_len = (value == NULL) ? 0 : strlen( value );
 
@@ -171,6 +173,8 @@ ldap_compare_s(
 {
        struct berval bvalue;
 
+       assert( value != NULL );
+
        bvalue.bv_val = (char *) value;
        bvalue.bv_len = (value == NULL) ? 0 : strlen( value );
 
index 76c2799236133b46dc3e2dcc760936d29b8e37cf..12f455be9863cc1e9fc97ef205d6a2b14abc3bd5 100644 (file)
@@ -38,6 +38,7 @@ ldap_int_put_controls(
        LDAPControl *const *c;
 
        assert( ld != NULL );
+       assert( LDAP_VALID(ld) );
        assert( ber != NULL );
 
        if( ctrls == NULL ) {
@@ -414,6 +415,7 @@ ldap_create_control(
        struct berval *bvalp;
 
        assert( requestOID != NULL );
+       assert( ber != NULL );
        assert( ctrlp != NULL );
 
        ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
@@ -452,6 +454,7 @@ int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
        LDAPControl *const *c;
 
        assert( ld != NULL );
+       assert( LDAP_VALID(ld) );
 
        if( ctrls == NULL ) {
                /* use default server controls */
index c35eb0d5a996c2a90d84c205bc67f2973f1dc02b..b2707577dfa0e6c6f7dccd4c462a9e5de2cef1d4 100644 (file)
@@ -434,19 +434,6 @@ ldap_int_sasl_open(
        int rc;
        sasl_conn_t *ctx;
 
-       sasl_callback_t *session_callbacks =
-               LDAP_CALLOC( 2, sizeof( sasl_callback_t ) );
-
-       if( session_callbacks == NULL ) return LDAP_NO_MEMORY;
-
-       session_callbacks[0].id = SASL_CB_USER;
-       session_callbacks[0].proc = NULL;
-       session_callbacks[0].context = ld;
-
-       session_callbacks[1].id = SASL_CB_LIST_END;
-       session_callbacks[1].proc = NULL;
-       session_callbacks[1].context = NULL;
-
        assert( lc->lconn_sasl_ctx == NULL );
 
        if ( host == NULL ) {
@@ -456,14 +443,13 @@ ldap_int_sasl_open(
 
 #if SASL_VERSION_MAJOR >= 2
        rc = sasl_client_new( "ldap", host, NULL, NULL,
-               session_callbacks, 0, &ctx );
+               NULL, 0, &ctx );
 #else
-       rc = sasl_client_new( "ldap", host, session_callbacks,
+       rc = sasl_client_new( "ldap", host, NULL,
                SASL_SECURITY_LAYER, &ctx );
 #endif
 
        if ( rc != SASL_OK ) {
-               LDAP_FREE( session_callbacks );
                ld->ld_errno = sasl_err2ldap( rc );
                return ld->ld_errno;
        }
@@ -477,7 +463,6 @@ ldap_int_sasl_open(
 #endif
 
        lc->lconn_sasl_ctx = ctx;
-       lc->lconn_sasl_cbs = session_callbacks;
 
        if( ssf ) {
 #if SASL_VERSION_MAJOR >= 2
@@ -510,8 +495,6 @@ int ldap_int_sasl_close( LDAP *ld, LDAPConn *lc )
        if( ctx != NULL ) {
                sasl_dispose( &ctx );
                lc->lconn_sasl_ctx = NULL;
-               LDAP_FREE( lc->lconn_sasl_cbs );
-               lc->lconn_sasl_cbs = NULL;
        }
 
        return LDAP_SUCCESS;
index 1a763c9b6efc3b419206f83e464d11cab6988cb7..cc193e93582bef587dcfb15c511b60feaf00d18d 100644 (file)
@@ -41,9 +41,8 @@ int ldap_dn2domain(
        char *domain = NULL;
        char **dn;
 
-       if( dn_in == NULL || domainp == NULL ) {
-               return -1;
-       }
+       assert( dn_in != NULL );
+       assert( domainp != NULL );
 
        dn = ldap_explode_dn( dn_in, 0 );
 
@@ -147,12 +146,12 @@ int ldap_domain2dn(
     char *domain, *s, *tok_r, *dn;
     size_t loc;
 
-    if (domain_in == NULL || dnp == NULL) {
-       return LDAP_NO_MEMORY;
-    }
+       assert( domain_in != NULL );
+       assert( dnp != NULL );
+
     domain = LDAP_STRDUP(domain_in);
     if (domain == NULL) {
-       return LDAP_NO_MEMORY;
+               return LDAP_NO_MEMORY;
     }
     dn = NULL;
     loc = 0;
index b75a4403f4e787efcffc57c15f2665bcaca5dd88..4fb23eff6cb69bc0993f0daec9c65963daf39231 100644 (file)
@@ -29,10 +29,6 @@ ldap_first_entry( LDAP *ld, LDAPMessage *chain )
        assert( LDAP_VALID( ld ) );
        assert( chain != NULL );
 
-       if( ld == NULL || chain == NULL ) {
-               return NULL;
-       }
-
        return chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY
                ? chain
                : ldap_next_entry( ld, chain );
@@ -45,11 +41,7 @@ ldap_next_entry( LDAP *ld, LDAPMessage *entry )
        assert( LDAP_VALID( ld ) );
        assert( entry != NULL );
 
-       if ( ld == NULL || entry == NULL ) {
-               return NULL;
-       }
-
-       for (
+       for(
                entry = entry->lm_chain;
                entry != NULL;
                entry = entry->lm_chain )
@@ -70,10 +62,6 @@ ldap_count_entries( LDAP *ld, LDAPMessage *chain )
        assert( ld != NULL );
        assert( LDAP_VALID( ld ) );
 
-       if ( ld == NULL ) {
-               return -1;
-       }
-
        for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
                if( chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY ) {
                        i++;
index cd10cde790ab87aaf485cf9b3ddcde46f3469ca7..4ad20dd9f4c813a6172fbc9e940e42b441803d9d 100644 (file)
@@ -189,7 +189,6 @@ typedef struct ldap_conn {
 #endif
 #ifdef HAVE_CYRUS_SASL
        void            *lconn_sasl_ctx;
-       void            *lconn_sasl_cbs;
 #endif
        int                     lconn_refcnt;
        time_t          lconn_lastused; /* time */
diff --git a/libraries/libldap/messages.c b/libraries/libldap/messages.c
new file mode 100644 (file)
index 0000000..bcb13a7
--- /dev/null
@@ -0,0 +1,55 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+ *  messages.c
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+LDAPMessage *
+ldap_first_message( LDAP *ld, LDAPMessage *chain )
+{
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( chain != NULL );
+
+       return chain;
+}
+
+LDAPMessage *
+ldap_next_message( LDAP *ld, LDAPMessage *msg )
+{
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+       assert( msg != NULL );
+
+       return msg->lm_chain;
+}
+
+int
+ldap_count_messages( LDAP *ld, LDAPMessage *chain )
+{
+       int     i;
+
+       assert( ld != NULL );
+       assert( LDAP_VALID( ld ) );
+
+       for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
+               i++;
+       }
+
+       return( i );
+}
index 2aae3f469c5a0bcce38000b0685e601c19cb4a6f..ff9b63fc0c7902403a6716bee1cf279004311cd6 100644 (file)
@@ -24,7 +24,7 @@ ldap_first_reference( LDAP *ld, LDAPMessage *chain )
 {
        assert( ld != NULL );
        assert( LDAP_VALID( ld ) );
-       assert( chain !=  NULL );
+       assert( chain != NULL );
 
        return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE
                ? chain
@@ -36,7 +36,7 @@ ldap_next_reference( LDAP *ld, LDAPMessage *ref )
 {
        assert( ld != NULL );
        assert( LDAP_VALID( ld ) );
-       assert( ref !=  NULL );
+       assert( ref != NULL );
 
        for (
                ref = ref->lm_chain;
@@ -58,13 +58,7 @@ ldap_count_references( LDAP *ld, LDAPMessage *chain )
 
        assert( ld != NULL );
        assert( LDAP_VALID( ld ) );
-       assert( chain !=  NULL );
-
-       if ( ld == NULL ) {
-               return -1;
-       }
 
-       
        for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
                if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
                        i++;
index b7cc3e70ef661f6a08cb1c6d0550da567177b2fc..98fa9b85665a0c0e60fbc89325a5879ce13856ac 100644 (file)
@@ -23,7 +23,7 @@ bdb_add(
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        struct berval   pdn;
        Entry           *p = NULL;
-       int                     rc
+       int             rc, ret
        const char      *text;
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
@@ -33,6 +33,8 @@ bdb_add(
 #ifdef BDB_SUBENTRIES
        int subentry;
 #endif
+       u_int32_t       locker;
+       DB_LOCK         lock;
 #if 0
        u_int32_t       lockid;
        DB_LOCK         lock;
@@ -108,6 +110,8 @@ retry:      /* transaction retry */
                text = "internal error";
                goto return_results;
        }
+
+       locker = TXN_ID ( ltid );
 #if 0
        lockid = TXN_ID( ltid );
 #endif
@@ -142,7 +146,7 @@ retry:      /* transaction retry */
 #endif
 
                /* get parent */
-               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0 );
+               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0, locker, &lock );
 
                switch( rc ) {
                case 0:
@@ -169,7 +173,7 @@ retry:      /* transaction retry */
                                refs = is_entry_referral( matched )
                                        ? get_entry_referrals( be, conn, op, matched )
                                        : NULL;
-                               bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                               bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, matched );
                                matched = NULL;
 
                        } else {
@@ -200,7 +204,7 @@ retry:      /* transaction retry */
                case DB_LOCK_DEADLOCK:
                case DB_LOCK_NOTGRANTED:
                        /* free parent and reader lock */
-                       bdb_cache_return_entry_r( &bdb->bi_cache, p );
+                       bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
                        p = NULL;
                        goto retry;
                }
@@ -262,7 +266,7 @@ retry:      /* transaction retry */
                                matched_dn, NULL, refs, NULL );
 
                        ber_bvarray_free( refs );
-                       bdb_cache_return_entry_r( &bdb->bi_cache, p );
+                       bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
                        p = NULL;
                        goto done;
                }
@@ -275,7 +279,7 @@ retry:      /* transaction retry */
 #endif
 
                /* free parent and reader lock */
-               bdb_cache_return_entry_r( &bdb->bi_cache, p );
+               bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
                p = NULL;
 
        } else {
@@ -430,9 +434,22 @@ retry:     /* transaction retry */
                        text = "txn_prepare failed";
 
                } else {
+                       ret = bdb_cache_add_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, CACHE_WRITE_LOCK, locker, &lock);
+#if 0
                        if ( bdb_cache_add_entry_rw(&bdb->bi_cache,
                                e, CACHE_WRITE_LOCK) != 0 )
-                       {
+#endif
+                       switch ( ret ) {
+                       case 0:
+                               break;
+                       case DB_LOCK_DEADLOCK:
+                       case DB_LOCK_NOTGRANTED:
+                               goto retry;
+                       default:
+                               ret = LDAP_OTHER;
+                       }
+
+                       if ( ret ) {
                                if(( rc=TXN_ABORT( ltid )) != 0 ) {
                                        text = "cache add & txn_abort failed";
                                } else {
index 38203b994d3e245290427b0d29eb1e30a4962c8e..1277f0256104f9addae957f37ed24829b19ed65a 100644 (file)
@@ -39,6 +39,9 @@ bdb_attribute(
        const char *entry_at_name = entry_at->ad_cname.bv_val;
        AccessControlState acl_state = ACL_STATE_INIT;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG(( "backend", LDAP_LEVEL_ARGS,
                "bdb_attribute: gr dn: \"%s\"\n", entry_ndn->bv_val ));
@@ -65,6 +68,11 @@ bdb_attribute(
                txn = boi->boi_txn;
        }
 
+       if ( txn != NULL )
+               locker = TXN_ID ( txn );
+       else
+               LOCK_ID ( bdb->bi_dbenv, &locker );
+
        if (target != NULL && dn_match(&target->e_nname, entry_ndn)) {
                /* we already have a LOCKED copy of the entry */
                e = target;
@@ -80,16 +88,23 @@ bdb_attribute(
 
 
        } else {
+dn2entry_retry:
                /* can we find entry */
-               rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0 );
+               rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0, locker, &lock );
                switch( rc ) {
                case DB_NOTFOUND:
                case 0:
                        break;
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto dn2entry_retry;
                default:
                        if( txn != NULL ) {
                                boi->boi_err = rc;
                        }
+                       else {
+                               LOCK_ID_FREE( bdb->bi_dbenv, locker );
+                       }
                        return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
                }
                if (e == NULL) {
@@ -102,6 +117,9 @@ bdb_attribute(
                                "=> bdb_attribute: cannot find entry: \"%s\"\n",
                                        entry_ndn->bv_val, 0, 0 ); 
 #endif
+                       if ( txn == NULL ) {
+                               LOCK_ID_FREE( bdb->bi_dbenv, locker );
+                       }
                        return LDAP_NO_SUCH_OBJECT; 
                }
                
@@ -205,7 +223,11 @@ bdb_attribute(
 return_results:
        if( target != e ) {
                /* free entry */
-               bdb_cache_return_entry_r(&bdb->bi_cache, e);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
+       }
+
+       if ( txn == NULL ) {
+               LOCK_ID_FREE( bdb->bi_dbenv, locker );
        }
 
 #ifdef NEW_LOGGING
index be89b98bf30361f5165387cc92175719c878f71b..784bbc89aaa40eeffa247c368991d747d9db1dc7 100644 (file)
@@ -146,21 +146,27 @@ struct bdb_op_info {
 #if DB_VERSION_MAJOR < 4
 #define LOCK_DETECT(env,f,t,a)         lock_detect(env, f, t, a)
 #define LOCK_GET(env,i,f,o,m,l)                lock_get(env, i, f, o, m, l)
+#define LOCK_PUT(env,l)                        lock_put(env, l)
 #define TXN_CHECKPOINT(env,k,m,f)      txn_checkpoint(env, k, m, f)
 #define TXN_BEGIN(env,p,t,f)           txn_begin((env), p, t, f)
 #define TXN_PREPARE(txn,gid)           txn_prepare((txn), (gid))
 #define TXN_COMMIT(txn,f)                      txn_commit((txn), (f))
 #define        TXN_ABORT(txn)                          txn_abort((txn))
 #define TXN_ID(txn)                                    txn_id(txn)
+#define LOCK_ID(env, locker)           lock_id(env, locker)
+#define LOCK_ID_FREE(env, locker)      lock_id_free(env, locker)
 #else
 #define LOCK_DETECT(env,f,t,a)         (env)->lock_detect(env, f, t, a)
 #define LOCK_GET(env,i,f,o,m,l)                (env)->lock_get(env, i, f, o, m, l)
+#define LOCK_PUT(env,l)                        (env)->lock_put(env, l)
 #define TXN_CHECKPOINT(env,k,m,f)      (env)->txn_checkpoint(env, k, m, f)
 #define TXN_BEGIN(env,p,t,f)           (env)->txn_begin((env), p, t, f)
 #define TXN_PREPARE(txn,g)                     (txn)->prepare((txn), (g))
 #define TXN_COMMIT(txn,f)                      (txn)->commit((txn), (f))
 #define TXN_ABORT(txn)                         (txn)->abort((txn))
 #define TXN_ID(txn)                                    (txn)->id(txn)
+#define LOCK_ID(env, locker)           (env)->lock_id(env, locker)
+#define LOCK_ID_FREE(env, locker)      (env)->lock_id_free(env, locker)
 #endif
 
 LDAP_END_DECL
index ad1bcfe3bb8315648d2da15b9a6ec51412cce818..be64c5b6a8c90ca587a63b51cbf81943868bf619 100644 (file)
@@ -40,14 +40,20 @@ bdb_bind(
 
        AttributeDescription *password = slap_schema.si_ad_userPassword;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "bind", LDAP_LEVEL_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val ));
 #else
        Debug( LDAP_DEBUG_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val, 0, 0);
 #endif
 
+       LOCK_ID(bdb->bi_dbenv, &locker);
+
+dn2entry_retry:
        /* get entry */
-       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
 
        switch(rc) {
        case DB_NOTFOUND:
@@ -56,10 +62,15 @@ bdb_bind(
        case LDAP_BUSY:
                send_ldap_result( conn, op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
+               LOCK_ID_FREE(bdb->bi_dbenv, locker);
                return LDAP_BUSY;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
                send_ldap_result( conn, op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
+               LOCK_ID_FREE(bdb->bi_dbenv, locker);
                return rc;
        }
 
@@ -75,7 +86,7 @@ bdb_bind(
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
 
-                       bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
                        matched = NULL;
 
                } else {
@@ -108,6 +119,8 @@ bdb_bind(
                                NULL, NULL, NULL, NULL );
                }
 
+               LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
                ber_bvarray_free( refs );
                free( matched_dn );
 
@@ -274,9 +287,11 @@ bdb_bind(
 done:
        /* free entry and reader lock */
        if( e != NULL ) {
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
 
+       LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
        /* front end with send result on success (rc==0) */
        return rc;
 }
index 5038db4bc799bacf7dbe6f7982e621f379a1a0db..18854548fed61a6764105066e3f1d7348f53a697 100644 (file)
@@ -132,6 +132,36 @@ bdb_cache_entry_private_init( Entry *e )
        return 0;
 }
 
+int
+bdb_cache_entry_db_lock
+( DB_ENV *env, u_int32_t locker, Entry *e, int rw, u_int32_t flags, DB_LOCK *lock )
+{
+       int       rc;
+       DBT       lockobj;
+       int       db_rw;
+
+       if (rw)
+               db_rw = DB_LOCK_WRITE;
+       else
+               db_rw = DB_LOCK_READ;
+
+       lockobj.data = e->e_nname.bv_val;
+       lockobj.size = e->e_nname.bv_len;
+       rc = LOCK_GET(env, locker, flags | DB_LOCK_NOWAIT,
+                                       &lockobj, db_rw, lock);
+       return rc;
+}
+
+int
+bdb_cache_entry_db_unlock
+( DB_ENV *env, DB_LOCK *lock )
+{
+       int rc;
+
+       rc = LOCK_PUT ( env, lock );
+       return rc;
+}
+
 /*
  * marks an entry in CREATING state as committed, so it is really returned
  * to the cache. Otherwise an entry in CREATING state is removed.
@@ -162,8 +192,9 @@ bdb_cache_entry_private_destroy( Entry *e )
 }
 
 void
-bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
+bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
 {
+
        ID id;
        int refcnt, freeit = 1;
 
@@ -172,7 +203,112 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
 
        assert( e->e_private );
 
+#if 0
        bdb_cache_entry_rdwr_unlock(e, rw);
+#endif
+
+       id = e->e_id;
+       refcnt = --BEI(e)->bei_refcnt;
+
+       /*
+        * if the entry is returned when in CREATING state, it is deleted
+        * but not freed because it may belong to someone else (do_add,
+        * for instance)
+        */
+       if (  BEI(e)->bei_state == CACHE_ENTRY_CREATING ) {
+               /* set lru mutex */
+               ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
+               bdb_cache_delete_entry_internal( cache, e );
+               /* free lru mutex */
+               ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
+               freeit = 0;
+               /* now the entry is in DELETED state */
+       }
+
+       if ( BEI(e)->bei_state == CACHE_ENTRY_COMMITTED ) {
+               BEI(e)->bei_state = CACHE_ENTRY_READY;
+
+               /* free cache write lock */
+               ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                          "bdb_unlocked_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
+                          id, rw ? "w" : "r", refcnt ));
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "====> bdb_unlocked_cache_return_entry_%s( %ld ): created (%d)\n",
+                       rw ? "w" : "r", id, refcnt );
+#endif
+
+
+       } else if ( BEI(e)->bei_state == CACHE_ENTRY_DELETED ) {
+               if( refcnt > 0 ) {
+                       /* free cache write lock */
+                       ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                                  "bdb_unlocked_cache_return_entry_rw: %ld, delete pending (%d).\n",
+                                  id, refcnt ));
+#else
+                       Debug( LDAP_DEBUG_TRACE,
+                               "====> bdb_unlocked_cache_return_entry_%s( %ld ): delete pending (%d)\n",
+                               rw ? "w" : "r", id, refcnt );
+#endif
+
+               } else {
+                       bdb_cache_entry_private_destroy( e );
+                       if ( freeit ) {
+                               bdb_entry_return( e );
+                       }
+
+                       /* free cache write lock */
+                       ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                                  "bdb_unlocked_cache_return_entry_rw: (%ld): deleted (%d)\n",
+                                  id, refcnt ));
+#else
+                       Debug( LDAP_DEBUG_TRACE,
+                               "====> bdb_unlocked_cache_return_entry_%s( %ld ): deleted (%d)\n",
+                               rw ? "w" : "r", id, refcnt );
+#endif
+               }
+
+       } else {
+               /* free cache write lock */
+               ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                          "bdb_unlocked_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
+                          id, rw ? "w": "r", refcnt ));
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "====> bdb_unlocked_cache_return_entry_%s( %ld ): returned (%d)\n",
+                       rw ? "w" : "r", id, refcnt);
+#endif
+       }
+}
+
+void
+bdb_cache_return_entry_rw
+( DB_ENV *env, Cache *cache, Entry *e, int rw, DB_LOCK *lock )
+{
+       ID id;
+       int refcnt, freeit = 1;
+
+       /* set cache write lock */
+       ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
+
+       assert( e->e_private );
+
+       bdb_cache_entry_db_unlock( env, lock );
+#if 0
+       bdb_cache_entry_rdwr_unlock(e, rw);
+#endif
 
        id = e->e_id;
        refcnt = --BEI(e)->bei_refcnt;
@@ -290,12 +426,16 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
  * returns:    0       entry has been created and locked
  *             1       entry already existed
  *             -1      something bad happened
+ *             other    Berkeley DB locking error code
  */
 int
 bdb_cache_add_entry_rw(
+    DB_ENV     *env,
     Cache      *cache,
     Entry      *e,
-    int                rw
+    int                rw,
+    u_int32_t  locker,
+    DB_LOCK    *lock
 )
 {
        int     i, rc;
@@ -385,7 +525,37 @@ bdb_cache_add_entry_rw(
                return( -1 );
        }
 
-       bdb_cache_entry_rdwr_lock( e, rw );
+       rc = bdb_cache_entry_db_lock( env, locker, e, rw, 0, lock );
+       switch ( rc ) {
+       case 0 :
+               break;
+       case DB_LOCK_DEADLOCK :
+       case DB_LOCK_NOTGRANTED :
+               /* undo avl changes immediately */
+               if ( avl_delete( &cache->c_idtree, (caddr_t) e,
+                       (AVL_CMP) entry_id_cmp ) == NULL ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
+                               "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+#else
+                       Debug( LDAP_DEBUG_ANY, "====> can't delete from id cache\n", 0, 0, 0 );
+#endif
+               }
+               if ( avl_delete( &cache->c_dntree, (caddr_t) e,
+                               (AVL_CMP) entry_dn_cmp ) == NULL ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
+                                       "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+#else
+                       Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", 0, 0, 0 );
+#endif
+               }
+               /* fall through */
+       default :
+               bdb_cache_entry_private_destroy(e);
+               ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+               return rc;
+       }
 
        /* put the entry into 'CREATING' state */
        /* will be marked after when entry is returned */
@@ -661,14 +831,18 @@ try_again:
 
 Entry *
 bdb_cache_find_entry_id(
+       DB_ENV  *env,
        Cache   *cache,
        ID                              id,
-       int                             rw
+       int                             rw,
+       u_int32_t       locker,
+       DB_LOCK         *lock
 )
 {
        Entry   e;
        Entry   *ep;
        int     count = 0;
+       int     rc;
 
        e.e_id = id;
 
@@ -715,7 +889,13 @@ try_again:
                }
 
                /* acquire reader lock */
+               rc = bdb_cache_entry_db_lock ( env, locker, ep, rw, 0, lock );
+
+#if 0
                if ( bdb_cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
+#endif
+
+               if ( rc ) { /* will be changed to retry beyond threshold */
                        /* could not acquire entry lock...
                         * owner cannot free as we have the cache locked.
                         * so, unlock the cache, yield, and try again.
@@ -732,6 +912,9 @@ try_again:
                        Debug(LDAP_DEBUG_TRACE,
                                "====> bdb_cache_find_entry_id( %ld ): %ld (busy) %d\n",
                                id, ep_id, state);
+                       Debug(LDAP_DEBUG_TRACE,
+                               "locker = %d\n",
+                               locker, 0, 0);
 #endif
 
                        ldap_pvt_thread_yield();
index e9c40dcbbc4bb5b721b096f200b0a188869b359c..ac799bb62777791701da86b2cd90c090a076f781 100644 (file)
@@ -31,8 +31,14 @@ bdb_compare(
        const char      *text = NULL;
        int             manageDSAit = get_manageDSAit( op );
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
+       LOCK_ID ( bdb->bi_dbenv, &locker );
+
+dn2entry_retry:
        /* get entry */
-       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
 
        switch( rc ) {
        case DB_NOTFOUND:
@@ -41,6 +47,9 @@ bdb_compare(
        case LDAP_BUSY:
                text = "ldap server busy";
                goto return_results;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
                rc = LDAP_OTHER;
                text = "internal error";
@@ -56,7 +65,7 @@ bdb_compare(
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
                        matched = NULL;
 
                } else {
@@ -125,8 +134,10 @@ return_results:
 done:
        /* free entry */
        if( e != NULL ) {
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
 
+       LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+
        return rc;
 }
index dcaf399fafd07c9abb777f2abc130bf84a00a992..a348631cc73205f4f1564e750ddaf69f75e85d53 100644 (file)
@@ -33,6 +33,9 @@ bdb_delete(
        AttributeDescription *children = slap_schema.si_ad_children;
        DB_TXN          *ltid = NULL;
        struct bdb_op_info opinfo;
+
+       u_int32_t       locker;
+       DB_LOCK         lock;
 #if 0
        u_int32_t       lockid;
        DB_LOCK         lock;
@@ -49,7 +52,7 @@ bdb_delete(
        if( 0 ) {
 retry: /* transaction retry */
                if( e != NULL ) {
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "delete", LDAP_LEVEL_DETAIL1, 
@@ -87,6 +90,8 @@ retry:        /* transaction retry */
                text = "internal error";
                goto return_results;
        }
+
+       locker = TXN_ID ( ltid );
 #if 0
        lockid = TXN_ID( ltid );
 #endif
@@ -111,7 +116,7 @@ retry:      /* transaction retry */
                }
 #endif
                /* get parent */
-               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0 );
+               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0, locker, &lock );
 
                switch( rc ) {
                case 0:
@@ -147,7 +152,7 @@ retry:      /* transaction retry */
                rc = access_allowed( be, conn, op, p,
                        children, NULL, ACL_WRITE, NULL );
 
-               bdb_cache_return_entry_r(&bdb->bi_cache, p);
+               bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
                p = NULL;
 
                switch( opinfo.boi_err ) {
@@ -226,7 +231,7 @@ retry:      /* transaction retry */
        }
 
        /* get entry for read/modify/write */
-       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW );
+       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW, locker, &lock );
 
        switch( rc ) {
        case 0:
@@ -263,7 +268,7 @@ retry:      /* transaction retry */
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched );
+                       bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, matched);
                        matched = NULL;
 
                } else {
@@ -465,7 +470,7 @@ return_results:
 done:
        /* free entry */
        if( e != NULL ) {
-               bdb_cache_return_entry_w(&bdb->bi_cache, e);
+               bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
        }
 
        if( ltid != NULL ) {
index 00cd9efed7cea38446f909fe4af43ce29d6312a1..a6440536f7ebb662761bab2260d71ab522273371 100644 (file)
@@ -25,7 +25,9 @@ bdb_dn2entry_rw(
        Entry **e,
        Entry **matched,
        int flags,
-       int rw )
+       int rw,
+       u_int32_t locker,
+       DB_LOCK *lock )
 {
        int rc;
        ID              id, id2 = 0;
@@ -52,9 +54,9 @@ bdb_dn2entry_rw(
        }
 
        if( id2 == 0 ) {
-               rc = bdb_id2entry_rw( be, tid, id, e, rw );
+               rc = bdb_id2entry_rw( be, tid, id, e, rw, locker, lock );
        } else {
-               rc = bdb_id2entry_r( be, tid, id2, matched);
+               rc = bdb_id2entry_r( be, tid, id2, matched, locker, lock );
        }
 
        return rc;
index bd8adc0bdc8c2deb688b4adf0a0c59f0ee3757c5..a09bc1e3f4b578dcec590e8befcd484512c263a7 100644 (file)
@@ -65,6 +65,10 @@ bdb_filter_candidates(
                Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
 #endif
                rc = bdb_dn2idl( be, f->f_dn, DN_ONE_PREFIX, ids );
+               if( rc == DB_NOTFOUND ) {
+                       BDB_IDL_ZERO( ids );
+                       rc = 0;
+               }
                break;
 
        case SLAPD_FILTER_DN_SUBTREE:
index 2000de520996c7f849c70efc136ce9ac9bd2c2b1..6c2cdf11330a3c7f9035248c16555a65ffa41101 100644 (file)
@@ -44,6 +44,9 @@ bdb_group(
        const char *group_oc_name = NULL;
        const char *group_at_name = group_at->ad_cname.bv_val;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
        if( group_oc->soc_names && group_oc->soc_names[0] ) {
                group_oc_name = group_oc->soc_names[0];
        } else {
@@ -76,6 +79,11 @@ bdb_group(
                txn = boi->boi_txn;
        }
 
+       if ( txn )
+               locker = TXN_ID( txn );
+       else
+               LOCK_ID ( bdb->bi_dbenv, &locker );
+
        if (dn_match(&target->e_name, gr_ndn)) {
                /* we already have a LOCKED copy of the entry */
                e = target;
@@ -88,12 +96,18 @@ bdb_group(
                        gr_ndn->bv_val, 0, 0 );
 #endif
        } else {
+dn2entry_retry:
                /* can we find group entry */
-               rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0 ); 
+               rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0, locker, &lock ); 
                if( rc ) {
+                       if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED )
+                               goto dn2entry_retry;
                        if( txn ) {
                                boi->boi_err = rc;
                        }
+                       else {
+                               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+                       }
                        return( 1 );
                }
                if (e == NULL) {
@@ -106,6 +120,9 @@ bdb_group(
                                "=> bdb_group: cannot find group: \"%s\"\n",
                                        gr_ndn->bv_val, 0, 0 ); 
 #endif
+                       if ( txn == NULL ) {
+                               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+                       }
                        return( 1 );
                }
 #ifdef NEW_LOGGING
@@ -211,7 +228,11 @@ bdb_group(
 return_results:
        if( target != e ) {
                /* free entry */
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
+       }
+
+       if ( txn == NULL ) {
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
        }
 
 #ifdef NEW_LOGGING
index 10ec1637a58aacd6baff8e40cd27354fbedacbc0..0a841cab21e1c7099e740d2ef8e7886d067e8133 100644 (file)
@@ -80,13 +80,15 @@ int bdb_id2entry_rw(
        DB_TXN *tid,
        ID id,
        Entry **e,
-       int rw )
+       int rw,
+       u_int32_t locker,
+       DB_LOCK *lock )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        DB *db = bdb->bi_id2entry->bdi_db;
        DBT key, data;
        struct berval bv;
-       int rc = 0;
+       int rc = 0, ret = 0;
 
        *e = NULL;
 
@@ -97,7 +99,7 @@ int bdb_id2entry_rw(
        DBTzero( &data );
        data.flags = DB_DBT_MALLOC;
 
-       if ((*e = bdb_cache_find_entry_id(&bdb->bi_cache, id, rw)) != NULL) {
+       if ((*e = bdb_cache_find_entry_id(bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock)) != NULL) {
                return 0;
        }
 
@@ -121,24 +123,36 @@ int bdb_id2entry_rw(
                ch_free( data.data );
        }
 
-       while (rc == 0 && bdb_cache_add_entry_rw(&bdb->bi_cache, *e, rw) != 0) {
-               Entry *ee;
-               int add_loop_cnt = 0;
-               if ( (*e)->e_private != NULL ) {
-                       free ((*e)->e_private);
-               }
-               (*e)->e_private = NULL;
-               if ( (ee = bdb_cache_find_entry_id
-                               (&bdb->bi_cache, id, rw) ) != NULL) {
-                       bdb_entry_return ( *e );
-                       *e = ee;
-                       return 0;
+       if ( rc == 0 ) {
+               ret = bdb_cache_add_entry_rw( bdb->bi_dbenv,
+                               &bdb->bi_cache, *e, rw, locker, lock);
+               while ( ret == 1 || ret == -1 ) {
+                       Entry *ee;
+                       int add_loop_cnt = 0;
+                       if ( (*e)->e_private != NULL ) {
+                               free ((*e)->e_private);
+                       }
+                       (*e)->e_private = NULL;
+                       if ( (ee = bdb_cache_find_entry_id
+                                       (bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock) ) != NULL) {
+                               bdb_entry_return ( *e );
+                               *e = ee;
+                               return 0;
+                       }
+                       if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
+                               bdb_entry_return ( *e );
+                               *e = NULL;
+                               return LDAP_BUSY;
+                       }
                }
-               if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
-                       bdb_entry_return ( *e );
+               if ( ret != 0 ) {
+                       if ( (*e)->e_private != NULL )
+                               free ( (*e)->e_private );
+                       bdb_entry_return( *e );
                        *e = NULL;
-                       return LDAP_BUSY;
+                       ch_free( data.data );
                }
+               rc = ret;
        }
 
 #ifdef BDB_HIER
@@ -232,7 +246,7 @@ int bdb_entry_release(
  
        if ( slapMode == SLAP_SERVER_MODE ) {
                /* free entry and reader or writer lock */
-               bdb_cache_return_entry_rw( &bdb->bi_cache, e, rw );
+               bdb_unlocked_cache_return_entry_rw( &bdb->bi_cache, e, rw );
        } else {
                if (e->e_private != NULL)
                        free (e->e_private);
index 9fece09c88f86b7b916666f4f517ae71bebcb31e..d205b60060b3b925e34da6ed69b678309afb62be 100644 (file)
@@ -91,7 +91,6 @@ int bdb_modify_internal(
                        Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: replace\n", 0, 0, 0);
 #endif
                        err = modify_replace_values( e, mod, text, textbuf, textlen );
-                       assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
                        if( err != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG (( "modify", LDAP_LEVEL_ERR, "bdb_modify_internal: %d %s\n", err, *text ));
@@ -250,6 +249,9 @@ bdb_modify(
        DB_TXN  *ltid = NULL;
        struct bdb_op_info opinfo;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "modify", LDAP_LEVEL_ENTRY, "bdb_modify: %s\n", dn->bv_val ));
 #else
@@ -260,7 +262,7 @@ bdb_modify(
 retry: /* transaction retry */
                if( e != NULL ) {
                        bdb_cache_delete_entry(&bdb->bi_cache, e);
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "modify", LDAP_LEVEL_DETAIL1, "bdb_modify: retrying...\n" ));
@@ -296,13 +298,15 @@ retry:    /* transaction retry */
                goto return_results;
        }
 
+       locker = TXN_ID ( ltid );
+
        opinfo.boi_bdb = be;
        opinfo.boi_txn = ltid;
        opinfo.boi_err = 0;
        op->o_private = &opinfo;
 
        /* get entry */
-       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0, locker, &lock );
 
        if ( rc != 0 ) {
 #ifdef NEW_LOGGING
@@ -338,7 +342,7 @@ retry:      /* transaction retry */
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+                       bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, matched);
                        matched = NULL;
 
                } else {
@@ -464,7 +468,7 @@ done:
        }
 
        if( e != NULL ) {
-               bdb_cache_return_entry_w (&bdb->bi_cache, e);
+               bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
        }
        return rc;
 }
index cb1e1517ebb81f3f5bc9377d26152d5af4a8dd69..30f345c7f072ed1193e2aaef51b0eb7c6f647a2c 100644 (file)
@@ -56,6 +56,9 @@ bdb_modrdn(
 
        int             manageDSAit = get_manageDSAit( op );
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "modrdn", LDAP_LEVEL_ENTRY, "==>bdb_modrdn(%s,%s,%s)\n",
                dn->bv_val,newrdn->bv_val,
@@ -78,13 +81,13 @@ bdb_modrdn(
 retry: /* transaction retry */
                if (e != NULL) {
                        bdb_cache_delete_entry(&bdb->bi_cache, e);
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
                }
                if (p != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, p);
+                       bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
                }
                if (np != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, np);
+                       bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "modrdn", LDAP_LEVEL_DETAIL1, "==>bdb_modrdn: retrying...\n"));
@@ -119,13 +122,15 @@ retry:    /* transaction retry */
                goto return_results;
        }
 
+       locker = TXN_ID ( ltid );
+
        opinfo.boi_bdb = be;
        opinfo.boi_txn = ltid;
        opinfo.boi_err = 0;
        op->o_private = &opinfo;
 
        /* get entry */
-       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0, locker, &lock );
 
        switch( rc ) {
        case 0:
@@ -152,7 +157,7 @@ retry:      /* transaction retry */
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+                       bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, matched);
                        matched = NULL;
 
                } else {
@@ -199,7 +204,7 @@ retry:      /* transaction retry */
                /* Make sure parent entry exist and we can write its 
                 * children.
                 */
-               rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0 );
+               rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0, locker, &lock );
 
                switch( rc ) {
                case 0:
@@ -348,7 +353,7 @@ retry:      /* transaction retry */
                        /* newSuperior == entry being moved?, if so ==> ERROR */
                        /* Get Entry with dn=newSuperior. Does newSuperior exist? */
 
-                       rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0 );
+                       rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0, locker, &lock );
 
                        switch( rc ) {
                        case 0:
@@ -855,17 +860,17 @@ done:
        /* LDAP v3 Support */
        if( np != NULL ) {
                /* free new parent and reader lock */
-               bdb_cache_return_entry_r(&bdb->bi_cache, np);
+               bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
        }
 
        if( p != NULL ) {
                /* free parent and reader lock */
-               bdb_cache_return_entry_r(&bdb->bi_cache, p);
+               bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
        }
 
        /* free entry */
        if( e != NULL ) {
-               bdb_cache_return_entry_w( &bdb->bi_cache, e );
+               bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
        }
 
        if( ltid != NULL ) {
index 08172b8c2d173278de42aa9669ca1114285caf58..5278c23ba3baa83ca6ed59a29f9a81223b903eab 100644 (file)
@@ -44,9 +44,11 @@ bdb_operational(
 
        if( 0 ) {
 retry: /* transaction retry */
+#if 0
                if( e != NULL ) {
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
                }
+#endif
 #ifdef NEW_LOGGING
                LDAP_LOG (( "operational", LDAP_LEVEL_DETAIL1,
                        "=> bdb_operational: retrying...\n" ));
index 0e05443926b91970ecebf9e9b951c6c76ed4cb32..25f0c654ed7513a2184c6684b29b49dc0af7abc9 100644 (file)
@@ -41,6 +41,9 @@ bdb_exop_passwd(
        struct berval dn;
        struct berval ndn;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
        assert( reqoid != NULL );
        assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
 
@@ -109,7 +112,7 @@ bdb_exop_passwd(
 retry: /* transaction retry */
                if ( e != NULL ) {
                        bdb_cache_delete_entry(&bdb->bi_cache, e);
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "passwd", LDAP_LEVEL_DETAIL1, "bdb_exop_passwd: retrying...\n" ));
@@ -144,13 +147,15 @@ retry:    /* transaction retry */
                goto done;
        }
 
+       locker = TXN_ID ( ltid );
+
        opinfo.boi_bdb = be;
        opinfo.boi_txn = ltid;
        opinfo.boi_err = 0;
        op->o_private = &opinfo;
 
        /* get entry */
-       rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 );
+       rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 , locker, &lock);
 
        switch(rc) {
        case DB_LOCK_DEADLOCK:
@@ -256,7 +261,7 @@ retry:      /* transaction retry */
 
 done:
        if( e != NULL ) {
-               bdb_cache_return_entry_w( &bdb->bi_cache, e );
+               bdb_cache_return_entry_w( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
                
        if( hash.bv_val != NULL ) {
index cdea9803e190411fc29f2d066bf0051eca884bc4..f5c7af92fd366317f5c380ea9e4a9ece9c14d031 100644 (file)
@@ -58,9 +58,9 @@ bdb_db_cache(
  * dn2entry.c
  */
 int bdb_dn2entry_rw LDAP_P(( BackendDB *be, DB_TXN *tid,
-       struct berval *dn, Entry **e, Entry **matched, int flags, int rw ));
-#define bdb_dn2entry_r(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0)
-#define bdb_dn2entry_w(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1)
+       struct berval *dn, Entry **e, Entry **matched, int flags, int rw , u_int32_t locker, DB_LOCK *lock));
+#define bdb_dn2entry_r(be, tid, dn, e, m, f, locker, lock) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0, locker, lock)
+#define bdb_dn2entry_w(be, tid, dn, e, m, f, locker, lock) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1, locker, lock)
 
 /*
  * dn2id.c
@@ -152,9 +152,11 @@ int bdb_id2entry_rw(
        DB_TXN *tid,
        ID id,
        Entry **e,
-       int rw );
-#define bdb_id2entry_r(be, tid, id, e)      bdb_id2entry_rw((be), (tid), (id), (e), 0)
-#define bdb_id2entry_w(be, tid, id, e)      bdb_id2entry_rw((be), (tid), (id), (e), 1)
+       int rw,
+       u_int32_t locker,
+       DB_LOCK *lock );
+#define bdb_id2entry_r(be, tid, id, e, locker, lock)      bdb_id2entry_rw((be), (tid), (id), (e), 0, locker, lock)
+#define bdb_id2entry_w(be, tid, id, e, locker, lock)      bdb_id2entry_rw((be), (tid), (id), (e), 1, locker, lock)
 
 void bdb_entry_free ( Entry *e );
 
@@ -301,13 +303,19 @@ BI_op_extended bdb_exop_passwd;
  */
 
 void bdb_cache_entry_commit( Entry *e );
-void bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
-#define bdb_cache_return_entry_r(c, e) bdb_cache_return_entry_rw((c), (e), 0)
-#define bdb_cache_return_entry_w(c, e) bdb_cache_return_entry_rw((c), (e), 1)
+void bdb_cache_return_entry_rw( DB_ENV *env, Cache *cache, Entry *e, int rw, DB_LOCK *lock );
+#define bdb_cache_return_entry_r(env, c, e, l) bdb_cache_return_entry_rw((env), (c), (e), 0, (l))
+#define bdb_cache_return_entry_w(env, c, e, l) bdb_cache_return_entry_rw((env), (c), (e), 1, (l))
+void bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
+#define bdb_unlocked_cache_return_entry_r( c, e ) bdb_unlocked_cache_return_entry_rw((c), (e), 0)
+#define bdb_unlocked_cache_return_entry_w( c, e ) bdb_unlocked_cache_return_entry_rw((c), (e), 1)
 int bdb_cache_add_entry_rw(
-       Cache   *cache,
-       Entry   *e,
-       int     rw
+       DB_ENV  *env,
+       Cache   *cache,
+       Entry   *e,
+       int     rw,
+       u_int32_t locker,
+       DB_LOCK *lock
 );
 int bdb_cache_update_entry(
        Cache   *cache,
@@ -319,9 +327,12 @@ ID bdb_cache_find_entry_ndn2id(
        struct berval   *ndn
 );
 Entry* bdb_cache_find_entry_id(
-       Cache   *cache,
-       ID      id,
-       int     rw
+       DB_ENV          *env,
+       Cache           *cache,
+       ID              id,
+       int             rw,
+       u_int32_t       locker,
+       DB_LOCK         *lock
 );
 int bdb_cache_delete_entry(
        Cache   *cache,
index 3517492c7945b8c24374ec5a254258689bab207d..4d60f68d0e83030029b78329c7c41b3424ea4b3f 100644 (file)
@@ -26,6 +26,9 @@ bdb_referrals(
        Entry *e = NULL;
        Entry *matched = NULL;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
        if( op->o_tag == LDAP_REQ_SEARCH ) {
                /* let search take care of itself */
                return rc;
@@ -36,8 +39,11 @@ bdb_referrals(
                return rc;
        } 
 
+       LOCK_ID ( bdb->bi_dbenv, &locker );
+
+dn2entry_retry:
        /* get entry */
-       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
 
        switch(rc) {
        case DB_NOTFOUND:
@@ -46,14 +52,18 @@ bdb_referrals(
                break;
        case LDAP_BUSY:
                if (e != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (matched != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
                return LDAP_BUSY;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
 #ifdef NEW_LOGGING
                LDAP_LOG (( "referral", LDAP_LEVEL_ERR,
@@ -65,13 +75,14 @@ bdb_referrals(
                        db_strerror(rc), rc, 0 ); 
 #endif
                if (e != NULL) {
-                        bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                        bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                 if (matched != NULL) {
-                        bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                        bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
                return rc;
        }
 
@@ -97,7 +108,7 @@ bdb_referrals(
                                refs = get_entry_referrals( be, conn, op, matched );
                        }
 
-                       bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                        matched = NULL;
                } else if ( default_referral != NULL ) {
                        rc = LDAP_OTHER;
@@ -116,6 +127,7 @@ bdb_referrals(
                                NULL, NULL );
                }
 
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
                free( matched_dn );
                return rc;
        }
@@ -148,6 +160,7 @@ bdb_referrals(
                ber_bvarray_free( refs );
        }
 
-       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
+       LOCK_ID_FREE ( bdb->bi_dbenv, locker );
        return rc;
 }
index 9887feb342c6515c777c11af87c1e1cb0a8d31c0..a68e17fb646e90400b4058bb1f660c30aea5f04b 100644 (file)
@@ -59,6 +59,9 @@ bdb_search(
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "search", LDAP_LEVEL_ENTRY,"bdb_back_search\n"));
 #else
@@ -68,6 +71,8 @@ bdb_search(
 
        manageDSAit = get_manageDSAit( op );
 
+       LOCK_ID (bdb->bi_dbenv, &locker );
+
        if ( nbase->bv_len == 0 ) {
                /* DIT root special case */
                e = (Entry *) &slap_entry_root;
@@ -81,7 +86,8 @@ bdb_search(
        } else
 #endif
        {
-               rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0 );
+dn2entry_retry:
+               rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0, locker, &lock );
        }
 
        switch(rc) {
@@ -90,23 +96,28 @@ bdb_search(
                break;
        case LDAP_BUSY:
                if (e != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (matched != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                return LDAP_BUSY;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
                if (e != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (matched != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                return rc;
        }
 
@@ -116,14 +127,13 @@ bdb_search(
 
                if ( matched != NULL ) {
                        BerVarray erefs;
-
                        ber_dupbv( &matched_dn, &matched->e_name );
 
                        erefs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
 
-                       bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                        matched = NULL;
 
                        if( erefs ) {
@@ -140,6 +150,7 @@ bdb_search(
                send_ldap_result( conn, op,     rc=LDAP_REFERRAL ,
                        matched_dn.bv_val, text, refs, NULL );
 
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                if ( refs ) ber_bvarray_free( refs );
                if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
                return rc;
@@ -154,7 +165,7 @@ bdb_search(
                erefs = get_entry_referrals( be, conn, op, e );
                refs = NULL;
 
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
                e = NULL;
 
                if( erefs ) {
@@ -175,6 +186,7 @@ bdb_search(
                        refs ? NULL : "bad referral object",
                        refs, NULL );
 
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                ber_bvarray_free( refs );
                ber_memfree( matched_dn.bv_val );
                return 1;
@@ -270,7 +282,7 @@ bdb_search(
        cursor = e->e_id == NOID ? 1 : e->e_id;
 
        if ( e != &slap_entry_root ) {
-               bdb_cache_return_entry_r(&bdb->bi_cache, e);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
        }
        e = NULL;
 
@@ -320,13 +332,17 @@ bdb_search(
                        goto done;
                }
 
+id2entry_retry:
                /* get the entry with reader lock */
-               rc = bdb_id2entry_r( be, NULL, id, &e );
+               rc = bdb_id2entry_r( be, NULL, id, &e, locker, &lock );
 
                if (rc == LDAP_BUSY) {
                        send_ldap_result( conn, op, rc=LDAP_BUSY,
                                NULL, "ldap server busy", NULL, NULL );
                        goto done;
+
+               } else if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) {
+                       goto id2entry_retry;    
                }
 
                if ( e == NULL ) {
@@ -416,18 +432,49 @@ bdb_search(
                if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
                        is_entry_referral( e ) )
                {
-                       BerVarray erefs = get_entry_referrals(
-                               be, conn, op, e );
-                       BerVarray refs = referral_rewrite( erefs,
-                               &e->e_name, NULL,
-                               scope == LDAP_SCOPE_SUBTREE 
-                                       ? LDAP_SCOPE_SUBTREE
-                                       : LDAP_SCOPE_BASE );
+                       struct berval   dn;
 
-                       send_search_reference( be, conn, op,
-                               e, refs, NULL, &v2refs );
+                       /* check scope */
+                       if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+                               if ( !be_issuffix( be, &e->e_nname ) ) {
+                                       dnParent( &e->e_nname, &dn );
+                                       scopeok = dn_match( &dn, &realbase );
+                               } else {
+                                       scopeok = (realbase.bv_len == 0);
+                               }
 
-                       ber_bvarray_free( refs );
+                       } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+                               scopeok = dnIsSuffix( &e->e_nname, &realbase );
+
+                       } else {
+                               scopeok = 1;
+                       }
+
+                       if( scopeok ) {
+                               BerVarray erefs = get_entry_referrals(
+                                       be, conn, op, e );
+                               BerVarray refs = referral_rewrite( erefs,
+                                       &e->e_name, NULL,
+                                       scope == LDAP_SCOPE_SUBTREE
+                                               ? LDAP_SCOPE_SUBTREE
+                                               : LDAP_SCOPE_BASE );
+
+                               send_search_reference( be, conn, op,
+                                       e, refs, NULL, &v2refs );
+
+                               ber_bvarray_free( refs );
+
+                       } else {
+#ifdef NEW_LOGGING
+                               LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL2,
+                                       "bdb_search: candidate referral %ld scope not okay\n",
+                                       id ));
+#else
+                               Debug( LDAP_DEBUG_TRACE,
+                                       "bdb_search: candidate referral %ld scope not okay\n",
+                                       id, 0, 0 );
+#endif
+                       }
 
                        goto loop_continue;
                }
@@ -456,7 +503,7 @@ bdb_search(
                        if ( scopeok ) {
                                /* check size limit */
                                if ( --slimit == -1 ) {
-                                       bdb_cache_return_entry_r (&bdb->bi_cache, e);
+                                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                                        e = NULL;
                                        send_search_result( conn, op,
                                                rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
@@ -481,7 +528,7 @@ bdb_search(
                                        case 1:         /* entry not sent */
                                                break;
                                        case -1:        /* connection closed */
-                                               bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                                               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                                                e = NULL;
                                                rc = LDAP_OTHER;
                                                goto done;
@@ -509,7 +556,7 @@ bdb_search(
 loop_continue:
                if( e != NULL ) {
                        /* free reader lock */
-                        bdb_cache_return_entry_r ( &bdb->bi_cache, e );
+                        bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e , &lock);
                         e = NULL;
                }
 
@@ -524,9 +571,11 @@ loop_continue:
 done:
        if( e != NULL ) {
                /* free reader lock */
-               bdb_cache_return_entry_r ( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
 
+       LOCK_ID_FREE (bdb->bi_dbenv, locker );
+
        if( v2refs ) ber_bvarray_free( v2refs );
        if( realbase.bv_val ) ch_free( realbase.bv_val );
 
index 3dc4cdbcf1baff1e096801430229fbf0868d2233..137734c104b8d3a3d2fb8557cd4d137c911d21e1 100644 (file)
@@ -490,13 +490,15 @@ static int slap_get_listener_addresses(
 
                freeaddrinfo(res);
 #else
+               int i, n = 1;
                struct in_addr in;
+               struct hostent *he = NULL;
 
                if ( host == NULL ) {
                        in.s_addr = htonl(INADDR_ANY);
 
                } else if ( !inet_aton( host, &in ) ) {
-                       struct hostent *he = gethostbyname( host );
+                       he = gethostbyname( host );
                        if( he == NULL ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
@@ -508,25 +510,30 @@ static int slap_get_listener_addresses(
 #endif
                                return -1;
                        }
-                       AC_MEMCPY( &in, he->h_addr, sizeof( in ) );
+                       for (n = 0; he->h_addr_list[n]; n++) ;
                }
 
-               *sal = ch_malloc(2 * sizeof(void *));
+               *sal = ch_malloc((n+1) * sizeof(void *));
                if (*sal == NULL) {
                        return -1;
                }
 
                sap = *sal;
-               *sap = ch_malloc(sizeof(struct sockaddr_in));
-               if (*sap == NULL) {
-                       goto errexit;
+               for ( i = 0; i<n; i++ ) {
+                       sap[i] = ch_malloc(sizeof(struct sockaddr_in));
+                       if (*sap == NULL) {
+                               goto errexit;
+                       }
+                       (void)memset( (void *)sap[i], '\0', sizeof(struct sockaddr_in) );
+                       sap[i]->sa_family = AF_INET;
+                       ((struct sockaddr_in *)sap[i])->sin_port = htons(port);
+                       if (he) {
+                               AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, he->h_addr_list[i], sizeof(struct in_addr) );
+                       } else {
+                               AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, &in, sizeof(struct in_addr) );
+                       }
                }
-               sap[1] = NULL;
-
-               (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_in) );
-               (*sap)->sa_family = AF_INET;
-               ((struct sockaddr_in *)*sap)->sin_port = htons(port);
-               ((struct sockaddr_in *)*sap)->sin_addr = in;
+               sap[i] = NULL;
 #endif
        }
 
@@ -537,10 +544,13 @@ errexit:
        return -1;
 }
 
-static Listener * slap_open_listener(
-       const char* url )
+static int slap_open_listener(
+       const char* url,
+       int *listeners,
+       int *cur
+       )
 {
-       int     tmp, rc;
+       int     num, tmp, rc;
        Listener l;
        Listener *li;
        LDAPURLDesc *lud;
@@ -565,7 +575,7 @@ static Listener * slap_open_listener(
                        "daemon: listen URL \"%s\" parse error=%d\n",
                        url, rc, 0 );
 #endif
-               return NULL;
+               return rc;
        }
 
 #ifndef HAVE_TLS
@@ -580,7 +590,7 @@ static Listener * slap_open_listener(
                        url, 0, 0 );
 #endif
                ldap_free_urldesc( lud );
-               return NULL;
+               return -1;
        }
 
        if(! lud->lud_port ) {
@@ -620,7 +630,7 @@ static Listener * slap_open_listener(
                        url, 0, 0);
 #endif
                ldap_free_urldesc( lud );
-               return NULL;
+               return -1;
 #endif
        } else {
 #ifdef LDAP_CONNECTIONLESS
@@ -637,7 +647,16 @@ static Listener * slap_open_listener(
 
        ldap_free_urldesc( lud );
        if ( err ) {
-               return NULL;
+               return -1;
+       }
+
+       /* If we got more than one address returned, we need to make space
+        * for it in the slap_listeners array.
+        */
+       for ( num=0; sal[num]; num++ );
+       if ( num > 1 ) {
+               *listeners += num-1;
+               slap_listeners = ch_realloc( slap_listeners, (*listeners + 1) * sizeof(Listener *) );
        }
 
        psal = sal;
@@ -732,9 +751,8 @@ static Listener * slap_open_listener(
 #endif
                }
 
-               if (!bind(l.sl_sd, *sal, addrlen))
-                       break;
-               err = sock_errno();
+               if (bind(l.sl_sd, *sal, addrlen)) {
+                       err = sock_errno();
 #ifdef NEW_LOGGING
                LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
                           "slap_open_listener: bind(%ld) failed errno=%d (%s)\n",
@@ -743,21 +761,10 @@ static Listener * slap_open_listener(
                Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
                       (long) l.sl_sd, err, sock_errstr(err) );
 #endif
-               tcp_close( l.sl_sd );
-               sal++;
-       } /* while ( *sal != NULL ) */
-
-       if ( *sal == NULL ) {
-#ifdef NEW_LOGGING
-               LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
-                          "slap_open_listener: bind(%ld) failed.\n", (long)l.sl_sd ));
-#else
-               Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed\n",
-                       (long) l.sl_sd, 0, 0 );
-#endif
-               slap_free_listener_addresses(psal);
-               return NULL;
-       }
+                       tcp_close( l.sl_sd );
+                       sal++;
+                       continue;
+               }
 
        switch ( (*sal)->sa_family ) {
 #ifdef LDAP_PF_LOCAL
@@ -775,7 +782,7 @@ static Listener * slap_open_listener(
 #endif
                        tcp_close( l.sl_sd );
                        slap_free_listener_addresses(psal);
-                       return NULL;
+                       return -1;
                }
                l.sl_name = ch_malloc( strlen(addr) + sizeof("PATH=") );
                sprintf( l.sl_name, "PATH=%s", addr );
@@ -821,20 +828,27 @@ static Listener * slap_open_listener(
                break;
        }
 
-       slap_free_listener_addresses(psal);
-
+       AC_MEMCPY(&l.sl_sa, *sal, addrlen);
        l.sl_url = ch_strdup( url );
        li = ch_malloc( sizeof( Listener ) );
        *li = l;
+       slap_listeners[*cur] = li;
+       (*cur)++;
+       sal++;
+
+       } /* while ( *sal != NULL ) */
+
+       slap_free_listener_addresses(psal);
+
 
 #ifdef NEW_LOGGING
        LDAP_LOG(( "connection", LDAP_LEVEL_RESULTS,
-                  "slap_open_listener: daemon initialzed %s\n", l.sl_url ));
+                  "slap_open_listener: daemon initialized %s\n", l.sl_url ));
 #else
        Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
                l.sl_url, 0, 0 );
 #endif
-       return li;
+       return 0;
 }
 
 static int sockinit(void);
@@ -842,7 +856,7 @@ static int sockdestroy(void);
 
 int slapd_daemon_init( const char *urls )
 {
-       int i, rc;
+       int i, j, n, rc;
        char **u;
 
 #ifdef NEW_LOGGING
@@ -938,15 +952,13 @@ int slapd_daemon_init( const char *urls )
 #endif
        slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
 
-       for(i = 0; u[i] != NULL; i++ ) {
-               slap_listeners[i] = slap_open_listener( u[i] );
-
-               if( slap_listeners[i] == NULL ) {
+       for(n = 0, j = 0; u[n]; n++ ) {
+               if ( slap_open_listener( u[n], &i, &j ) ) {
                        charray_free( u );
                        return -1;
                }
        }
-       slap_listeners[i] = NULL;
+       slap_listeners[j] = NULL;
 
 #ifdef NEW_LOGGING
        LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
index 1437f35cc4279e7dcde36f81f143bb0a8752305b..a4b02c75bd730eb2011c75cc7dca46db56a35fdf 100644 (file)
@@ -579,6 +579,8 @@ struct slap_internal_schema {
        AttributeDescription *si_ad_modifyTimestamp;
        AttributeDescription *si_ad_hasSubordinates;
        AttributeDescription *si_ad_subschemaSubentry;
+       AttributeDescription *si_ad_entryUUID;
+       AttributeDescription *si_ad_entryCSN;
 
        /* root DSE attribute descriptions */
        AttributeDescription *si_ad_altServer;