" 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"
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 ];
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 */
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 ) {
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 );
ldap_perror( ld, "ldap_bind" );
return( EXIT_FAILURE );
}
+
}
}
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 );
}
ldap_unbind( ld );
}
+ if ( rejfp != NULL ) {
+ fclose( rejfp );
+ }
+
return( rc );
}
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
-.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
.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
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
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
(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.
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)
.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
-
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
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:
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:
.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.
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 )))
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;
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;
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 );
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
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,
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,
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
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",
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
int msgid;
struct berval bvalue;
+ assert( value != NULL );
+
bvalue.bv_val = (char *) value;
bvalue.bv_len = (value == NULL) ? 0 : strlen( value );
{
struct berval bvalue;
+ assert( value != NULL );
+
bvalue.bv_val = (char *) value;
bvalue.bv_len = (value == NULL) ? 0 : strlen( value );
LDAPControl *const *c;
assert( ld != NULL );
+ assert( LDAP_VALID(ld) );
assert( ber != NULL );
if( ctrls == NULL ) {
struct berval *bvalp;
assert( requestOID != NULL );
+ assert( ber != NULL );
assert( ctrlp != NULL );
ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
LDAPControl *const *c;
assert( ld != NULL );
+ assert( LDAP_VALID(ld) );
if( ctrls == NULL ) {
/* use default server controls */
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 ) {
#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;
}
#endif
lc->lconn_sasl_ctx = ctx;
- lc->lconn_sasl_cbs = session_callbacks;
if( ssf ) {
#if SASL_VERSION_MAJOR >= 2
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;
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 );
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;
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 );
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 )
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++;
#endif
#ifdef HAVE_CYRUS_SASL
void *lconn_sasl_ctx;
- void *lconn_sasl_cbs;
#endif
int lconn_refcnt;
time_t lconn_lastused; /* time */
--- /dev/null
+/* $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 );
+}
{
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
- assert( chain != NULL );
+ assert( chain != NULL );
return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE
? chain
{
assert( ld != NULL );
assert( LDAP_VALID( ld ) );
- assert( ref != NULL );
+ assert( ref != NULL );
for (
ref = ref->lm_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++;
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;
#ifdef BDB_SUBENTRIES
int subentry;
#endif
+ u_int32_t locker;
+ DB_LOCK lock;
#if 0
u_int32_t lockid;
DB_LOCK lock;
text = "internal error";
goto return_results;
}
+
+ locker = TXN_ID ( ltid );
#if 0
lockid = TXN_ID( ltid );
#endif
#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:
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 {
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;
}
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;
}
#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 {
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 {
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 ));
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;
} 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) {
"=> 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;
}
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
#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
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:
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;
}
? 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 {
NULL, NULL, NULL, NULL );
}
+ LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
ber_bvarray_free( refs );
free( matched_dn );
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;
}
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.
}
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;
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;
* 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;
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 */
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;
}
/* 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.
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();
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:
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";
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 {
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;
}
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;
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,
text = "internal error";
goto return_results;
}
+
+ locker = TXN_ID ( ltid );
#if 0
lockid = TXN_ID( ltid );
#endif
}
#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:
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 ) {
}
/* 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:
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 {
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 ) {
Entry **e,
Entry **matched,
int flags,
- int rw )
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock )
{
int rc;
ID id, id2 = 0;
}
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;
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:
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 {
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;
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) {
"=> 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
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
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;
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;
}
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
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);
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 ));
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
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" ));
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
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 {
}
if( e != NULL ) {
- bdb_cache_return_entry_w (&bdb->bi_cache, e);
+ bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
}
return rc;
}
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,
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"));
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:
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 {
/* 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:
/* 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:
/* 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 ) {
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" ));
struct berval dn;
struct berval ndn;
+ u_int32_t locker;
+ DB_LOCK lock;
+
assert( reqoid != NULL );
assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
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" ));
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:
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 ) {
* 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
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 );
*/
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,
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,
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;
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:
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,
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;
}
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;
NULL, NULL );
}
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
free( matched_dn );
return rc;
}
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;
}
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
manageDSAit = get_manageDSAit( op );
+ LOCK_ID (bdb->bi_dbenv, &locker );
+
if ( nbase->bv_len == 0 ) {
/* DIT root special case */
e = (Entry *) &slap_entry_root;
} 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) {
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;
}
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 ) {
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;
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 ) {
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;
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;
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 ) {
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;
}
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,
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;
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;
}
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 );
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,
#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
}
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;
"daemon: listen URL \"%s\" parse error=%d\n",
url, rc, 0 );
#endif
- return NULL;
+ return rc;
}
#ifndef HAVE_TLS
url, 0, 0 );
#endif
ldap_free_urldesc( lud );
- return NULL;
+ return -1;
}
if(! lud->lud_port ) {
url, 0, 0);
#endif
ldap_free_urldesc( lud );
- return NULL;
+ return -1;
#endif
} else {
#ifdef LDAP_CONNECTIONLESS
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;
#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",
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
#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 );
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);
int slapd_daemon_init( const char *urls )
{
- int i, rc;
+ int i, j, n, rc;
char **u;
#ifdef NEW_LOGGING
#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,
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;