]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/refint.c
Merge remote-tracking branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_5
[openldap] / servers / slapd / overlays / refint.c
index ee7b326091da8782f88c5a42deeb9d483f986aa7..b38e62a2fd57ed8fbdefd3a7bae31481229bd35a 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2004-2012 The OpenLDAP Foundation.
+ * Copyright 2004-2014 The OpenLDAP Foundation.
  * Portions Copyright 2004 Symas Corporation.
  * All rights reserved.
  *
@@ -527,6 +527,7 @@ refint_repair(
        dependent_data  *dp;
        SlapReply               rs = {REP_RESULT};
        Operation               op2;
+       unsigned long   opid;
        int             rc;
 
        op->o_callback->sc_response = refint_search_cb;
@@ -542,7 +543,7 @@ refint_repair(
                Debug( LDAP_DEBUG_TRACE,
                        "refint_repair: search failed: %d\n",
                        rc, 0, 0 );
-               return 0;
+               return rc;
        }
 
        /* safety? paranoid just in case */
@@ -565,6 +566,7 @@ refint_repair(
         *
         */
 
+       opid = op->o_opid;
        op2 = *op;
        for ( dp = rq->attrs; dp; dp = dp->next ) {
                SlapReply       rs2 = {REP_RESULT};
@@ -587,6 +589,7 @@ refint_repair(
                /* Internal ops, never replicate these */
                op2.orm_no_opattrs = 1;
                op2.o_dont_replicate = 1;
+               op2.o_opid = 0;
 
                /* Set our ModifiersName */
                if ( SLAP_LASTMOD( op->o_bd ) ) {
@@ -686,6 +689,7 @@ refint_repair(
                        op2.o_tmpfree( m, op2.o_tmpmemctx );
                }
        }
+       op2.o_opid = opid;
 
        return 0;
 }
@@ -702,6 +706,7 @@ refint_qtask( void *ctx, void *arg )
        Filter ftop, *fptr;
        refint_q *rq;
        refint_attrs *ip;
+       int pausing = 0, rc = 0;
 
        connection_fake_init( &conn, &opbuf, ctx );
        op = &opbuf.ob_op;
@@ -739,6 +744,11 @@ refint_qtask( void *ctx, void *arg )
                dependent_data  *dp, *dp_next;
                refint_attrs *ra, *ra_next;
 
+               if ( ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 ) {
+                       pausing = 1;
+                       break;
+               }
+
                /* Dequeue an op */
                ldap_pvt_thread_mutex_lock( &id->qmutex );
                rq = id->qhead;
@@ -774,7 +784,7 @@ refint_qtask( void *ctx, void *arg )
 
                if ( rq->db != NULL ) {
                        op->o_bd = rq->db;
-                       refint_repair( op, id, rq );
+                       rc = refint_repair( op, id, rq );
 
                } else {
                        BackendDB       *be;
@@ -787,7 +797,7 @@ refint_qtask( void *ctx, void *arg )
 
                                if ( be->be_search && be->be_modify ) {
                                        op->o_bd = be;
-                                       refint_repair( op, id, rq );
+                                       rc = refint_repair( op, id, rq );
                                }
                        }
                }
@@ -807,6 +817,17 @@ refint_qtask( void *ctx, void *arg )
                        op->o_tmpfree( dp, op->o_tmpmemctx );
                }
                op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
+               if ( rc == LDAP_BUSY ) {
+                       pausing = 1;
+                       /* re-queue this op */
+                       ldap_pvt_thread_mutex_lock( &id->qmutex );
+                       rq->next = id->qhead;
+                       id->qhead = rq;
+                       if ( !id->qtail )
+                               id->qtail = rq;
+                       ldap_pvt_thread_mutex_unlock( &id->qmutex );
+                       break;
+               }
 
                if ( !BER_BVISNULL( &rq->newndn )) {
                        ch_free( rq->newndn.bv_val );
@@ -827,7 +848,14 @@ refint_qtask( void *ctx, void *arg )
        /* wait until we get explicitly scheduled again */
        ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
        ldap_pvt_runqueue_stoptask( &slapd_rq, id->qtask );
-       ldap_pvt_runqueue_resched( &slapd_rq,id->qtask, 1 );
+       if ( pausing ) {
+               /* try to run again as soon as the pause is done */
+               id->qtask->interval.tv_sec = 0;
+               ldap_pvt_runqueue_resched( &slapd_rq, id->qtask, 0 );
+               id->qtask->interval.tv_sec = RUNQ_INTERVAL;
+       } else {
+               ldap_pvt_runqueue_resched( &slapd_rq,id->qtask, 1 );
+       }
        ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
 
        return NULL;