]> git.sur5r.net Git - openldap/commitdiff
Use mdb_op_info consistently
authorHoward Chu <hyc@openldap.org>
Wed, 24 Aug 2011 11:03:10 +0000 (04:03 -0700)
committerHoward Chu <hyc@openldap.org>
Wed, 24 Aug 2011 11:03:10 +0000 (04:03 -0700)
14 files changed:
servers/slapd/back-mdb/add.c
servers/slapd/back-mdb/back-mdb.h
servers/slapd/back-mdb/bind.c
servers/slapd/back-mdb/compare.c
servers/slapd/back-mdb/delete.c
servers/slapd/back-mdb/id2entry.c
servers/slapd/back-mdb/init.c
servers/slapd/back-mdb/libmdb
servers/slapd/back-mdb/modify.c
servers/slapd/back-mdb/modrdn.c
servers/slapd/back-mdb/operational.c
servers/slapd/back-mdb/proto-mdb.h
servers/slapd/back-mdb/referral.c
servers/slapd/back-mdb/search.c

index 6fc0e2d60acce94fc78f3eabafdf995031bbeafc..517f476cbfe21491ee050ea986048b1555661a01 100644 (file)
@@ -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 ) {
index ac850f80f2de4fa3754c3e0b37204256ac16f484..7a47218cd9917272ee25ca043e2c52c7ff98d440 100644 (file)
@@ -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 )        \
index c8d0191e570927f807936d3c9bbc68caacb91074..95f017fc232ea6a817a798268f5389ac772a8478 100644 (file)
@@ -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 );
index b27ad9aa905033586cc7e3e3f781cce7d5165784..2b2ddfb981c21339d1e5269aa14f83fd5b7f05d9 100644 (file)
@@ -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 );
index 4223a1e00bb685b2b293c0b4f37ceceb7295ed5e..30edd4ec279d4c0fc7487144b94cc0f208e33b64 100644 (file)
@@ -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 );
index 332161f599a68f7c60b3335c14e4cc6f1599925e..b55611ef74a57b358ac5cbdb68d46330ec888093 100644 (file)
@@ -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;
+}
index bf8cc13675a970814bbb8b45754f246ccce15970..5c8b75148cb9b09824d6655b1abbd945c05f34ea 100644 (file)
@@ -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] ) {
index 55a9c362261183ee455fa5fd4a7e4009ea353077..96aa7f066185995c6465448661217ede44d6b2ef 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 55a9c362261183ee455fa5fd4a7e4009ea353077
+Subproject commit 96aa7f066185995c6465448661217ede44d6b2ef
index cbf150f7c1bba5ac347a8a0765118c1b5eaea689..4340853889b4ab7e87a19afa118cf09f77cdfd9d 100644 (file)
@@ -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 ) {
index f540c7b18adf7f94acdf1ec86dd94fee4fec9701..fc9e04a99cab2bfdfd3d2baf1b9ae20e09ef1f39 100644 (file)
@@ -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 ) {
index f6d24890d2d2ec1c359fe6f0704a4cc785ef736c..d6c16665e0b82e47627cc0e868376ae9b491d76f 100644 (file)
@@ -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;
 }
 
index 6cfd5a3cdcece1982efd433221fb0c9f002ce87a..ed9a3d7c5d9c27e749513d4b7ba38cfb99a98430 100644 (file)
@@ -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
index 41ea285f91c85ecc6c606ba2201cf4c2cc038d80..1c28434f321218eb81356de7f853c6cd0f2afcab 100644 (file)
@@ -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;
 }
index 64da45057e3075a5a482f133715781b6034d7e9d..cb68f4ef0f538ca0a0e8b5c5b590b86e83c2af81 100644 (file)
@@ -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, &ltid );
-
-               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 ) {