]> git.sur5r.net Git - openldap/commitdiff
Add compare routine
authorKurt Zeilenga <kurt@openldap.org>
Sun, 24 Sep 2000 06:04:58 +0000 (06:04 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Sun, 24 Sep 2000 06:04:58 +0000 (06:04 +0000)
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/backbdb.dsp
servers/slapd/back-bdb/compare.c [new file with mode: 0644]
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/dn2id.c
servers/slapd/back-bdb/error.c
servers/slapd/back-bdb/proto-bdb.h

index 3d550a9a2c26cd758ef108a7d7822cd7295ceb71..c7c2a6ce77519010429f79312d2b87681709bfa0 100644 (file)
@@ -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;
        }
index 4abaa3f651b069f5cfb29548eb1968847f2092bd..5003574b93e045eded3b450d8a35d9141a4e0f26 100644 (file)
@@ -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"
index 7a92a3532e3bff835ebdac6b653a4d50b5a55e5e..66395d7bb071d8694248b107928ba33591454459 100644 (file)
@@ -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 (file)
index 0000000..ece33d0
--- /dev/null
@@ -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 <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
index a39930179805a53a1a53b9b49ac10ce887380be7..887e05afdd45b077d192538df3a03bbe91c280d9 100644 (file)
@@ -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 );
index 36b1541bd456daf06aea4d13f8723c8becac71d8..4b5c46e9b2740c51a3605a7aec2a05ded7b8a1fb 100644 (file)
@@ -8,9 +8,7 @@
 #include "portable.h"
 
 #include <stdio.h>
-
 #include <ac/string.h>
-#include <ac/socket.h>
 
 #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.
index aced7cf0dacf787b14ec54bbe6be56efcd9d4645..9e126da605baa133621bdd1b05daa70c50476840 100644 (file)
@@ -8,7 +8,6 @@
 #include "portable.h"
 
 #include <stdio.h>
-
 #include <ac/string.h>
 
 #include "slap.h"
index c896ec9ed2f07dd15e2e8f984497a8b6f41e90b0..780b275b875ff656bb5bdcb4dc995e75ad11b41b 100644 (file)
@@ -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
  */