]> git.sur5r.net Git - openldap/commitdiff
redesign of back-bdb locking :
authorJong Hyuk Choi <jongchoi@openldap.org>
Fri, 31 May 2002 20:49:19 +0000 (20:49 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Fri, 31 May 2002 20:49:19 +0000 (20:49 +0000)
cache entry is locked by Berkeley DB lock primitives.

17 files changed:
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/attribute.c
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/bind.c
servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/compare.c
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/dn2entry.c
servers/slapd/back-bdb/group.c
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/modify.c
servers/slapd/back-bdb/modrdn.c
servers/slapd/back-bdb/operational.c
servers/slapd/back-bdb/passwd.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/referral.c
servers/slapd/back-bdb/search.c

index b7cc3e70ef661f6a08cb1c6d0550da567177b2fc..303ed63a35d19712a8efbb9477ddc374fbc16ec7 100644 (file)
@@ -23,7 +23,7 @@ bdb_add(
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        struct berval   pdn;
        Entry           *p = NULL;
-       int                     rc
+       int             rc, ret
        const char      *text;
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
@@ -33,6 +33,8 @@ bdb_add(
 #ifdef BDB_SUBENTRIES
        int subentry;
 #endif
+       u_int32_t       locker;
+       DB_LOCK         lock;
 #if 0
        u_int32_t       lockid;
        DB_LOCK         lock;
@@ -108,6 +110,8 @@ retry:      /* transaction retry */
                text = "internal error";
                goto return_results;
        }
+
+       locker = TXN_ID ( ltid );
 #if 0
        lockid = TXN_ID( ltid );
 #endif
@@ -142,7 +146,7 @@ retry:      /* transaction retry */
 #endif
 
                /* get parent */
-               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0 );
+               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0, locker, &lock );
 
                switch( rc ) {
                case 0:
@@ -169,7 +173,7 @@ retry:      /* transaction retry */
                                refs = is_entry_referral( matched )
                                        ? get_entry_referrals( be, conn, op, matched )
                                        : NULL;
-                               bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                                matched = NULL;
 
                        } else {
@@ -200,7 +204,7 @@ retry:      /* transaction retry */
                case DB_LOCK_DEADLOCK:
                case DB_LOCK_NOTGRANTED:
                        /* free parent and reader lock */
-                       bdb_cache_return_entry_r( &bdb->bi_cache, p );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, p, &lock );
                        p = NULL;
                        goto retry;
                }
@@ -262,7 +266,7 @@ retry:      /* transaction retry */
                                matched_dn, NULL, refs, NULL );
 
                        ber_bvarray_free( refs );
-                       bdb_cache_return_entry_r( &bdb->bi_cache, p );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, p, &lock );
                        p = NULL;
                        goto done;
                }
@@ -275,7 +279,7 @@ retry:      /* transaction retry */
 #endif
 
                /* free parent and reader lock */
-               bdb_cache_return_entry_r( &bdb->bi_cache, p );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, p, &lock );
                p = NULL;
 
        } else {
@@ -430,9 +434,22 @@ retry:     /* transaction retry */
                        text = "txn_prepare failed";
 
                } else {
+                       ret = bdb_cache_add_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, CACHE_WRITE_LOCK, locker, &lock);
+#if 0
                        if ( bdb_cache_add_entry_rw(&bdb->bi_cache,
                                e, CACHE_WRITE_LOCK) != 0 )
-                       {
+#endif
+                       switch ( ret ) {
+                       case 0:
+                               break;
+                       case DB_LOCK_DEADLOCK:
+                       case DB_LOCK_NOTGRANTED:
+                               goto retry;
+                       default:
+                               ret = LDAP_OTHER;
+                       }
+
+                       if ( ret ) {
                                if(( rc=TXN_ABORT( ltid )) != 0 ) {
                                        text = "cache add & txn_abort failed";
                                } else {
index 38203b994d3e245290427b0d29eb1e30a4962c8e..1277f0256104f9addae957f37ed24829b19ed65a 100644 (file)
@@ -39,6 +39,9 @@ bdb_attribute(
        const char *entry_at_name = entry_at->ad_cname.bv_val;
        AccessControlState acl_state = ACL_STATE_INIT;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG(( "backend", LDAP_LEVEL_ARGS,
                "bdb_attribute: gr dn: \"%s\"\n", entry_ndn->bv_val ));
@@ -65,6 +68,11 @@ bdb_attribute(
                txn = boi->boi_txn;
        }
 
+       if ( txn != NULL )
+               locker = TXN_ID ( txn );
+       else
+               LOCK_ID ( bdb->bi_dbenv, &locker );
+
        if (target != NULL && dn_match(&target->e_nname, entry_ndn)) {
                /* we already have a LOCKED copy of the entry */
                e = target;
@@ -80,16 +88,23 @@ bdb_attribute(
 
 
        } else {
+dn2entry_retry:
                /* can we find entry */
-               rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0 );
+               rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0, locker, &lock );
                switch( rc ) {
                case DB_NOTFOUND:
                case 0:
                        break;
+               case DB_LOCK_DEADLOCK:
+               case DB_LOCK_NOTGRANTED:
+                       goto dn2entry_retry;
                default:
                        if( txn != NULL ) {
                                boi->boi_err = rc;
                        }
+                       else {
+                               LOCK_ID_FREE( bdb->bi_dbenv, locker );
+                       }
                        return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
                }
                if (e == NULL) {
@@ -102,6 +117,9 @@ bdb_attribute(
                                "=> bdb_attribute: cannot find entry: \"%s\"\n",
                                        entry_ndn->bv_val, 0, 0 ); 
 #endif
+                       if ( txn == NULL ) {
+                               LOCK_ID_FREE( bdb->bi_dbenv, locker );
+                       }
                        return LDAP_NO_SUCH_OBJECT; 
                }
                
@@ -205,7 +223,11 @@ bdb_attribute(
 return_results:
        if( target != e ) {
                /* free entry */
-               bdb_cache_return_entry_r(&bdb->bi_cache, e);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
+       }
+
+       if ( txn == NULL ) {
+               LOCK_ID_FREE( bdb->bi_dbenv, locker );
        }
 
 #ifdef NEW_LOGGING
index be89b98bf30361f5165387cc92175719c878f71b..784bbc89aaa40eeffa247c368991d747d9db1dc7 100644 (file)
@@ -146,21 +146,27 @@ struct bdb_op_info {
 #if DB_VERSION_MAJOR < 4
 #define LOCK_DETECT(env,f,t,a)         lock_detect(env, f, t, a)
 #define LOCK_GET(env,i,f,o,m,l)                lock_get(env, i, f, o, m, l)
+#define LOCK_PUT(env,l)                        lock_put(env, l)
 #define TXN_CHECKPOINT(env,k,m,f)      txn_checkpoint(env, k, m, f)
 #define TXN_BEGIN(env,p,t,f)           txn_begin((env), p, t, f)
 #define TXN_PREPARE(txn,gid)           txn_prepare((txn), (gid))
 #define TXN_COMMIT(txn,f)                      txn_commit((txn), (f))
 #define        TXN_ABORT(txn)                          txn_abort((txn))
 #define TXN_ID(txn)                                    txn_id(txn)
+#define LOCK_ID(env, locker)           lock_id(env, locker)
+#define LOCK_ID_FREE(env, locker)      lock_id_free(env, locker)
 #else
 #define LOCK_DETECT(env,f,t,a)         (env)->lock_detect(env, f, t, a)
 #define LOCK_GET(env,i,f,o,m,l)                (env)->lock_get(env, i, f, o, m, l)
+#define LOCK_PUT(env,l)                        (env)->lock_put(env, l)
 #define TXN_CHECKPOINT(env,k,m,f)      (env)->txn_checkpoint(env, k, m, f)
 #define TXN_BEGIN(env,p,t,f)           (env)->txn_begin((env), p, t, f)
 #define TXN_PREPARE(txn,g)                     (txn)->prepare((txn), (g))
 #define TXN_COMMIT(txn,f)                      (txn)->commit((txn), (f))
 #define TXN_ABORT(txn)                         (txn)->abort((txn))
 #define TXN_ID(txn)                                    (txn)->id(txn)
+#define LOCK_ID(env, locker)           (env)->lock_id(env, locker)
+#define LOCK_ID_FREE(env, locker)      (env)->lock_id_free(env, locker)
 #endif
 
 LDAP_END_DECL
index ad1bcfe3bb8315648d2da15b9a6ec51412cce818..be64c5b6a8c90ca587a63b51cbf81943868bf619 100644 (file)
@@ -40,14 +40,20 @@ bdb_bind(
 
        AttributeDescription *password = slap_schema.si_ad_userPassword;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "bind", LDAP_LEVEL_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val ));
 #else
        Debug( LDAP_DEBUG_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val, 0, 0);
 #endif
 
+       LOCK_ID(bdb->bi_dbenv, &locker);
+
+dn2entry_retry:
        /* get entry */
-       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
 
        switch(rc) {
        case DB_NOTFOUND:
@@ -56,10 +62,15 @@ bdb_bind(
        case LDAP_BUSY:
                send_ldap_result( conn, op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
+               LOCK_ID_FREE(bdb->bi_dbenv, locker);
                return LDAP_BUSY;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
                send_ldap_result( conn, op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
+               LOCK_ID_FREE(bdb->bi_dbenv, locker);
                return rc;
        }
 
@@ -75,7 +86,7 @@ bdb_bind(
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
 
-                       bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
                        matched = NULL;
 
                } else {
@@ -108,6 +119,8 @@ bdb_bind(
                                NULL, NULL, NULL, NULL );
                }
 
+               LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
                ber_bvarray_free( refs );
                free( matched_dn );
 
@@ -274,9 +287,11 @@ bdb_bind(
 done:
        /* free entry and reader lock */
        if( e != NULL ) {
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
 
+       LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
        /* front end with send result on success (rc==0) */
        return rc;
 }
index 5038db4bc799bacf7dbe6f7982e621f379a1a0db..35d5a5720dc1fba8f9a7a7cdae082c8b40ab0614 100644 (file)
@@ -132,6 +132,36 @@ bdb_cache_entry_private_init( Entry *e )
        return 0;
 }
 
+int
+bdb_cache_entry_db_lock
+( DB_ENV *env, u_int32_t locker, Entry *e, int rw, u_int32_t flags, DB_LOCK *lock )
+{
+       int       rc;
+       DBT       lockobj;
+       int       db_rw;
+
+       if (rw)
+               db_rw = DB_LOCK_WRITE;
+       else
+               db_rw = DB_LOCK_READ;
+
+       lockobj.data = e->e_nname.bv_val;
+       lockobj.size = e->e_nname.bv_len;
+       rc = LOCK_GET(env, locker, flags | DB_LOCK_NOWAIT,
+                                       &lockobj, db_rw, lock);
+       return rc;
+}
+
+int
+bdb_cache_entry_db_unlock
+( DB_ENV *env, DB_LOCK *lock )
+{
+       int rc;
+
+       rc = LOCK_PUT ( env, lock );
+       return rc;
+}
+
 /*
  * marks an entry in CREATING state as committed, so it is really returned
  * to the cache. Otherwise an entry in CREATING state is removed.
@@ -162,8 +192,9 @@ bdb_cache_entry_private_destroy( Entry *e )
 }
 
 void
-bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
+bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
 {
+
        ID id;
        int refcnt, freeit = 1;
 
@@ -172,7 +203,112 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
 
        assert( e->e_private );
 
+#if 0
        bdb_cache_entry_rdwr_unlock(e, rw);
+#endif
+
+       id = e->e_id;
+       refcnt = --BEI(e)->bei_refcnt;
+
+       /*
+        * if the entry is returned when in CREATING state, it is deleted
+        * but not freed because it may belong to someone else (do_add,
+        * for instance)
+        */
+       if (  BEI(e)->bei_state == CACHE_ENTRY_CREATING ) {
+               /* set lru mutex */
+               ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
+               bdb_cache_delete_entry_internal( cache, e );
+               /* free lru mutex */
+               ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
+               freeit = 0;
+               /* now the entry is in DELETED state */
+       }
+
+       if ( BEI(e)->bei_state == CACHE_ENTRY_COMMITTED ) {
+               BEI(e)->bei_state = CACHE_ENTRY_READY;
+
+               /* free cache write lock */
+               ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                          "bdb_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
+                          id, rw ? "w" : "r", refcnt ));
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "====> bdb_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_cache_return_entry_rw: %ld, delete pending (%d).\n",
+                                  id, refcnt ));
+#else
+                       Debug( LDAP_DEBUG_TRACE,
+                               "====> bdb_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_cache_return_entry_rw: (%ld): deleted (%d)\n",
+                                  id, refcnt ));
+#else
+                       Debug( LDAP_DEBUG_TRACE,
+                               "====> bdb_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_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
+                          id, rw ? "w": "r", refcnt ));
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "====> bdb_cache_return_entry_%s( %ld ): returned (%d)\n",
+                       rw ? "w" : "r", id, refcnt);
+#endif
+       }
+}
+
+void
+bdb_cache_return_entry_rw
+( DB_ENV *env, Cache *cache, Entry *e, int rw, DB_LOCK *lock )
+{
+       ID id;
+       int refcnt, freeit = 1;
+
+       /* set cache write lock */
+       ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
+
+       assert( e->e_private );
+
+       bdb_cache_entry_db_unlock( env, lock );
+#if 0
+       bdb_cache_entry_rdwr_unlock(e, rw);
+#endif
 
        id = e->e_id;
        refcnt = --BEI(e)->bei_refcnt;
@@ -290,12 +426,16 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
  * returns:    0       entry has been created and locked
  *             1       entry already existed
  *             -1      something bad happened
+ *             other    Berkeley DB locking error code
  */
 int
 bdb_cache_add_entry_rw(
+    DB_ENV     *env,
     Cache      *cache,
     Entry      *e,
-    int                rw
+    int                rw,
+    u_int32_t  locker,
+    DB_LOCK    *lock
 )
 {
        int     i, rc;
@@ -385,7 +525,37 @@ bdb_cache_add_entry_rw(
                return( -1 );
        }
 
-       bdb_cache_entry_rdwr_lock( e, rw );
+       rc = bdb_cache_entry_db_lock( env, locker, e, rw, 0, lock );
+       switch ( rc ) {
+       case 0 :
+               break;
+       case DB_LOCK_DEADLOCK :
+       case DB_LOCK_NOTGRANTED :
+               /* undo avl changes immediately */
+               if ( avl_delete( &cache->c_idtree, (caddr_t) e,
+                       (AVL_CMP) entry_id_cmp ) == NULL ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
+                               "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+#else
+                       Debug( LDAP_DEBUG_ANY, "====> can't delete from id cache\n", 0, 0, 0 );
+#endif
+               }
+               if ( avl_delete( &cache->c_dntree, (caddr_t) e,
+                               (AVL_CMP) entry_dn_cmp ) == NULL ) {
+#ifdef NEW_LOGGING
+                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
+                                       "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+#else
+                       Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", 0, 0, 0 );
+#endif
+               }
+               /* fall through */
+       default :
+               bdb_cache_entry_private_destroy(e);
+               ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+               return rc;
+       }
 
        /* put the entry into 'CREATING' state */
        /* will be marked after when entry is returned */
@@ -661,14 +831,18 @@ try_again:
 
 Entry *
 bdb_cache_find_entry_id(
+       DB_ENV  *env,
        Cache   *cache,
        ID                              id,
-       int                             rw
+       int                             rw,
+       u_int32_t       locker,
+       DB_LOCK         *lock
 )
 {
        Entry   e;
        Entry   *ep;
        int     count = 0;
+       int     rc;
 
        e.e_id = id;
 
@@ -715,7 +889,13 @@ try_again:
                }
 
                /* acquire reader lock */
+               rc = bdb_cache_entry_db_lock ( env, locker, ep, rw, 0, lock );
+
+#if 0
                if ( bdb_cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
+#endif
+
+               if ( rc ) { /* will be changed to retry beyond threshold */
                        /* could not acquire entry lock...
                         * owner cannot free as we have the cache locked.
                         * so, unlock the cache, yield, and try again.
@@ -732,6 +912,9 @@ try_again:
                        Debug(LDAP_DEBUG_TRACE,
                                "====> bdb_cache_find_entry_id( %ld ): %ld (busy) %d\n",
                                id, ep_id, state);
+                       Debug(LDAP_DEBUG_TRACE,
+                               "locker = %d\n",
+                               locker, 0, 0);
 #endif
 
                        ldap_pvt_thread_yield();
index e9c40dcbbc4bb5b721b096f200b0a188869b359c..ac799bb62777791701da86b2cd90c090a076f781 100644 (file)
@@ -31,8 +31,14 @@ bdb_compare(
        const char      *text = NULL;
        int             manageDSAit = get_manageDSAit( op );
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
+       LOCK_ID ( bdb->bi_dbenv, &locker );
+
+dn2entry_retry:
        /* get entry */
-       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
 
        switch( rc ) {
        case DB_NOTFOUND:
@@ -41,6 +47,9 @@ bdb_compare(
        case LDAP_BUSY:
                text = "ldap server busy";
                goto return_results;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
                rc = LDAP_OTHER;
                text = "internal error";
@@ -56,7 +65,7 @@ bdb_compare(
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
                        matched = NULL;
 
                } else {
@@ -125,8 +134,10 @@ return_results:
 done:
        /* free entry */
        if( e != NULL ) {
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
 
+       LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+
        return rc;
 }
index dcaf399fafd07c9abb777f2abc130bf84a00a992..9ded16580eef7d761ee4c4b26373397881599233 100644 (file)
@@ -33,6 +33,9 @@ bdb_delete(
        AttributeDescription *children = slap_schema.si_ad_children;
        DB_TXN          *ltid = NULL;
        struct bdb_op_info opinfo;
+
+       u_int32_t       locker;
+       DB_LOCK         lock;
 #if 0
        u_int32_t       lockid;
        DB_LOCK         lock;
@@ -49,7 +52,7 @@ bdb_delete(
        if( 0 ) {
 retry: /* transaction retry */
                if( e != NULL ) {
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "delete", LDAP_LEVEL_DETAIL1, 
@@ -87,6 +90,8 @@ retry:        /* transaction retry */
                text = "internal error";
                goto return_results;
        }
+
+       locker = TXN_ID ( ltid );
 #if 0
        lockid = TXN_ID( ltid );
 #endif
@@ -111,7 +116,7 @@ retry:      /* transaction retry */
                }
 #endif
                /* get parent */
-               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0 );
+               rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0, locker, &lock );
 
                switch( rc ) {
                case 0:
@@ -147,7 +152,7 @@ retry:      /* transaction retry */
                rc = access_allowed( be, conn, op, p,
                        children, NULL, ACL_WRITE, NULL );
 
-               bdb_cache_return_entry_r(&bdb->bi_cache, p);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, p, &lock);
                p = NULL;
 
                switch( opinfo.boi_err ) {
@@ -226,7 +231,7 @@ retry:      /* transaction retry */
        }
 
        /* get entry for read/modify/write */
-       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW );
+       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW, locker, &lock );
 
        switch( rc ) {
        case 0:
@@ -263,7 +268,7 @@ retry:      /* transaction retry */
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched );
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
                        matched = NULL;
 
                } else {
@@ -465,7 +470,7 @@ return_results:
 done:
        /* free entry */
        if( e != NULL ) {
-               bdb_cache_return_entry_w(&bdb->bi_cache, e);
+               bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
        }
 
        if( ltid != NULL ) {
index 00cd9efed7cea38446f909fe4af43ce29d6312a1..a6440536f7ebb662761bab2260d71ab522273371 100644 (file)
@@ -25,7 +25,9 @@ bdb_dn2entry_rw(
        Entry **e,
        Entry **matched,
        int flags,
-       int rw )
+       int rw,
+       u_int32_t locker,
+       DB_LOCK *lock )
 {
        int rc;
        ID              id, id2 = 0;
@@ -52,9 +54,9 @@ bdb_dn2entry_rw(
        }
 
        if( id2 == 0 ) {
-               rc = bdb_id2entry_rw( be, tid, id, e, rw );
+               rc = bdb_id2entry_rw( be, tid, id, e, rw, locker, lock );
        } else {
-               rc = bdb_id2entry_r( be, tid, id2, matched);
+               rc = bdb_id2entry_r( be, tid, id2, matched, locker, lock );
        }
 
        return rc;
index 2000de520996c7f849c70efc136ce9ac9bd2c2b1..6c2cdf11330a3c7f9035248c16555a65ffa41101 100644 (file)
@@ -44,6 +44,9 @@ bdb_group(
        const char *group_oc_name = NULL;
        const char *group_at_name = group_at->ad_cname.bv_val;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
        if( group_oc->soc_names && group_oc->soc_names[0] ) {
                group_oc_name = group_oc->soc_names[0];
        } else {
@@ -76,6 +79,11 @@ bdb_group(
                txn = boi->boi_txn;
        }
 
+       if ( txn )
+               locker = TXN_ID( txn );
+       else
+               LOCK_ID ( bdb->bi_dbenv, &locker );
+
        if (dn_match(&target->e_name, gr_ndn)) {
                /* we already have a LOCKED copy of the entry */
                e = target;
@@ -88,12 +96,18 @@ bdb_group(
                        gr_ndn->bv_val, 0, 0 );
 #endif
        } else {
+dn2entry_retry:
                /* can we find group entry */
-               rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0 ); 
+               rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0, locker, &lock ); 
                if( rc ) {
+                       if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED )
+                               goto dn2entry_retry;
                        if( txn ) {
                                boi->boi_err = rc;
                        }
+                       else {
+                               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+                       }
                        return( 1 );
                }
                if (e == NULL) {
@@ -106,6 +120,9 @@ bdb_group(
                                "=> bdb_group: cannot find group: \"%s\"\n",
                                        gr_ndn->bv_val, 0, 0 ); 
 #endif
+                       if ( txn == NULL ) {
+                               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+                       }
                        return( 1 );
                }
 #ifdef NEW_LOGGING
@@ -211,7 +228,11 @@ bdb_group(
 return_results:
        if( target != e ) {
                /* free entry */
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
+       }
+
+       if ( txn == NULL ) {
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
        }
 
 #ifdef NEW_LOGGING
index 10ec1637a58aacd6baff8e40cd27354fbedacbc0..0a841cab21e1c7099e740d2ef8e7886d067e8133 100644 (file)
@@ -80,13 +80,15 @@ int bdb_id2entry_rw(
        DB_TXN *tid,
        ID id,
        Entry **e,
-       int rw )
+       int rw,
+       u_int32_t locker,
+       DB_LOCK *lock )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        DB *db = bdb->bi_id2entry->bdi_db;
        DBT key, data;
        struct berval bv;
-       int rc = 0;
+       int rc = 0, ret = 0;
 
        *e = NULL;
 
@@ -97,7 +99,7 @@ int bdb_id2entry_rw(
        DBTzero( &data );
        data.flags = DB_DBT_MALLOC;
 
-       if ((*e = bdb_cache_find_entry_id(&bdb->bi_cache, id, rw)) != NULL) {
+       if ((*e = bdb_cache_find_entry_id(bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock)) != NULL) {
                return 0;
        }
 
@@ -121,24 +123,36 @@ int bdb_id2entry_rw(
                ch_free( data.data );
        }
 
-       while (rc == 0 && bdb_cache_add_entry_rw(&bdb->bi_cache, *e, rw) != 0) {
-               Entry *ee;
-               int add_loop_cnt = 0;
-               if ( (*e)->e_private != NULL ) {
-                       free ((*e)->e_private);
-               }
-               (*e)->e_private = NULL;
-               if ( (ee = bdb_cache_find_entry_id
-                               (&bdb->bi_cache, id, rw) ) != NULL) {
-                       bdb_entry_return ( *e );
-                       *e = ee;
-                       return 0;
+       if ( rc == 0 ) {
+               ret = bdb_cache_add_entry_rw( bdb->bi_dbenv,
+                               &bdb->bi_cache, *e, rw, locker, lock);
+               while ( ret == 1 || ret == -1 ) {
+                       Entry *ee;
+                       int add_loop_cnt = 0;
+                       if ( (*e)->e_private != NULL ) {
+                               free ((*e)->e_private);
+                       }
+                       (*e)->e_private = NULL;
+                       if ( (ee = bdb_cache_find_entry_id
+                                       (bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock) ) != NULL) {
+                               bdb_entry_return ( *e );
+                               *e = ee;
+                               return 0;
+                       }
+                       if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
+                               bdb_entry_return ( *e );
+                               *e = NULL;
+                               return LDAP_BUSY;
+                       }
                }
-               if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
-                       bdb_entry_return ( *e );
+               if ( ret != 0 ) {
+                       if ( (*e)->e_private != NULL )
+                               free ( (*e)->e_private );
+                       bdb_entry_return( *e );
                        *e = NULL;
-                       return LDAP_BUSY;
+                       ch_free( data.data );
                }
+               rc = ret;
        }
 
 #ifdef BDB_HIER
@@ -232,7 +246,7 @@ int bdb_entry_release(
  
        if ( slapMode == SLAP_SERVER_MODE ) {
                /* free entry and reader or writer lock */
-               bdb_cache_return_entry_rw( &bdb->bi_cache, e, rw );
+               bdb_unlocked_cache_return_entry_rw( &bdb->bi_cache, e, rw );
        } else {
                if (e->e_private != NULL)
                        free (e->e_private);
index 184976e5e877d8e7043b553228306317b78be396..2e47ab49a5f428c32ae12f07f5beb534b1f29f11 100644 (file)
@@ -249,6 +249,9 @@ bdb_modify(
        DB_TXN  *ltid = NULL;
        struct bdb_op_info opinfo;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "modify", LDAP_LEVEL_ENTRY, "bdb_modify: %s\n", dn->bv_val ));
 #else
@@ -259,7 +262,7 @@ bdb_modify(
 retry: /* transaction retry */
                if( e != NULL ) {
                        bdb_cache_delete_entry(&bdb->bi_cache, e);
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "modify", LDAP_LEVEL_DETAIL1, "bdb_modify: retrying...\n" ));
@@ -295,13 +298,15 @@ retry:    /* transaction retry */
                goto return_results;
        }
 
+       locker = TXN_ID ( ltid );
+
        opinfo.boi_bdb = be;
        opinfo.boi_txn = ltid;
        opinfo.boi_err = 0;
        op->o_private = &opinfo;
 
        /* get entry */
-       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0, locker, &lock );
 
        if ( rc != 0 ) {
 #ifdef NEW_LOGGING
@@ -337,7 +342,7 @@ retry:      /* transaction retry */
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                        matched = NULL;
 
                } else {
@@ -463,7 +468,7 @@ 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);
        }
        return rc;
 }
index cb1e1517ebb81f3f5bc9377d26152d5af4a8dd69..0a7e1de7ee59c6d9b53c77ddcee5c25cfd2e21b4 100644 (file)
@@ -56,6 +56,9 @@ bdb_modrdn(
 
        int             manageDSAit = get_manageDSAit( op );
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "modrdn", LDAP_LEVEL_ENTRY, "==>bdb_modrdn(%s,%s,%s)\n",
                dn->bv_val,newrdn->bv_val,
@@ -78,13 +81,13 @@ bdb_modrdn(
 retry: /* transaction retry */
                if (e != NULL) {
                        bdb_cache_delete_entry(&bdb->bi_cache, e);
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (p != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, p);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, p, &lock);
                }
                if (np != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, np);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, np, &lock);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "modrdn", LDAP_LEVEL_DETAIL1, "==>bdb_modrdn: retrying...\n"));
@@ -119,13 +122,15 @@ retry:    /* transaction retry */
                goto return_results;
        }
 
+       locker = TXN_ID ( ltid );
+
        opinfo.boi_bdb = be;
        opinfo.boi_txn = ltid;
        opinfo.boi_err = 0;
        op->o_private = &opinfo;
 
        /* get entry */
-       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0, locker, &lock );
 
        switch( rc ) {
        case 0:
@@ -152,7 +157,7 @@ retry:      /* transaction retry */
                        refs = is_entry_referral( matched )
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
-                       bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+                       bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
                        matched = NULL;
 
                } else {
@@ -199,7 +204,7 @@ retry:      /* transaction retry */
                /* Make sure parent entry exist and we can write its 
                 * children.
                 */
-               rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0 );
+               rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0, locker, &lock );
 
                switch( rc ) {
                case 0:
@@ -348,7 +353,7 @@ retry:      /* transaction retry */
                        /* newSuperior == entry being moved?, if so ==> ERROR */
                        /* Get Entry with dn=newSuperior. Does newSuperior exist? */
 
-                       rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0 );
+                       rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0, locker, &lock );
 
                        switch( rc ) {
                        case 0:
@@ -855,17 +860,17 @@ done:
        /* LDAP v3 Support */
        if( np != NULL ) {
                /* free new parent and reader lock */
-               bdb_cache_return_entry_r(&bdb->bi_cache, np);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, np, &lock);
        }
 
        if( p != NULL ) {
                /* free parent and reader lock */
-               bdb_cache_return_entry_r(&bdb->bi_cache, p);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, p, &lock);
        }
 
        /* free entry */
        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( ltid != NULL ) {
index 08172b8c2d173278de42aa9669ca1114285caf58..d0517abf9ecdf59e6c416abfdfe15b9923a4b5b7 100644 (file)
@@ -44,9 +44,11 @@ bdb_operational(
 
        if( 0 ) {
 retry: /* transaction retry */
+#if 0
                if( e != NULL ) {
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
+#endif
 #ifdef NEW_LOGGING
                LDAP_LOG (( "operational", LDAP_LEVEL_DETAIL1,
                        "=> bdb_operational: retrying...\n" ));
index 0e05443926b91970ecebf9e9b951c6c76ed4cb32..25f0c654ed7513a2184c6684b29b49dc0af7abc9 100644 (file)
@@ -41,6 +41,9 @@ bdb_exop_passwd(
        struct berval dn;
        struct berval ndn;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
        assert( reqoid != NULL );
        assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
 
@@ -109,7 +112,7 @@ bdb_exop_passwd(
 retry: /* transaction retry */
                if ( e != NULL ) {
                        bdb_cache_delete_entry(&bdb->bi_cache, e);
-                       bdb_cache_return_entry_w(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
 #ifdef NEW_LOGGING
                LDAP_LOG (( "passwd", LDAP_LEVEL_DETAIL1, "bdb_exop_passwd: retrying...\n" ));
@@ -144,13 +147,15 @@ retry:    /* transaction retry */
                goto done;
        }
 
+       locker = TXN_ID ( ltid );
+
        opinfo.boi_bdb = be;
        opinfo.boi_txn = ltid;
        opinfo.boi_err = 0;
        op->o_private = &opinfo;
 
        /* get entry */
-       rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 );
+       rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 , locker, &lock);
 
        switch(rc) {
        case DB_LOCK_DEADLOCK:
@@ -256,7 +261,7 @@ retry:      /* transaction retry */
 
 done:
        if( e != NULL ) {
-               bdb_cache_return_entry_w( &bdb->bi_cache, e );
+               bdb_cache_return_entry_w( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
                
        if( hash.bv_val != NULL ) {
index cdea9803e190411fc29f2d066bf0051eca884bc4..7cfe90293fdf37e7b73442db2753526f96aa7cab 100644 (file)
@@ -58,9 +58,9 @@ bdb_db_cache(
  * dn2entry.c
  */
 int bdb_dn2entry_rw LDAP_P(( BackendDB *be, DB_TXN *tid,
-       struct berval *dn, Entry **e, Entry **matched, int flags, int rw ));
-#define bdb_dn2entry_r(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0)
-#define bdb_dn2entry_w(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1)
+       struct berval *dn, Entry **e, Entry **matched, int flags, int rw , u_int32_t locker, DB_LOCK *lock));
+#define bdb_dn2entry_r(be, tid, dn, e, m, f, locker, lock) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0, locker, lock)
+#define bdb_dn2entry_w(be, tid, dn, e, m, f, locker, lock) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1, locker, lock)
 
 /*
  * dn2id.c
@@ -152,9 +152,11 @@ int bdb_id2entry_rw(
        DB_TXN *tid,
        ID id,
        Entry **e,
-       int rw );
-#define bdb_id2entry_r(be, tid, id, e)      bdb_id2entry_rw((be), (tid), (id), (e), 0)
-#define bdb_id2entry_w(be, tid, id, e)      bdb_id2entry_rw((be), (tid), (id), (e), 1)
+       int rw,
+       u_int32_t locker,
+       DB_LOCK *lock );
+#define bdb_id2entry_r(be, tid, id, e, locker, lock)      bdb_id2entry_rw((be), (tid), (id), (e), 0, locker, lock)
+#define bdb_id2entry_w(be, tid, id, e, locker, lock)      bdb_id2entry_rw((be), (tid), (id), (e), 1, locker, lock)
 
 void bdb_entry_free ( Entry *e );
 
@@ -301,13 +303,19 @@ BI_op_extended bdb_exop_passwd;
  */
 
 void bdb_cache_entry_commit( Entry *e );
-void bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
-#define bdb_cache_return_entry_r(c, e) bdb_cache_return_entry_rw((c), (e), 0)
-#define bdb_cache_return_entry_w(c, e) bdb_cache_return_entry_rw((c), (e), 1)
+void bdb_cache_return_entry_rw( DB_ENV *env, Cache *cache, Entry *e, int rw, DB_LOCK *lock );
+#define bdb_cache_return_entry_r(env, c, e, l) bdb_cache_return_entry_rw((env), (c), (e), 0, (l))
+#define bdb_cache_return_entry_w(env, c, e, l) bdb_cache_return_entry_rw((env), (c), (e), 1, (l))
+void bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
+#define bdb_unlocked_cache_return_entry_r( c, e ) bdb_cache_return_entry_rw((c), (e), 0)
+#define bdb_unlocked_cache_return_entry_w( c, e ) bdb_cache_return_entry_rw((c), (e), 1)
 int bdb_cache_add_entry_rw(
-       Cache   *cache,
-       Entry   *e,
-       int     rw
+       DB_ENV  *env,
+       Cache   *cache,
+       Entry   *e,
+       int     rw,
+       u_int32_t locker,
+       DB_LOCK *lock
 );
 int bdb_cache_update_entry(
        Cache   *cache,
@@ -319,9 +327,12 @@ ID bdb_cache_find_entry_ndn2id(
        struct berval   *ndn
 );
 Entry* bdb_cache_find_entry_id(
-       Cache   *cache,
-       ID      id,
-       int     rw
+       DB_ENV          *env,
+       Cache           *cache,
+       ID              id,
+       int             rw,
+       u_int32_t       locker,
+       DB_LOCK         *lock
 );
 int bdb_cache_delete_entry(
        Cache   *cache,
index 3517492c7945b8c24374ec5a254258689bab207d..4d60f68d0e83030029b78329c7c41b3424ea4b3f 100644 (file)
@@ -26,6 +26,9 @@ bdb_referrals(
        Entry *e = NULL;
        Entry *matched = NULL;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
        if( op->o_tag == LDAP_REQ_SEARCH ) {
                /* let search take care of itself */
                return rc;
@@ -36,8 +39,11 @@ bdb_referrals(
                return rc;
        } 
 
+       LOCK_ID ( bdb->bi_dbenv, &locker );
+
+dn2entry_retry:
        /* get entry */
-       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+       rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
 
        switch(rc) {
        case DB_NOTFOUND:
@@ -46,14 +52,18 @@ bdb_referrals(
                break;
        case LDAP_BUSY:
                if (e != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (matched != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
                return LDAP_BUSY;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
 #ifdef NEW_LOGGING
                LDAP_LOG (( "referral", LDAP_LEVEL_ERR,
@@ -65,13 +75,14 @@ bdb_referrals(
                        db_strerror(rc), rc, 0 ); 
 #endif
                if (e != NULL) {
-                        bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                        bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                 if (matched != NULL) {
-                        bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                        bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
                return rc;
        }
 
@@ -97,7 +108,7 @@ bdb_referrals(
                                refs = get_entry_referrals( be, conn, op, matched );
                        }
 
-                       bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                        matched = NULL;
                } else if ( default_referral != NULL ) {
                        rc = LDAP_OTHER;
@@ -116,6 +127,7 @@ bdb_referrals(
                                NULL, NULL );
                }
 
+               LOCK_ID_FREE ( bdb->bi_dbenv, locker );
                free( matched_dn );
                return rc;
        }
@@ -148,6 +160,7 @@ bdb_referrals(
                ber_bvarray_free( refs );
        }
 
-       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
+       LOCK_ID_FREE ( bdb->bi_dbenv, locker );
        return rc;
 }
index 9887feb342c6515c777c11af87c1e1cb0a8d31c0..5dabe6b49f15f923cd584d7cbc75bf706b4ef9bc 100644 (file)
@@ -59,6 +59,9 @@ bdb_search(
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
 
+       u_int32_t       locker;
+       DB_LOCK         lock;
+
 #ifdef NEW_LOGGING
        LDAP_LOG (( "search", LDAP_LEVEL_ENTRY,"bdb_back_search\n"));
 #else
@@ -68,6 +71,8 @@ bdb_search(
 
        manageDSAit = get_manageDSAit( op );
 
+       LOCK_ID (bdb->bi_dbenv, &locker );
+
        if ( nbase->bv_len == 0 ) {
                /* DIT root special case */
                e = (Entry *) &slap_entry_root;
@@ -81,7 +86,8 @@ bdb_search(
        } else
 #endif
        {
-               rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0 );
+dn2entry_retry:
+               rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0, locker, &lock );
        }
 
        switch(rc) {
@@ -90,23 +96,28 @@ bdb_search(
                break;
        case LDAP_BUSY:
                if (e != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (matched != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                return LDAP_BUSY;
+       case DB_LOCK_DEADLOCK:
+       case DB_LOCK_NOTGRANTED:
+               goto dn2entry_retry;
        default:
                if (e != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                }
                if (matched != NULL) {
-                       bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                }
                send_ldap_result( conn, op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                return rc;
        }
 
@@ -123,7 +134,7 @@ bdb_search(
                                ? get_entry_referrals( be, conn, op, matched )
                                : NULL;
 
-                       bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
                        matched = NULL;
 
                        if( erefs ) {
@@ -140,6 +151,7 @@ bdb_search(
                send_ldap_result( conn, op,     rc=LDAP_REFERRAL ,
                        matched_dn.bv_val, text, refs, NULL );
 
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                if ( refs ) ber_bvarray_free( refs );
                if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
                return rc;
@@ -154,7 +166,7 @@ bdb_search(
                erefs = get_entry_referrals( be, conn, op, e );
                refs = NULL;
 
-               bdb_cache_return_entry_r( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
                e = NULL;
 
                if( erefs ) {
@@ -175,6 +187,7 @@ bdb_search(
                        refs ? NULL : "bad referral object",
                        refs, NULL );
 
+               LOCK_ID_FREE (bdb->bi_dbenv, locker );
                ber_bvarray_free( refs );
                ber_memfree( matched_dn.bv_val );
                return 1;
@@ -270,7 +283,7 @@ bdb_search(
        cursor = e->e_id == NOID ? 1 : e->e_id;
 
        if ( e != &slap_entry_root ) {
-               bdb_cache_return_entry_r(&bdb->bi_cache, e);
+               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
        }
        e = NULL;
 
@@ -320,14 +333,18 @@ bdb_search(
                        goto done;
                }
 
+id2entry_retry:
                /* get the entry with reader lock */
-               rc = bdb_id2entry_r( be, NULL, id, &e );
+               rc = bdb_id2entry_r( be, NULL, id, &e, locker, &lock );
 
                if (rc == LDAP_BUSY) {
                        send_ldap_result( conn, op, rc=LDAP_BUSY,
                                NULL, "ldap server busy", NULL, NULL );
                        goto done;
                }
+               else if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) {
+                       goto id2entry_retry;    
+               }
 
                if ( e == NULL ) {
                        if( !BDB_IDL_IS_RANGE(candidates) ) {
@@ -456,7 +473,7 @@ bdb_search(
                        if ( scopeok ) {
                                /* check size limit */
                                if ( --slimit == -1 ) {
-                                       bdb_cache_return_entry_r (&bdb->bi_cache, e);
+                                       bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                                        e = NULL;
                                        send_search_result( conn, op,
                                                rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
@@ -481,7 +498,7 @@ bdb_search(
                                        case 1:         /* entry not sent */
                                                break;
                                        case -1:        /* connection closed */
-                                               bdb_cache_return_entry_r(&bdb->bi_cache, e);
+                                               bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
                                                e = NULL;
                                                rc = LDAP_OTHER;
                                                goto done;
@@ -509,7 +526,7 @@ bdb_search(
 loop_continue:
                if( e != NULL ) {
                        /* free reader lock */
-                        bdb_cache_return_entry_r ( &bdb->bi_cache, e );
+                        bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e , &lock);
                         e = NULL;
                }
 
@@ -524,9 +541,11 @@ loop_continue:
 done:
        if( e != NULL ) {
                /* free reader lock */
-               bdb_cache_return_entry_r ( &bdb->bi_cache, e );
+               bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
        }
 
+       LOCK_ID_FREE (bdb->bi_dbenv, locker );
+
        if( v2refs ) ber_bvarray_free( v2refs );
        if( realbase.bv_val ) ch_free( realbase.bv_val );