From ed5e8db572da8371cc22c8b00f4693df4ba39851 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 18 Oct 2005 21:35:07 +0000 Subject: [PATCH] Eliminate long-lived read transaction, we can just set a cursor's locker ID explicitly to our long-lived locker. Should have thought of this before... --- servers/slapd/back-bdb/cache.c | 114 +---------------------------- servers/slapd/back-bdb/id2entry.c | 12 ++- servers/slapd/back-bdb/proto-bdb.h | 1 + servers/slapd/back-bdb/tools.c | 23 +++--- 4 files changed, 28 insertions(+), 122 deletions(-) diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index eb894b2757..64c2656e78 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -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, <id, 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, <id, 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 ) diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index bb1a955f89..dd427d2ba6 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -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; diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index a71728f6c0..82cb7c1b34 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -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 diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c index c4920f4f3b..3c9761c8e7 100644 --- a/servers/slapd/back-bdb/tools.c +++ b/servers/slapd/back-bdb/tools.c @@ -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) ); -- 2.39.5