]> git.sur5r.net Git - openldap/commitdiff
Eliminate long-lived read transaction, we can just set a cursor's locker
authorHoward Chu <hyc@openldap.org>
Tue, 18 Oct 2005 21:35:07 +0000 (21:35 +0000)
committerHoward Chu <hyc@openldap.org>
Tue, 18 Oct 2005 21:35:07 +0000 (21:35 +0000)
ID explicitly to our long-lived locker. Should have thought of this before...

servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/tools.c

index eb894b2757826c30f62aca6b2800e53dbf7e4b38..64c2656e786743d31806b4289fa0ea2641365329 100644 (file)
@@ -35,8 +35,6 @@ static int    bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr);
 static void    bdb_lru_print(Cache *cache);
 #endif
 
-static int bdb_txn_get( Operation *op, DB_ENV *env, DB_TXN **txn, int reset );
-
 /* 4.2.52 */
 #if DB_VERSION_FULL == 0x04020034
 #define        READ_TXN_FLAG   ReadFlag
@@ -704,7 +702,7 @@ again:      ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
        /* See if the ID exists in the database; add it to the cache if so */
        if ( !*eip ) {
 #ifndef BDB_HIER
-               rc = bdb_id2entry( op->o_bd, tid, id, &ep );
+               rc = bdb_id2entry( op->o_bd, tid, locker, id, &ep );
                if ( rc == 0 ) {
                        rc = bdb_cache_find_ndn( op, tid,
                                &ep->e_nname, eip );
@@ -752,31 +750,14 @@ load1:
                                bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock );
                        } else if ( rc == 0 ) {
                                if ( load ) {
-                                       DB_TXN *ltid;
-                                       u_int32_t locker2 = locker;
-
-                                       /* We don't wrap entire read operations in txn's, but
-                                        * we need our cache entry lock and any DB page locks
-                                        * to be associated, in order for deadlock detection
-                                        * to work properly. So if we need to read from the DB,
-                                        * we use a long-lived per-thread txn for this step.
-                                        */
-                                       if ( !ep && !tid ) {
-                                               rc = bdb_txn_get( op, bdb->bi_dbenv, &ltid, 0 );
-                                               if ( ltid )
-                                                       locker2 = TXN_ID( ltid );
-                                       } else {
-                                               ltid = tid;
-                                       }
-                                       /* Give up original read lock, obtain write lock with
-                                        * (possibly) new locker ID.
+                                       /* Give up original read lock, obtain write lock
                                         */
                                    if ( rc == 0 ) {
-                                               rc = bdb_cache_entry_db_relock( bdb->bi_dbenv, locker2,
+                                               rc = bdb_cache_entry_db_relock( bdb->bi_dbenv, locker,
                                                        *eip, 1, 0, lock );
                                        }
                                        if ( rc == 0 && !ep) {
-                                               rc = bdb_id2entry( op->o_bd, ltid, id, &ep );
+                                               rc = bdb_id2entry( op->o_bd, tid, locker, id, &ep );
                                        }
                                        if ( rc == 0 ) {
                                                ep->e_private = *eip;
@@ -798,22 +779,6 @@ load1:
                                                /* Otherwise, release the lock. */
                                                bdb_cache_entry_db_unlock( bdb->bi_dbenv, lock );
                                        }
-                                       if ( locker2 != locker ) {
-                                               /* If we're using the per-thread txn, release all
-                                                * of its page locks now.
-                                                */
-                                               DB_LOCKREQ list;
-                                               list.op = DB_LOCK_PUT_ALL;
-                                               list.obj = NULL;
-                                               bdb->bi_dbenv->lock_vec( bdb->bi_dbenv, locker2,
-                                                       0, &list, 1, NULL );
-                                               /* If this txn was deadlocked, we must abort it
-                                                * and invalidate this per-thread txn.
-                                                */
-                                               if ( rc == DB_LOCK_DEADLOCK ) {
-                                                       bdb_txn_get( op, bdb->bi_dbenv, &ltid, 1 );
-                                               }
-                                       }
                                } else if ( !(*eip)->bei_e ) {
                                        /* Some other thread is trying to load the entry,
                                         * give it a chance to finish.
@@ -1282,77 +1247,6 @@ bdb_lru_print( Cache *cache )
 }
 #endif
 
-static void
-bdb_txn_free( void *key, void *data )
-{
-       DB_TXN *txn = data;
-       TXN_ABORT( txn );
-}
-
-/* Obtain a long-lived transaction for the current thread.
- * If reset == 1, remove the current transaction. */
-static int
-bdb_txn_get( Operation *op, DB_ENV *env, DB_TXN **txn, int reset )
-{
-       int i, rc;
-       void *ctx, *data = NULL;
-
-       if ( slapMode & SLAP_TOOL_MODE ) {
-               *txn = NULL;
-               return 0;
-       }
-
-       /* If no op was provided, try to find the ctx anyway... */
-       if ( op ) {
-               ctx = op->o_threadctx;
-       } else {
-               ctx = ldap_pvt_thread_pool_context();
-       }
-
-       /* Shouldn't happen unless we're single-threaded */
-       if ( !ctx ) {
-               *txn = NULL;
-               return 0;
-       }
-
-       if ( reset ) {
-               TXN_ABORT( *txn );
-               return ldap_pvt_thread_pool_setkey( ctx, ((char *)env)+1, NULL, NULL );
-       }
-
-       if ( ldap_pvt_thread_pool_getkey( ctx, ((char *)env)+1, &data, NULL ) ||
-               data == NULL ) {
-               for ( i=0, rc=1; rc != 0 && i<4; i++ ) {
-                       rc = TXN_BEGIN( env, NULL, txn, READ_TXN_FLAG );
-#if DB_VERSION_FULL == 0x04020034
-                       if ( rc == EINVAL && READ_TXN_FLAG ) {
-                               READ_TXN_FLAG = 0;
-                               Debug( LDAP_DEBUG_ANY,
-                                       "bdb_txn_get: BerkeleyDB 4.2.52 library needs TXN patch!\n",
-                                       0, 0, 0 );
-                               i--;
-                               continue;
-                       }
-#endif
-                       if (rc) ldap_pvt_thread_yield();
-               }
-               if ( rc != 0) {
-                       return rc;
-               }
-               if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, ((char *)env)+1,
-                       *txn, bdb_txn_free ) ) ) {
-                       TXN_ABORT( *txn );
-                       Debug( LDAP_DEBUG_ANY, "bdb_txn_get: err %s(%d)\n",
-                               db_strerror(rc), rc, 0 );
-
-                       return rc;
-               }
-       } else {
-               *txn = data;
-       }
-       return 0;
-}
-
 #ifdef BDB_REUSE_LOCKERS
 static void
 bdb_locker_id_free( void *key, void *data )
index bb1a955f8959593d9c365bd23bc0c1e0d127e5ee..dd427d2ba69a4f56a2c9afa78e9d451537cf9c4d 100644 (file)
@@ -92,12 +92,14 @@ int bdb_id2entry_update(
 int bdb_id2entry(
        BackendDB *be,
        DB_TXN *tid,
+       u_int32_t locker,
        ID id,
        Entry **e )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        DB *db = bdb->bi_id2entry->bdi_db;
        DBT key, data;
+       DBC *cursor;
        struct berval bv;
        int rc = 0;
        ID nid;
@@ -113,7 +115,15 @@ int bdb_id2entry(
        data.flags = DB_DBT_MALLOC;
 
        /* fetch it */
-       rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags );
+       rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags );
+       if ( rc ) return rc;
+
+       /* Use our own locker if needed */
+       if ( !tid && locker )
+               cursor->locker = locker;
+
+       rc = cursor->c_get( cursor, &key, &data, DB_SET );
+       cursor->c_close( cursor );
 
        if( rc != 0 ) {
                return rc;
index a71728f6c09c62ff4ea86b36cb3727b5d300ba3f..82cb7c1b34da8cfc2713b031eae611bd283f1c84 100644 (file)
@@ -192,6 +192,7 @@ int bdb_id2entry_delete(
 int bdb_id2entry(
        BackendDB *be,
        DB_TXN *tid,
+       u_int32_t locker,
        ID id,
        Entry **e);
 #endif
index c4920f4f3b8b4b7bc0b82ca71dcc5c9113462e54..3c9761c8e79bf8a94c53e0a1d3d4079c7d766582 100644 (file)
@@ -40,12 +40,23 @@ static Avlnode *index_attrs, index_dummy;
 int bdb_tool_entry_open(
        BackendDB *be, int mode )
 {
+       struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+
        /* initialize key and data thangs */
        DBTzero( &key );
        DBTzero( &data );
        key.flags = DB_DBT_REALLOC;
        data.flags = DB_DBT_REALLOC;
 
+       if (cursor == NULL) {
+               int rc = bdb->bi_id2entry->bdi_db->cursor(
+                       bdb->bi_id2entry->bdi_db, NULL, &cursor,
+                       bdb->bi_db_opflags );
+               if( rc != 0 ) {
+                       return -1;
+               }
+       }
+
        return 0;
 }
 
@@ -94,16 +105,6 @@ ID bdb_tool_entry_next(
        assert( slapMode & SLAP_TOOL_MODE );
        assert( bdb != NULL );
        
-       /* Initialization */
-       if (cursor == NULL) {
-               rc = bdb->bi_id2entry->bdi_db->cursor(
-                       bdb->bi_id2entry->bdi_db, NULL, &cursor,
-                       bdb->bi_db_opflags );
-               if( rc != 0 ) {
-                       return NOID;
-               }
-       }
-
        rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
 
        if( rc != 0 ) {
@@ -165,7 +166,7 @@ int bdb_tool_id2entry_get(
        Entry **e
 )
 {
-       int rc = bdb_id2entry( be, NULL, id, e );
+       int rc = bdb_id2entry( be, NULL, 0, id, e );
 
        if ( rc == DB_NOTFOUND && id == 0 ) {
                Entry *dummy = ch_calloc( 1, sizeof(Entry) );