From: Howard Chu Date: Sat, 30 Dec 2006 12:05:55 +0000 (+0000) Subject: In bdb_cache_add use a readlock outside the txn to protect the entry X-Git-Tag: OPENLDAP_REL_ENG_2_4_4ALPHA~8^2~292 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=e844a6956d8b3dc1a5bffa9eec20b08c6a6fc624;p=openldap In bdb_cache_add use a readlock outside the txn to protect the entry until send_ldap_result completes. --- diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 41773376f0..274c8f40df 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -35,7 +35,7 @@ bdb_add(Operation *op, SlapReply *rs ) DB_TXN *ltid = NULL, *lt2; struct bdb_op_info opinfo = {0}; int subentry; - u_int32_t locker = 0; + u_int32_t locker = 0, rlocker = 0; DB_LOCK lock; int num_retries = 0; @@ -128,6 +128,9 @@ txnReturn: goto return_results; } + /* Get our thread locker ID */ + rs->sr_err = LOCK_ID( bdb->bi_dbenv, &rlocker ); + if( 0 ) { retry: /* transaction retry */ if( p ) { @@ -424,7 +427,8 @@ retry: /* transaction retry */ nrdn = op->ora_e->e_nname; } - bdb_cache_add( bdb, ei, op->ora_e, &nrdn, locker ); + /* Use the thread locker here, outside the txn */ + bdb_cache_add( bdb, ei, op->ora_e, &nrdn, rlocker, &lock ); if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) { rs->sr_text = "txn_commit failed"; @@ -461,27 +465,26 @@ return_results: } op->o_private = NULL; - if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { - slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); - slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); - } - if( rs->sr_err == LDAP_SUCCESS ) { - EntryInfo *ei = oe->e_private; - /* We own the entry now, and it can be purged at will * Check to make sure it's the same entry we entered with. * Possibly a callback may have mucked with it, although * in general callbacks should treat the entry as read-only. */ + bdb_cache_return_entry_r( bdb->bi_dbenv, &bi->bi_cache, oe, &lock ); if ( op->ora_e == oe ) op->ora_e = NULL; - ei->bei_state ^= CACHE_ENTRY_NOT_LINKED; if ( bdb->bi_txn_cp_kbyte ) { TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); } } + + if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { + slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); + slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); + } + return rs->sr_err; } diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 0c78cd3935..7a652a6e7b 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -886,10 +886,10 @@ bdb_cache_add( EntryInfo *eip, Entry *e, struct berval *nrdn, - u_int32_t locker ) + u_int32_t locker, + DB_LOCK *lock ) { EntryInfo *new, ei; - DB_LOCK lock; int rc; #ifdef BDB_HIER struct berval rdn = e->e_name; @@ -903,7 +903,7 @@ bdb_cache_add( /* Lock this entry so that bdb_add can run to completion. * It can only fail if BDB has run out of lock resources. */ - rc = bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, &ei, 1, 0, &lock ); + rc = bdb_cache_entry_db_lock( bdb->bi_dbenv, locker, &ei, 0, 0, lock ); if ( rc ) { bdb_cache_entryinfo_unlock( eip ); return rc; @@ -931,9 +931,7 @@ bdb_cache_add( } new->bei_e = e; e->e_private = new; - /* Set "Not linked" status so LRU purger ignores it */ - new->bei_state = CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS | - CACHE_ENTRY_NOT_LINKED; + new->bei_state = CACHE_ENTRY_NO_KIDS | CACHE_ENTRY_NO_GRANDKIDS; eip->bei_state &= ~CACHE_ENTRY_NO_KIDS; if (eip->bei_parent) { eip->bei_parent->bei_state &= ~CACHE_ENTRY_NO_GRANDKIDS; diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index cffda2426e..98d840717d 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -499,7 +499,8 @@ int bdb_cache_add( EntryInfo *pei, Entry *e, struct berval *nrdn, - u_int32_t locker + u_int32_t locker, + DB_LOCK *lock ); int bdb_cache_modrdn( struct bdb_info *bdb,