]> git.sur5r.net Git - openldap/commitdiff
ITS#7904 writewait patch
authorQuanah Gibson-Mount <quanah@openldap.org>
Wed, 23 Jul 2014 20:55:36 +0000 (15:55 -0500)
committerQuanah Gibson-Mount <quanah@openldap.org>
Wed, 23 Jul 2014 20:55:36 +0000 (15:55 -0500)
    Add sc_writewait callback

    Invoked before a blocked writer waits for socket to be writable.
    Use in back-mdb to release reader txn while waiting.

servers/slapd/back-mdb/search.c
servers/slapd/result.c
servers/slapd/slap.h

index 9872c52205d7292bf7ea6974c606742a8d8794e2..c63db9c1640f89373f318f1f201471e582cda9d6 100644 (file)
@@ -316,6 +316,21 @@ static void scope_chunk_ret( Operation *op, ID2 *scopes )
 
 static void *search_stack( Operation *op );
 
+typedef struct ww_ctx {
+       MDB_txn *txn;
+       int flag;
+} ww_ctx;
+
+static void
+mdb_writewait( Operation *op, slap_callback *sc )
+{
+       ww_ctx *ww = sc->sc_private;
+       if ( !ww->flag ) {
+               mdb_txn_reset( ww->txn );
+               ww->flag = 1;
+       }
+}
+
 int
 mdb_search( Operation *op, SlapReply *rs )
 {
@@ -335,6 +350,8 @@ mdb_search( Operation *op, SlapReply *rs )
        int             tentries = 0;
        IdScopes        isc;
        MDB_cursor      *mci, *mcd;
+       ww_ctx wwctx;
+       slap_callback cb = { 0 };
 
        mdb_op_info     opinfo = {{{0}}}, *moi = &opinfo;
        MDB_txn                 *ltid = NULL;
@@ -673,6 +690,16 @@ dn2entry_retry:
                id = mdb_idl_first( candidates, &cursor );
        }
 
+       wwctx.flag = 0;
+       /* If we're running in our own read txn */
+       if (  moi == &opinfo ) {
+               cb.sc_writewait = mdb_writewait;
+               cb.sc_private = &wwctx;
+               wwctx.txn = ltid;
+               cb.sc_next = op->o_callback;
+               op->o_callback = &cb;
+       }
+
        while (id != NOID)
        {
                int scopeok;
@@ -935,6 +962,12 @@ notfound:
                        rs->sr_flags = 0;
 
                        send_search_reference( op, rs );
+                       if ( wwctx.flag ) {
+                               wwctx.flag = 0;
+                               mdb_txn_renew( ltid );
+                               mdb_cursor_renew( ltid, mci );
+                               mdb_cursor_renew( ltid, mcd );
+                       }
 
                        mdb_entry_return( op, e );
                        rs->sr_entry = NULL;
@@ -972,6 +1005,12 @@ notfound:
                                rs->sr_flags = 0;
                                rs->sr_err = LDAP_SUCCESS;
                                rs->sr_err = send_search_entry( op, rs );
+                               if ( wwctx.flag ) {
+                                       wwctx.flag = 0;
+                                       mdb_txn_renew( ltid );
+                                       mdb_cursor_renew( ltid, mci );
+                                       mdb_cursor_renew( ltid, mcd );
+                               }
                                rs->sr_attrs = NULL;
                                rs->sr_entry = NULL;
                                if (e != base)
@@ -1062,6 +1101,17 @@ nochange:
        rs->sr_err = LDAP_SUCCESS;
 
 done:
+       if ( cb.sc_private ) {
+               /* remove our writewait callback */
+               slap_callback **scp = &op->o_callback;
+               while ( *scp ) {
+                       if ( *scp == &cb ) {
+                               *scp = cb.sc_next;
+                               cb.sc_private = NULL;
+                               break;
+                       }
+               }
+       }
        mdb_cursor_close( mcd );
        mdb_cursor_close( mci );
        if ( moi == &opinfo ) {
index 0f1336a17fcbba43cabb0f60259cf2ec89cd7778..35cddc70d6a2f442f30b590f6ee042123bb16a90 100644 (file)
@@ -279,6 +279,22 @@ rs_entry2modifiable( Operation *op, SlapReply *rs, slap_overinst *on )
        return 1;
 }
 
+/* Check for any callbacks that want to be informed about being blocked
+ * on output. These callbacks are expected to leave the callback list
+ * unmodified. Their result is ignored.
+ */
+static void
+slap_writewait_play(
+       Operation *op )
+{
+       slap_callback   *sc = op->o_callback;
+
+       for ( ; sc; sc = sc->sc_next ) {
+               if ( sc->sc_writewait )
+                       sc->sc_writewait( op, sc );
+       }
+}
+
 static long send_ldap_ber(
        Operation *op,
        BerElement *ber )
@@ -348,6 +364,7 @@ static long send_ldap_ber(
                }
 
                /* wait for socket to be write-ready */
+               slap_writewait_play( op );
                ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
                conn->c_writewaiter = 1;
                slapd_set_write( conn->c_sd, 2 );
index 99100dd9f8d64930f250f3ab804e54967e116c77..baf8bc3f6b30b207297a6ac391a9d98f798fdc82 100644 (file)
@@ -2367,10 +2367,14 @@ struct BackendInfo {
 
 typedef int (slap_response)( Operation *, SlapReply * );
 
+struct slap_callback;
+typedef void (slap_writewait)( Operation *, struct slap_callback * );
+
 typedef struct slap_callback {
        struct slap_callback *sc_next;
        slap_response *sc_response;
        slap_response *sc_cleanup;
+       slap_writewait *sc_writewait;
        void *sc_private;
 } slap_callback;