From 2b77736c24f55b282ad2afeee4a7195396eea63d Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 24 Aug 2011 04:03:10 -0700 Subject: [PATCH] Use mdb_op_info consistently --- servers/slapd/back-mdb/add.c | 55 +++---- servers/slapd/back-mdb/back-mdb.h | 8 +- servers/slapd/back-mdb/bind.c | 27 +++- servers/slapd/back-mdb/compare.c | 15 +- servers/slapd/back-mdb/delete.c | 40 +++--- servers/slapd/back-mdb/id2entry.c | 206 +++++++++++++++++++-------- servers/slapd/back-mdb/init.c | 2 - servers/slapd/back-mdb/libmdb | 2 +- servers/slapd/back-mdb/modify.c | 48 ++++--- servers/slapd/back-mdb/modrdn.c | 59 ++++---- servers/slapd/back-mdb/operational.c | 36 ++--- servers/slapd/back-mdb/proto-mdb.h | 2 + servers/slapd/back-mdb/referral.c | 23 ++- servers/slapd/back-mdb/search.c | 52 +++---- 14 files changed, 356 insertions(+), 219 deletions(-) diff --git a/servers/slapd/back-mdb/add.c b/servers/slapd/back-mdb/add.c index 6fc0e2d60a..517f476cbf 100644 --- a/servers/slapd/back-mdb/add.c +++ b/servers/slapd/back-mdb/add.c @@ -33,7 +33,7 @@ mdb_add(Operation *op, SlapReply *rs ) AttributeDescription *entry = slap_schema.si_ad_entry; MDB_txn *txn = NULL; ID eid = NOID, pid = 0; - struct mdb_op_info opinfo = {{{ 0 }}}; + mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; int subentry; int success; @@ -119,7 +119,7 @@ txnReturn: subentry = is_entry_subentry( op->ora_e ); /* begin transaction */ - rs->sr_err = mdb_txn_begin( mdb->mi_dbenv, 0, &txn ); + rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -130,9 +130,7 @@ txnReturn: goto return_results; } - opinfo.moi_oe.oe_key = mdb; - opinfo.moi_txn = txn; - LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.moi_oe, oe_next ); + txn = moi->moi_txn; /* * Get the parent dn and see if the corresponding entry exists. @@ -371,25 +369,26 @@ txnReturn: } } - if ( op->o_noop ) { - mdb_txn_abort( txn ); - rs->sr_err = LDAP_X_NO_OPERATION; - txn = NULL; - goto return_results; - } + if ( moi == &opinfo ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + opinfo.moi_oe.oe_key = NULL; + if ( op->o_noop ) { + mdb_txn_abort( txn ); + rs->sr_err = LDAP_X_NO_OPERATION; + txn = NULL; + goto return_results; + } - if (( rs->sr_err = mdb_txn_commit( txn )) != 0 ) { - rs->sr_text = "txn_commit failed"; - Debug( LDAP_DEBUG_TRACE, - LDAP_XSTRING(mdb_add) ": %s : %s (%d)\n", - rs->sr_text, mdb_strerror(rs->sr_err), rs->sr_err ); - rs->sr_err = LDAP_OTHER; - goto return_results; + if (( rs->sr_err = mdb_txn_commit( txn )) != 0 ) { + rs->sr_text = "txn_commit failed"; + Debug( LDAP_DEBUG_TRACE, + LDAP_XSTRING(mdb_add) ": %s : %s (%d)\n", + rs->sr_text, mdb_strerror(rs->sr_err), rs->sr_err ); + rs->sr_err = LDAP_OTHER; + goto return_results; + } + txn = NULL; } - txn = NULL; - - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); - opinfo.moi_oe.oe_key = NULL; Debug(LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": added%s id=%08lx dn=\"%s\"\n", @@ -403,11 +402,13 @@ return_results: success = rs->sr_err; send_ldap_result( op, rs ); - if( txn != NULL ) { - mdb_txn_abort( txn ); - } - if ( opinfo.moi_oe.oe_key ) { - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + if( moi == &opinfo ) { + if( txn != NULL ) { + mdb_txn_abort( txn ); + } + if ( opinfo.moi_oe.oe_key ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + } } if( success == LDAP_SUCCESS ) { diff --git a/servers/slapd/back-mdb/back-mdb.h b/servers/slapd/back-mdb/back-mdb.h index ac850f80f2..7a47218cd9 100644 --- a/servers/slapd/back-mdb/back-mdb.h +++ b/servers/slapd/back-mdb/back-mdb.h @@ -98,12 +98,14 @@ struct mdb_info { #define mi_dn2id mi_dbis[MDB_DN2ID] #define mi_ad2id mi_dbis[MDB_AD2ID] -struct mdb_op_info { +typedef struct mdb_op_info { OpExtra moi_oe; MDB_txn* moi_txn; + int moi_ref; char moi_flag; -}; -#define MOI_DONTFREE 1 +} mdb_op_info; +#define MOI_READER 0x01 +#define MOI_FREEIT 0x02 /* Copy an ID "src" to pointer "dst" in big-endian byte order */ #define MDB_ID2DISK( src, dst ) \ diff --git a/servers/slapd/back-mdb/bind.c b/servers/slapd/back-mdb/bind.c index c8d0191e57..95f017fc23 100644 --- a/servers/slapd/back-mdb/bind.c +++ b/servers/slapd/back-mdb/bind.c @@ -32,6 +32,7 @@ mdb_bind( Operation *op, SlapReply *rs ) AttributeDescription *password = slap_schema.si_ad_userPassword; MDB_txn *rtxn; + mdb_op_info opinfo = {0}, *moi = &opinfo; Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(mdb_bind) ": dn: %s\n", @@ -53,7 +54,7 @@ mdb_bind( Operation *op, SlapReply *rs ) break; } - rs->sr_err = mdb_reader_get(op, mdb->mi_dbenv, &rtxn); + rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi); switch(rs->sr_err) { case 0: break; @@ -63,22 +64,24 @@ mdb_bind( Operation *op, SlapReply *rs ) return rs->sr_err; } + rtxn = moi->moi_txn; + /* get entry with reader lock */ rs->sr_err = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 0 ); switch(rs->sr_err) { case MDB_NOTFOUND: rs->sr_err = LDAP_INVALID_CREDENTIALS; - send_ldap_result( op, rs ); - return rs->sr_err; + goto done; case 0: break; case LDAP_BUSY: - send_ldap_error( op, rs, LDAP_BUSY, "ldap_server_busy" ); - return LDAP_BUSY; + rs->sr_text = "ldap_server_busy"; + goto done; default: - send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); - return rs->sr_err; + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; + goto done; } ber_dupbv( &op->oq_bind.rb_edn, &e->e_name ); @@ -132,6 +135,16 @@ mdb_bind( Operation *op, SlapReply *rs ) } done: + moi->moi_ref--; + if ( moi->moi_ref < 1 ) { + if ( moi->moi_flag & MOI_READER ) { + mdb_txn_reset( moi->moi_txn ); + } /* writers can abort themselves */ + LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); + if ( moi->moi_flag & MOI_FREEIT ) { + op->o_tmpfree( moi, op->o_tmpmemctx ); + } + } /* free entry and reader lock */ if( e != NULL ) { mdb_entry_return( e ); diff --git a/servers/slapd/back-mdb/compare.c b/servers/slapd/back-mdb/compare.c index b27ad9aa90..2b2ddfb981 100644 --- a/servers/slapd/back-mdb/compare.c +++ b/servers/slapd/back-mdb/compare.c @@ -29,8 +29,9 @@ mdb_compare( Operation *op, SlapReply *rs ) int manageDSAit = get_manageDSAit( op ); MDB_txn *rtxn; + mdb_op_info opinfo = {0}, *moi = &opinfo; - rs->sr_err = mdb_reader_get(op, mdb->mi_dbenv, &rtxn); + rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi); switch(rs->sr_err) { case 0: break; @@ -39,6 +40,8 @@ mdb_compare( Operation *op, SlapReply *rs ) return rs->sr_err; } + rtxn = moi->moi_txn; + /* get entry */ rs->sr_err = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 1 ); switch( rs->sr_err ) { @@ -120,6 +123,16 @@ return_results: } done: + moi->moi_ref--; + if ( moi->moi_ref < 1 ) { + if ( moi->moi_flag & MOI_READER ) { + mdb_txn_reset( moi->moi_txn ); + } /* writers can abort themselves */ + LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); + if ( moi->moi_flag & MOI_FREEIT ) { + op->o_tmpfree( moi, op->o_tmpmemctx ); + } + } /* free entry */ if ( e != NULL ) { mdb_entry_return( e ); diff --git a/servers/slapd/back-mdb/delete.c b/servers/slapd/back-mdb/delete.c index 4223a1e00b..30edd4ec27 100644 --- a/servers/slapd/back-mdb/delete.c +++ b/servers/slapd/back-mdb/delete.c @@ -33,7 +33,7 @@ mdb_delete( Operation *op, SlapReply *rs ) AttributeDescription *children = slap_schema.si_ad_children; AttributeDescription *entry = slap_schema.si_ad_entry; MDB_txn *txn = NULL; - struct mdb_op_info opinfo = {{{ 0 }}}; + mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; LDAPControl **preread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; @@ -100,7 +100,7 @@ txnReturn: } /* begin transaction */ - rs->sr_err = mdb_txn_begin( mdb->mi_dbenv, 0, &txn ); + rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -111,9 +111,7 @@ txnReturn: goto return_results; } - opinfo.moi_oe.oe_key = mdb; - opinfo.moi_txn = txn; - LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.moi_oe, oe_next ); + txn = moi->moi_txn; if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &pdn ); @@ -389,17 +387,19 @@ txnReturn: p = NULL; } - if( op->o_noop ) { - mdb_txn_abort( txn ); - rs->sr_err = LDAP_X_NO_OPERATION; - txn = NULL; - goto return_results; - } else { - rs->sr_err = mdb_txn_commit( txn ); + if( moi == &opinfo ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + opinfo.moi_oe.oe_key = NULL; + if( op->o_noop ) { + mdb_txn_abort( txn ); + rs->sr_err = LDAP_X_NO_OPERATION; + txn = NULL; + goto return_results; + } else { + rs->sr_err = mdb_txn_commit( txn ); + } txn = NULL; } - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); - opinfo.moi_oe.oe_key = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -434,11 +434,13 @@ return_results: mdb_entry_return( e ); } - if( txn != NULL ) { - mdb_txn_abort( txn ); - } - if ( opinfo.moi_oe.oe_key ) { - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + if( moi == &opinfo ) { + if( txn != NULL ) { + mdb_txn_abort( txn ); + } + if ( opinfo.moi_oe.oe_key ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + } } send_ldap_result( op, rs ); diff --git a/servers/slapd/back-mdb/id2entry.c b/servers/slapd/back-mdb/id2entry.c index 332161f599..b55611ef74 100644 --- a/servers/slapd/back-mdb/id2entry.c +++ b/servers/slapd/back-mdb/id2entry.c @@ -154,60 +154,33 @@ int mdb_entry_release( Entry *e, int rw ) { -#if 0 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; - struct mdb_op_info *moi; - OpExtra *oex; + struct mdb_op_info *moi = NULL; + MDB_txn *txn = NULL; + int rc; /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE, SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */ + mdb_entry_return ( e ); if ( slapMode == SLAP_SERVER_MODE ) { - /* If not in our cache, just free it */ - if ( !e->e_private ) { - return mdb_entry_return( e ); - } - /* free entry and reader or writer lock */ - LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { - if ( oex->oe_key == mdb ) break; - } - moi = (struct mdb_op_info *)oex; - - /* lock is freed with txn */ - if ( !moi || moi->moi_txn ) { - mdb_unlocked_cache_return_entry_rw( mdb, e, rw ); - } else { - struct mdb_lock_info *bli, *prev; - for ( prev=(struct mdb_lock_info *)&moi->boi_locks, - bli = boi->boi_locks; bli; prev=bli, bli=bli->bli_next ) { - if ( bli->bli_id == e->e_id ) { - mdb_cache_return_entry_rw( mdb, e, rw, &bli->bli_lock ); - prev->bli_next = bli->bli_next; - /* Cleanup, or let caller know we unlocked */ - if ( bli->bli_flag & BLI_DONTFREE ) - bli->bli_flag = 0; - else - op->o_tmpfree( bli, op->o_tmpmemctx ); - break; - } + rc = mdb_opinfo_get( op, mdb, 1, &moi ); + if ( rc ) + return rc; + + moi->moi_ref--; + if ( moi->moi_ref < 1 ) { + if ( moi->moi_flag & MOI_READER ) { + mdb_txn_reset( moi->moi_txn ); } - if ( !boi->boi_locks ) { - LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next ); - if ( !(boi->boi_flag & BOI_DONTFREE)) - op->o_tmpfree( boi, op->o_tmpmemctx ); + LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); + if ( moi->moi_flag & MOI_FREEIT ) { + op->o_tmpfree( moi, op->o_tmpmemctx ); } } - } else { - if (e->e_private != NULL) - BEI(e)->bei_e = NULL; - e->e_private = NULL; - mdb_entry_return ( e ); } return 0; -#else - return mdb_entry_return( e ); -#endif } /* return LDAP_SUCCESS IFF we can retrieve the specified entry. @@ -233,25 +206,10 @@ int mdb_entry_get( "=> mdb_entry_get: oc: \"%s\", at: \"%s\"\n", oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); - if( op ) { - OpExtra *oex; - LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { - if ( oex->oe_key == mdb ) break; - } - moi = (struct mdb_op_info *)oex; - if ( moi ) - txn = moi->moi_txn; - } - - if ( !txn ) { - rc = mdb_reader_get( op, mdb->mi_dbenv, &txn ); - switch(rc) { - case 0: - break; - default: - return LDAP_OTHER; - } - } + rc = mdb_opinfo_get( op, mdb, 0, &moi ); + if ( rc ) + return LDAP_OTHER; + txn = moi->moi_txn; /* can we find entry */ rc = mdb_dn2entry( op, txn, ndn, &e, 0 ); @@ -304,3 +262,129 @@ return_results: rc, 0, 0 ); return(rc); } + +static void +mdb_reader_free( void *key, void *data ) +{ + MDB_txn *txn = data; + + if ( txn ) mdb_txn_abort( txn ); +} + +/* free up any keys used by the main thread */ +void +mdb_reader_flush( MDB_env *env ) +{ + void *data; + void *ctx = ldap_pvt_thread_pool_context(); + + if ( !ldap_pvt_thread_pool_getkey( ctx, env, &data, NULL ) ) { + ldap_pvt_thread_pool_setkey( ctx, env, NULL, 0, NULL, NULL ); + mdb_reader_free( env, data ); + } +} + +int +mdb_opinfo_get( Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **moip ) +{ + int rc; + void *data; + void *ctx; + mdb_op_info *moi = NULL; + OpExtra *oex; + + if ( !mdb || !moip ) return -1; + + /* If no op was provided, try to find the ctx anyway... */ + if ( op ) { + ctx = op->o_threadctx; + } else { + ctx = ldap_pvt_thread_pool_context(); + } + + if ( op ) { + LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { + if ( oex->oe_key == mdb ) break; + } + moi = (mdb_op_info *)oex; + } + + if ( !moi ) { + moi = *moip; + + if ( !moi ) { + if ( op ) { + moi = op->o_tmpalloc(sizeof(struct mdb_op_info),op->o_tmpmemctx); + LDAP_SLIST_INSERT_HEAD( &op->o_extra, &moi->moi_oe, oe_next ); + } else { + moi = ch_malloc(sizeof(mdb_op_info)); + } + moi->moi_flag = MOI_FREEIT; + *moip = moi; + } + moi->moi_oe.oe_key = mdb; + moi->moi_ref = 0; + moi->moi_txn = NULL; + } + + if ( !rdonly ) { + /* This op started as a reader, but now wants to write. */ + if ( moi->moi_flag & MOI_READER ) { + moi = *moip; + LDAP_SLIST_INSERT_HEAD( &op->o_extra, &moi->moi_oe, oe_next ); + } else { + /* This op is continuing an existing write txn */ + *moip = moi; + } + moi->moi_ref++; + if ( !moi->moi_txn ) { + rc = mdb_txn_begin( mdb->mi_dbenv, 1, &moi->moi_txn ); + if (rc) { + Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n", + mdb_strerror(rc), rc, 0 ); + } + return rc; + } + return 0; + } + + /* OK, this is a reader */ + if ( !moi->moi_txn ) { + if ( !ctx ) { + /* Shouldn't happen unless we're single-threaded */ + rc = mdb_txn_begin( mdb->mi_dbenv, 1, &moi->moi_txn ); + if (rc) { + Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n", + mdb_strerror(rc), rc, 0 ); + } + return rc; + } + if ( ldap_pvt_thread_pool_getkey( ctx, mdb->mi_dbenv, &data, NULL ) ) { + rc = mdb_txn_begin( mdb->mi_dbenv, 1, &moi->moi_txn ); + if (rc) { + Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: err %s(%d)\n", + mdb_strerror(rc), rc, 0 ); + return rc; + } + data = moi->moi_txn; + if ( ( rc = ldap_pvt_thread_pool_setkey( ctx, mdb->mi_dbenv, + data, mdb_reader_free, NULL, NULL ) ) ) { + mdb_txn_abort( moi->moi_txn ); + moi->moi_txn = NULL; + Debug( LDAP_DEBUG_ANY, "mdb_opinfo_get: thread_pool_setkey failed err (%d)\n", + rc, 0, 0 ); + return rc; + } + } else { + moi->moi_txn = data; + } + } else { + if ( moi->moi_ref < 1 ) { + moi->moi_ref = 0; + mdb_txn_renew( moi->moi_txn ); + } + } + moi->moi_ref++; + + return 0; +} diff --git a/servers/slapd/back-mdb/init.c b/servers/slapd/back-mdb/init.c index bf8cc13675..5c8b75148c 100644 --- a/servers/slapd/back-mdb/init.c +++ b/servers/slapd/back-mdb/init.c @@ -247,11 +247,9 @@ mdb_db_close( BackendDB *be, ConfigReply *cr ) mdb->mi_flags &= ~MDB_IS_OPEN; -#if 0 if( mdb->mi_dbenv ) { mdb_reader_flush( mdb->mi_dbenv ); } -#endif if ( mdb->mi_dbenv ) { if ( mdb->mi_dbis[0] ) { diff --git a/servers/slapd/back-mdb/libmdb b/servers/slapd/back-mdb/libmdb index 55a9c36226..96aa7f0661 160000 --- a/servers/slapd/back-mdb/libmdb +++ b/servers/slapd/back-mdb/libmdb @@ -1 +1 @@ -Subproject commit 55a9c362261183ee455fa5fd4a7e4009ea353077 +Subproject commit 96aa7f066185995c6465448661217ede44d6b2ef diff --git a/servers/slapd/back-mdb/modify.c b/servers/slapd/back-mdb/modify.c index cbf150f7c1..4340853889 100644 --- a/servers/slapd/back-mdb/modify.c +++ b/servers/slapd/back-mdb/modify.c @@ -402,7 +402,7 @@ mdb_modify( Operation *op, SlapReply *rs ) char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; MDB_txn *txn = NULL; - struct mdb_op_info opinfo = {{{ 0 }}}; + mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; Entry dummy = {0}; LDAPControl **preread_ctrl = NULL; @@ -466,7 +466,7 @@ txnReturn: } /* begin transaction */ - rs->sr_err = mdb_txn_begin( mdb->mi_dbenv, 0, &txn ); + rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -477,9 +477,7 @@ txnReturn: goto return_results; } - opinfo.moi_oe.oe_key = mdb; - opinfo.moi_txn = txn; - LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.moi_oe, oe_next ); + txn = moi->moi_txn; /* get entry or ancestor */ rs->sr_err = mdb_dn2entry( op, txn, &op->o_req_ndn, &e, 1 ); @@ -610,21 +608,23 @@ txnReturn: } } - if( op->o_noop ) { - mdb_txn_abort( txn ); - rs->sr_err = LDAP_X_NO_OPERATION; - txn = NULL; - /* Only free attrs if they were dup'd. */ - if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL; - goto return_results; - } else { - dummy.e_attrs = NULL; + if( moi == &opinfo ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + opinfo.moi_oe.oe_key = NULL; + if( op->o_noop ) { + mdb_txn_abort( txn ); + rs->sr_err = LDAP_X_NO_OPERATION; + txn = NULL; + /* Only free attrs if they were dup'd. */ + if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL; + goto return_results; + } else { + dummy.e_attrs = NULL; - rs->sr_err = mdb_txn_commit( txn ); + rs->sr_err = mdb_txn_commit( txn ); + txn = NULL; + } } - txn = NULL; - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); - opinfo.moi_oe.oe_key = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -662,11 +662,13 @@ return_results: done: slap_graduate_commit_csn( op ); - if( txn != NULL ) { - mdb_txn_abort( txn ); - } - if ( opinfo.moi_oe.oe_key ) { - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + if( moi == &opinfo ) { + if( txn != NULL ) { + mdb_txn_abort( txn ); + } + if ( opinfo.moi_oe.oe_key ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + } } if( e != NULL ) { diff --git a/servers/slapd/back-mdb/modrdn.c b/servers/slapd/back-mdb/modrdn.c index f540c7b18a..fc9e04a99c 100644 --- a/servers/slapd/back-mdb/modrdn.c +++ b/servers/slapd/back-mdb/modrdn.c @@ -35,7 +35,7 @@ mdb_modrdn( Operation *op, SlapReply *rs ) char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; MDB_txn *txn = NULL; - struct mdb_op_info opinfo = {{{ 0 }}}; + struct mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; Entry dummy = {0}; Entry *np = NULL; /* newSuperior Entry */ @@ -105,7 +105,7 @@ txnReturn: slap_mods_opattrs( op, &op->orr_modlist, 1 ); /* begin transaction */ - rs->sr_err = mdb_txn_begin( mdb->mi_dbenv, 0, &txn ); + rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, @@ -116,9 +116,7 @@ txnReturn: goto return_results; } - opinfo.moi_oe.oe_key = mdb; - opinfo.moi_txn = txn; - LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.moi_oe, oe_next ); + txn = moi->moi_txn; if ( be_issuffix( op->o_bd, &e->e_nname ) ) { #ifdef MDB_MULTIPLE_SUFFIXES @@ -551,30 +549,31 @@ txnReturn: } } - if( op->o_noop ) { - mdb_txn_abort( txn ); - rs->sr_err = LDAP_X_NO_OPERATION; - txn = NULL; - /* Only free attrs if they were dup'd. */ - if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL; - goto return_results; - - } else { - dummy.e_attrs = NULL; - new_dn.bv_val = NULL; - new_ndn.bv_val = NULL; + if( moi == &opinfo ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + opinfo.moi_oe.oe_key = NULL; + if( op->o_noop ) { + mdb_txn_abort( txn ); + rs->sr_err = LDAP_X_NO_OPERATION; + txn = NULL; + /* Only free attrs if they were dup'd. */ + if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL; + goto return_results; - if(( rs->sr_err=mdb_txn_commit( txn )) != 0 ) { - rs->sr_text = "txn_commit failed"; } else { - rs->sr_err = LDAP_SUCCESS; + dummy.e_attrs = NULL; + new_dn.bv_val = NULL; + new_ndn.bv_val = NULL; + + if(( rs->sr_err=mdb_txn_commit( txn )) != 0 ) { + rs->sr_text = "txn_commit failed"; + } else { + rs->sr_err = LDAP_SUCCESS; + } + txn = NULL; } } - txn = NULL; - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); - opinfo.moi_oe.oe_key = NULL; - if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_modrdn) ": %s : %s (%d)\n", @@ -631,11 +630,13 @@ done: mdb_entry_return( e ); } - if( txn != NULL ) { - mdb_txn_abort( txn ); - } - if ( opinfo.moi_oe.oe_key ) { - LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + if( moi == &opinfo ) { + if( txn != NULL ) { + mdb_txn_abort( txn ); + } + if ( opinfo.moi_oe.oe_key ) { + LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); + } } if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { diff --git a/servers/slapd/back-mdb/operational.c b/servers/slapd/back-mdb/operational.c index f6d24890d2..d6c16665e0 100644 --- a/servers/slapd/back-mdb/operational.c +++ b/servers/slapd/back-mdb/operational.c @@ -35,29 +35,23 @@ mdb_hasSubordinates( int *hasSubordinates ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; - struct mdb_op_info *opinfo; - OpExtra *oex; MDB_txn *rtxn; + mdb_op_info opinfo = {0}, *moi = &opinfo; int rc; assert( e != NULL ); - /* Check for a txn in a parent op, otherwise use reader txn */ - LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { - if ( oex->oe_key == mdb ) - break; - } - opinfo = (struct mdb_op_info *) oex; - if ( opinfo && opinfo->moi_txn ) { - rtxn = opinfo->moi_txn; - } else { - rc = mdb_reader_get(op, mdb->mi_dbenv, &rtxn); - if ( rc ) { - rc = LDAP_OTHER; - goto done; - } + rc = mdb_opinfo_get(op, mdb, 1, &moi); + switch(rc) { + case 0: + break; + default: + rc = LDAP_OTHER; + goto done; } + rtxn = moi->moi_txn; + rc = mdb_dn2id_children( op, rtxn, e ); switch( rc ) { @@ -79,6 +73,16 @@ mdb_hasSubordinates( } done:; + moi->moi_ref--; + if ( moi->moi_ref < 1 ) { + if ( moi->moi_flag & MOI_READER ) { + mdb_txn_reset( moi->moi_txn ); + } /* writers can abort themselves */ + LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); + if ( moi->moi_flag & MOI_FREEIT ) { + op->o_tmpfree( moi, op->o_tmpmemctx ); + } + } return rc; } diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h index 6cfd5a3cdc..ed9a3d7c5d 100644 --- a/servers/slapd/back-mdb/proto-mdb.h +++ b/servers/slapd/back-mdb/proto-mdb.h @@ -174,6 +174,8 @@ int mdb_entry_return( Entry *e ); BI_entry_release_rw mdb_entry_release; BI_entry_get_rw mdb_entry_get; +void mdb_reader_flush( MDB_env *env ); +int mdb_opinfo_get( Operation *op, struct mdb_info *mdb, int rdonly, mdb_op_info **moi ); /* * idl.c diff --git a/servers/slapd/back-mdb/referral.c b/servers/slapd/back-mdb/referral.c index 41ea285f91..1c28434f32 100644 --- a/servers/slapd/back-mdb/referral.c +++ b/servers/slapd/back-mdb/referral.c @@ -28,6 +28,7 @@ mdb_referrals( Operation *op, SlapReply *rs ) int rc = LDAP_SUCCESS; MDB_txn *rtxn; + mdb_op_info opinfo = {0}, *moi = &opinfo; if( op->o_tag == LDAP_REQ_SEARCH ) { /* let search take care of itself */ @@ -39,7 +40,7 @@ mdb_referrals( Operation *op, SlapReply *rs ) return rc; } - rc = mdb_reader_get(op, mdb->mi_dbenv, &rtxn); + rc = mdb_opinfo_get(op, mdb, 1, &moi); switch(rc) { case 0: break; @@ -47,6 +48,8 @@ mdb_referrals( Operation *op, SlapReply *rs ) return LDAP_OTHER; } + rtxn = moi->moi_txn; + /* get entry */ rc = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 1 ); @@ -56,14 +59,15 @@ mdb_referrals( Operation *op, SlapReply *rs ) break; case LDAP_BUSY: rs->sr_text = "ldap server busy"; - return LDAP_BUSY; + goto done; default: Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_referrals) ": dn2entry failed: %s (%d)\n", mdb_strerror(rc), rc, 0 ); rs->sr_text = "internal error"; - return LDAP_OTHER; + rc = LDAP_OTHER; + goto done; } if ( rc == MDB_NOTFOUND ) { @@ -105,7 +109,7 @@ mdb_referrals( Operation *op, SlapReply *rs ) op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx ); rs->sr_matched = NULL; } - return rc; + goto done; } if ( is_entry_referral( e ) ) { @@ -134,6 +138,17 @@ mdb_referrals( Operation *op, SlapReply *rs ) ber_bvarray_free( refs ); } +done: + moi->moi_ref--; + if ( moi->moi_ref < 1 ) { + if ( moi->moi_flag & MOI_READER ) { + mdb_txn_reset( moi->moi_txn ); + } /* writers can abort themselves */ + LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); + if ( moi->moi_flag & MOI_FREEIT ) { + op->o_tmpfree( moi, op->o_tmpmemctx ); + } + } mdb_entry_return( e ); return rc; } diff --git a/servers/slapd/back-mdb/search.c b/servers/slapd/back-mdb/search.c index 64da45057e..cb68f4ef0f 100644 --- a/servers/slapd/back-mdb/search.c +++ b/servers/slapd/back-mdb/search.c @@ -293,36 +293,26 @@ mdb_search( Operation *op, SlapReply *rs ) int manageDSAit; int tentries = 0; - struct mdb_op_info *opinfo = NULL; + mdb_op_info opinfo = {0}, *moi = &opinfo; MDB_txn *ltid = NULL; MDB_cursor *idcursor = NULL; - OpExtra *oex; Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(mdb_search) "\n", 0, 0, 0); attrs = op->oq_search.rs_attrs; - LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { - if ( oex->oe_key == mdb ) - break; - } - opinfo = (struct mdb_op_info *) oex; - manageDSAit = get_manageDSAit( op ); - if ( opinfo && opinfo->moi_txn ) { - ltid = opinfo->moi_txn; - } else { - rs->sr_err = mdb_reader_get( op, mdb->mi_dbenv, <id ); - - switch(rs->sr_err) { - case 0: - break; - default: - send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); - return rs->sr_err; - } + rs->sr_err = mdb_opinfo_get( op, mdb, 1, &moi ); + switch(rs->sr_err) { + case 0: + break; + default: + send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); + return rs->sr_err; } + ltid = moi->moi_txn; + if ( op->ors_deref & LDAP_DEREF_FINDING ) { MDB_IDL_ZERO(candidates); } @@ -338,10 +328,10 @@ dn2entry_retry: break; case LDAP_BUSY: send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" ); - return LDAP_BUSY; + goto done; default: send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); - return rs->sr_err; + goto done; } if ( op->ors_deref & LDAP_DEREF_FINDING ) { @@ -415,7 +405,7 @@ dn2entry_retry: ber_memfree( matched_dn.bv_val ); rs->sr_matched = NULL; } - return rs->sr_err; + goto done; } /* NOTE: __NEW__ "search" access is required @@ -431,7 +421,7 @@ dn2entry_retry: mdb_entry_return(e); send_ldap_result( op, rs ); - return rs->sr_err; + goto done; } if ( !manageDSAit && is_entry_referral( e ) ) { @@ -468,7 +458,7 @@ dn2entry_retry: rs->sr_ref = NULL; ber_memfree( matched_dn.bv_val ); rs->sr_matched = NULL; - return 1; + goto done; } if ( get_assert( op ) && @@ -477,7 +467,7 @@ dn2entry_retry: rs->sr_err = LDAP_ASSERTION_FAILED; mdb_entry_return(e); send_ldap_result( op, rs ); - return 1; + goto done; } /* compute it anyway; root does not use it */ @@ -820,6 +810,16 @@ nochange: rs->sr_err = LDAP_SUCCESS; done: + moi->moi_ref--; + if ( moi->moi_ref < 1 ) { + if ( moi->moi_flag & MOI_READER ) { + mdb_txn_reset( moi->moi_txn ); + } /* writers can abort themselves */ + LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); + if ( moi->moi_flag & MOI_FREEIT ) { + op->o_tmpfree( moi, op->o_tmpmemctx ); + } + } if( idcursor ) mdb_cursor_close( idcursor ); if( rs->sr_v2ref ) { -- 2.39.5