From 64c521085be81a12cf300f0dbbc8196067cad72f Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Sun, 24 Sep 2000 06:04:58 +0000 Subject: [PATCH] Add compare routine --- servers/slapd/back-bdb/add.c | 20 ++- servers/slapd/back-bdb/back-bdb.h | 2 + servers/slapd/back-bdb/backbdb.dsp | 4 + servers/slapd/back-bdb/compare.c | 122 ++++++++++++++++++ servers/slapd/back-bdb/delete.c | 72 ++++++++--- servers/slapd/back-bdb/dn2id.c | 197 +++++++++++++++++------------ servers/slapd/back-bdb/error.c | 1 - servers/slapd/back-bdb/proto-bdb.h | 23 ++++ 8 files changed, 338 insertions(+), 103 deletions(-) create mode 100644 servers/slapd/back-bdb/compare.c diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 3d550a9a2c..c7c2a6ce77 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -53,6 +53,7 @@ bdb_add( } if (0) { + /* transaction retry */ retry: rc = txn_abort( ltid ); ltid = NULL; op->o_private = NULL; @@ -91,6 +92,9 @@ retry: rc = txn_abort( ltid ); ch_free( pdn ); switch( rc ) { + case 0: + case DB_NOTFOUND: + break; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; @@ -214,7 +218,13 @@ retry: rc = txn_abort( ltid ); 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; } @@ -224,7 +234,13 @@ retry: rc = txn_abort( ltid ); 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; } diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 4abaa3f651..5003574b93 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -33,6 +33,8 @@ LDAP_BEGIN_DECL #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" diff --git a/servers/slapd/back-bdb/backbdb.dsp b/servers/slapd/back-bdb/backbdb.dsp index 7a92a3532e..66395d7bb0 100644 --- a/servers/slapd/back-bdb/backbdb.dsp +++ b/servers/slapd/back-bdb/backbdb.dsp @@ -135,6 +135,10 @@ SOURCE=".\back-bdb.h" # End Source File # Begin Source File +SOURCE=.\compare.c +# End Source File +# Begin Source File + SOURCE=.\delete.c # End Source File # Begin Source File diff --git a/servers/slapd/back-bdb/compare.c b/servers/slapd/back-bdb/compare.c new file mode 100644 index 0000000000..ece33d08b9 --- /dev/null +++ b/servers/slapd/back-bdb/compare.c @@ -0,0 +1,122 @@ +/* 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 +#include + +#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 diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index a399301798..887e05afdd 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -34,6 +34,7 @@ bdb_delete( 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; @@ -66,6 +67,9 @@ retry: rc = txn_abort( ltid ); ch_free( pdn ); switch( rc ) { + case 0: + case DB_NOTFOUND: + break; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; @@ -115,6 +119,9 @@ retry: rc = txn_abort( ltid ); 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; @@ -173,32 +180,58 @@ retry: rc = txn_abort( ltid ); 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; } @@ -213,6 +246,7 @@ retry: rc = txn_abort( ltid ); db_strerror(rc), rc, 0 ); rc = LDAP_OTHER; text = "commit failed"; + } else { Debug( LDAP_DEBUG_TRACE, "bdb_add: added id=%08x dn=\"%s\"\n", @@ -226,8 +260,8 @@ return_results: 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 ); diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 36b1541bd4..4b5c46e9b2 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -8,9 +8,7 @@ #include "portable.h" #include - #include -#include #include "back-bdb.h" @@ -27,7 +25,7 @@ bdb_dn2id_add( 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 ); @@ -88,7 +86,121 @@ bdb_dn2id_add( 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; } @@ -183,83 +295,6 @@ dn2idl( } -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. diff --git a/servers/slapd/back-bdb/error.c b/servers/slapd/back-bdb/error.c index aced7cf0da..9e126da605 100644 --- a/servers/slapd/back-bdb/error.c +++ b/servers/slapd/back-bdb/error.c @@ -8,7 +8,6 @@ #include "portable.h" #include - #include #include "slap.h" diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index c896ec9ed2..780b275b87 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -34,6 +34,17 @@ int bdb_dn2id_add( 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 )); @@ -58,6 +69,11 @@ int bdb_id2entry_add( DB_TXN *tid, Entry *e ); +int bdb_id2entry_delete( + Backend *be, + DB_TXN *tid, + ID id ); + /* * idl.c */ @@ -68,6 +84,13 @@ int bdb_idl_insert_key( DBT *key, ID id ); +int bdb_idl_delete_key( + BackendDB *be, + DB *db, + DB_TXN *txn, + DBT *key, + ID id ); + /* * nextid.c */ -- 2.39.5