}
if (0) {
+ /* transaction retry */
retry: rc = txn_abort( ltid );
ltid = NULL;
op->o_private = NULL;
ch_free( pdn );
switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb_add: id2entry_add failed\n",
0, 0, 0 );
- rc = LDAP_OTHER;
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ }
text = "entry store failed";
goto return_results;
}
if ( index_entry_add( be, e, e->e_attrs ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "bdb_add: index_entry_add failed\n",
0, 0, 0 );
- rc = LDAP_OTHER;
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ }
text = "index generation failed";
goto return_results;
}
#define DEFAULT_MODE 0600
+#define BDB_TXN_RETRIES 16
+
#define BDB_DBENV_HOME LDAP_RUNDIR LDAP_DIRSEP "openldap-bdb"
#define BDB_TMP_SUBDIR LDAP_DIRSEP "tmp"
# End Source File
# Begin Source File
+SOURCE=.\compare.c
+# End Source File
+# Begin Source File
+
SOURCE=.\delete.c
# End Source File
# Begin Source File
--- /dev/null
+/* compare.c - bdb backend compare routine */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include "back-bdb.h"
+
+int
+bdb_compare(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ const char *dn,
+ const char *ndn,
+ AttributeAssertion *ava
+)
+{
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ Entry *matched;
+ Entry *e;
+ Attribute *a;
+ int rc;
+ const char *text = NULL;
+ int manageDSAit = get_manageDSAit( op );
+
+ /* get entry */
+ rc = dn2entry_r( be, NULL, ndn, &e, &matched );
+
+ switch( rc ) {
+ case DB_NOTFOUND:
+ break;
+ default:
+ rc = LDAP_OTHER;
+ text = "internal error";
+ goto return_results;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb_entry_return( be, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ goto done;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ goto done;
+ }
+
+ if ( ! access_allowed( be, conn, op, e,
+ ava->aa_desc, ava->aa_value, ACL_COMPARE ) )
+ {
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto return_results;
+ }
+
+ rc = LDAP_NO_SUCH_ATTRIBUTE;
+
+ for(a = attrs_find( e->e_attrs, ava->aa_desc );
+ a != NULL;
+ a = attrs_find( a->a_next, ava->aa_desc ))
+ {
+ rc = LDAP_COMPARE_FALSE;
+
+ if ( value_find( ava->aa_desc, a->a_vals, ava->aa_value ) == 0 )
+ {
+ rc = LDAP_COMPARE_TRUE;
+ break;
+ }
+
+ }
+
+ if( rc != LDAP_NO_SUCH_ATTRIBUTE ) {
+ rc = LDAP_SUCCESS;
+ }
+
+
+return_results:
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, text, NULL, NULL );
+
+done:
+ /* free entry */
+ if( e != NULL ) bdb_entry_return( be, e );
+
+ return rc;
+}
\ No newline at end of file
Debug(LDAP_DEBUG_ARGS, "==> bdb_delete: %s\n", dn, 0, 0);
if (0) {
+ /* transaction retry */
retry: rc = txn_abort( ltid );
ltid = NULL;
op->o_private = NULL;
ch_free( pdn );
switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
rc = dn2entry_w( be, ltid, ndn, &e, &matched );
switch( rc ) {
+ case 0:
+ case DB_NOTFOUND:
+ break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
goto done;
}
-
- if ( bdb_has_children( be, e ) ) {
- Debug(LDAP_DEBUG_ARGS,
- "<=- bdb_delete: non leaf %s\n",
- dn, 0, 0);
- rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
- text = "subtree delete not supported";
+ rc = bdb_dn2id_children( be, ltid, e->e_ndn );
+ if( rc != DB_NOTFOUND ) {
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ case 0:
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb_delete: non-leaf %s\n",
+ dn, 0, 0);
+ rc = LDAP_NOT_ALLOWED_ON_NONLEAF;
+ text = "subtree delete not supported";
+ break;
+ default:
+ Debug(LDAP_DEBUG_ARGS,
+ "<=- bdb_delete: has_children failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
+ rc = LDAP_OTHER;
+ text = "internal error";
+ }
goto return_results;
}
- /* delete from dn2id mapping */
- if ( bdb_dn2id_delete( be, e->e_ndn, e->e_id ) != 0 ) {
+ /* delete from dn2id */
+ rc = bdb_dn2id_delete( be, ltid, e->e_ndn, e->e_id );
+ if ( rc != 0 ) {
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ }
Debug(LDAP_DEBUG_ARGS,
- "<=- ldbm_back_delete: operations error %s\n",
- dn, 0, 0);
- rc = LDAP_OTHER;
+ "<=- bdb_delete: dn2id failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
text = "DN index delete failed";
goto return_results;
}
- /* delete from disk and cache */
- if ( bdb_id2entry_delete( be, e ) != 0 ) {
+ /* delete from id2entry */
+ if ( bdb_id2entry_delete( be, ltid, e->e_id ) != 0 ) {
+ switch( rc ) {
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ rc = LDAP_OTHER;
+ }
Debug(LDAP_DEBUG_ARGS,
- "<=- bdb_delete: operations error %s\n",
- dn, 0, 0);
- rc = LDAP_OTHER;
+ "<=- bdb_delete: id2entry failed: %s (%d)\n",
+ db_strerror(rc), rc, 0 );
text = "entry delete failed";
goto return_results;
}
db_strerror(rc), rc, 0 );
rc = LDAP_OTHER;
text = "commit failed";
+
} else {
Debug( LDAP_DEBUG_TRACE,
"bdb_add: added id=%08x dn=\"%s\"\n",
NULL, text, NULL, NULL );
done:
- /* free entry and writer lock */
- bdb_entry_return( be, e );
+ /* free entry */
+ if( e != NULL ) bdb_entry_return( be, e );
if( ltid != NULL ) {
txn_abort( ltid );
#include "portable.h"
#include <stdio.h>
-
#include <ac/string.h>
-#include <ac/socket.h>
#include "back-bdb.h"
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
- Debug( LDAP_DEBUG_TRACE, "=> bdb_index_dn_add( \"%s\", %ld )\n", dn, id, 0 );
+ Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
assert( id != NOID );
DBTzero( &key );
done:
ch_free( key.data );
- Debug( LDAP_DEBUG_TRACE, "<= bdb_index_dn_add %d\n", rc, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add %d\n", rc, 0, 0 );
+ return rc;
+}
+
+int
+bdb_dn2id_delete(
+ Backend *be,
+ DB_TXN *txn,
+ const char *dn,
+ ID id
+)
+{
+ int rc;
+ DBT key;
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ DB *db = bdb->bi_dn2id->bdi_db;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", %ld )\n", dn, id, 0 );
+ assert( id != NOID );
+
+ DBTzero( &key );
+ key.size = strlen( dn ) + 2;
+ key.data = ch_malloc( key.size );
+ ((char *)key.data)[0] = DN_BASE_PREFIX;
+ AC_MEMCPY( &((char *)key.data)[1], dn, key.size - 1 );
+
+ /* store it -- don't override */
+ rc = db->del( db, txn, &key, 0 );
+ if( rc != 0 ) {
+ goto done;
+ }
+
+ {
+ char *pdn = dn_parent( NULL, dn );
+ ((char *)(key.data))[0] = DN_ONE_PREFIX;
+
+ if( pdn != NULL ) {
+ key.size = strlen( pdn ) + 2;
+ AC_MEMCPY( &((char*)key.data)[1],
+ pdn, key.size - 1 );
+
+ rc = bdb_idl_delete_key( be, db, txn, &key, id );
+ free( pdn );
+
+ if( rc != 0 ) {
+ goto done;
+ }
+ }
+ }
+
+ {
+ char **subtree = dn_subtree( NULL, dn );
+
+ if( subtree != NULL ) {
+ int i;
+ ((char *)key.data)[0] = DN_SUBTREE_PREFIX;
+ for( i=0; subtree[i] != NULL; i++ ) {
+ key.size = strlen( subtree[i] ) + 2;
+ AC_MEMCPY( &((char *)key.data)[1],
+ subtree[i], key.size - 1 );
+
+ rc = bdb_idl_delete_key( be, db, txn, &key, id );
+
+ if( rc != 0 ) {
+ goto done;
+ }
+ }
+
+ charray_free( subtree );
+ }
+ }
+
+done:
+ ch_free( key.data );
+ Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete %d\n", rc, 0, 0 );
+ return rc;
+}
+
+int
+bdb_dn2id_children(
+ Backend *be,
+ DB_TXN *txn,
+ const char *dn
+)
+{
+ int rc;
+ DBT key, data;
+ struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+ DB *db = bdb->bi_dn2id->bdi_db;
+ ID id;
+
+ Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_children( %s )\n",
+ dn, 0, 0 );
+
+ DBTzero( &key );
+ key.size = strlen( dn ) + 2;
+ key.data = ch_malloc( key.size );
+ ((char *)key.data)[0] = DN_ONE_PREFIX;
+ AC_MEMCPY( &((char *)key.data)[1], dn, key.size - 1 );
+
+ /* we actually could do a empty get... */
+ DBTzero( &data );
+ data.data = &id;
+ data.ulen = sizeof(id);
+ data.flags = DB_DBT_USERMEM;
+ data.doff = 0;
+ data.dlen = sizeof(id);
+
+ rc = db->get( db, txn, &key, &data, 0 );
+
+ Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children( %s ): %s (%d)\n",
+ dn,
+ rc == 0 ? "yes" : ( rc == DB_NOTFOUND ? "no" :
+ db_strerror(rc) ), rc );
+
return rc;
}
}
-int
-dn2id_delete(
- Backend *be,
- const char *dn,
- ID id
-)
-{
- DBCache *db;
- Datum key;
- int rc;
-
- Debug( LDAP_DEBUG_TRACE, "=> dn2id_delete( \"%s\", %ld )\n", dn, id, 0 );
-
- assert( id != NOID );
-
- if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
- == NULL ) {
- Debug( LDAP_DEBUG_ANY,
- "<= dn2id_delete could not open dn2id%s\n", LDBM_SUFFIX,
- 0, 0 );
- return( -1 );
- }
-
-
- {
- char *pdn = dn_parent( NULL, dn );
-
- if( pdn != NULL ) {
- ldbm_datum_init( key );
- key.dsize = strlen( pdn ) + 2;
- key.dptr = ch_malloc( key.dsize );
- sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn );
-
- (void) idl_delete_key( be, db, key, id );
-
- free( key.dptr );
- free( pdn );
- }
- }
-
- {
- char **subtree = dn_subtree( NULL, dn );
-
- if( subtree != NULL ) {
- int i;
- for( i=0; subtree[i] != NULL; i++ ) {
- ldbm_datum_init( key );
- key.dsize = strlen( subtree[i] ) + 2;
- key.dptr = ch_malloc( key.dsize );
- sprintf( key.dptr, "%c%s",
- DN_SUBTREE_PREFIX, subtree[i] );
-
- (void) idl_delete_key( be, db, key, id );
-
- free( key.dptr );
- }
-
- charray_free( subtree );
- }
- }
-
- ldbm_datum_init( key );
-
- key.dsize = strlen( dn ) + 2;
- key.dptr = ch_malloc( key.dsize );
- sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
-
- rc = ldbm_cache_delete( db, key );
-
- free( key.dptr );
-
- ldbm_cache_close( be, db );
-
- Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 );
- return( rc );
-}
-
/*
* dn2entry - look up dn in the cache/indexes and return the corresponding
* entry.
#include "portable.h"
#include <stdio.h>
-
#include <ac/string.h>
#include "slap.h"
const char *dn,
ID id );
+int bdb_dn2id_delete(
+ BackendDB *be,
+ DB_TXN *tid,
+ const char *dn,
+ ID id );
+
+int bdb_dn2id_children(
+ BackendDB *be,
+ DB_TXN *tid,
+ const char *dn );
+
int bdb_dn2entry_rw LDAP_P(( Backend *be, DB_TXN *tid,
const char *dn, Entry **e, Entry **matched, int rw ));
DB_TXN *tid,
Entry *e );
+int bdb_id2entry_delete(
+ Backend *be,
+ DB_TXN *tid,
+ ID id );
+
/*
* idl.c
*/
DBT *key,
ID id );
+int bdb_idl_delete_key(
+ BackendDB *be,
+ DB *db,
+ DB_TXN *txn,
+ DBT *key,
+ ID id );
+
/*
* nextid.c
*/