]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
Fix autoca schema init
[openldap] / servers / slapd / syncrepl.c
index 255ca5bcc7deec260acfe581ce1ca75acccf504c..91f4d3a6b75e73bf4ea498e83e2e4cb4e7a320e0 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2015 The OpenLDAP Foundation.
+ * Copyright 2003-2017 The OpenLDAP Foundation.
  * Portions Copyright 2003 by IBM Corporation.
  * Portions Copyright 2003-2008 by Howard Chu, Symas Corporation.
  * All rights reserved.
@@ -82,8 +82,9 @@ typedef struct syncinfo_s {
        struct berval           si_base;
        struct berval           si_logbase;
        struct berval           si_filterstr;
-       Filter                  *si_filter;
        struct berval           si_logfilterstr;
+       Filter                  *si_filter;
+       Filter                  *si_logfilter;
        struct berval           si_contextdn;
        int                     si_scope;
        int                     si_attrsonly;
@@ -110,6 +111,10 @@ typedef struct syncinfo_s {
        int                     si_refreshDelete;
        int                     si_refreshPresent;
        int                     si_refreshDone;
+       int                     si_refreshCount;
+       time_t          si_refreshBeg;
+       time_t          si_refreshEnd;
+       OpExtra         *si_refreshTxn;
        int                     si_syncdata;
        int                     si_logstate;
        int                     si_lazyCommit;
@@ -736,6 +741,11 @@ do_syncrep1(
        }
 
        si->si_refreshDone = 0;
+       si->si_refreshBeg = slap_get_time();
+       si->si_refreshCount = 0;
+       si->si_refreshTxn = NULL;
+       Debug( LDAP_DEBUG_ANY, "do_syncrep1: %s starting refresh\n",
+               si->si_ridtxt, 0, 0 );
 
        rc = ldap_sync_search( si, op->o_tmpmemctx );
 
@@ -935,6 +945,10 @@ do_syncrep2(
                                                check_syncprov( op, si );
                                                ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
                                                for ( i =0; i<si->si_cookieState->cs_num; i++ ) {
+#ifdef CHATTY_SYNCLOG
+                                                       Debug( LDAP_DEBUG_SYNC, "do_syncrep2: %s CSN for sid %d: %s\n",
+                                                               si->si_ridtxt, i, si->si_cookieState->cs_vals[i].bv_val );
+#endif
                                                        /* new SID */
                                                        if ( sid < si->si_cookieState->cs_sids[i] )
                                                                break;
@@ -1186,6 +1200,13 @@ do_syncrep2(
                        {
                                rc = syncrepl_updateCookie( si, op, &syncCookie );
                        }
+                       if ( si->si_refreshCount ) {
+                               LDAP_SLIST_REMOVE( &op->o_extra, si->si_refreshTxn, OpExtra, oe_next );
+                               op->o_bd->bd_info->bi_op_txn( op, SLAP_TXN_COMMIT, &si->si_refreshTxn );
+                               si->si_refreshCount = 0;
+                               si->si_refreshTxn = NULL;
+                       }
+                       si->si_refreshEnd = slap_get_time();
                        if ( err == LDAP_SUCCESS
                                && si->si_logstate == SYNCLOG_FALLBACK ) {
                                si->si_logstate = SYNCLOG_LOGGING;
@@ -1267,6 +1288,17 @@ do_syncrep2(
                                        {
                                                si->si_refreshDone = 1;
                                        }
+                                       if ( si->si_refreshDone ) {
+                                               if ( si->si_refreshCount ) {
+                                                       LDAP_SLIST_REMOVE( &op->o_extra, si->si_refreshTxn, OpExtra, oe_next );
+                                                       op->o_bd->bd_info->bi_op_txn( op, SLAP_TXN_COMMIT, &si->si_refreshTxn );
+                                                       si->si_refreshCount = 0;
+                                                       si->si_refreshTxn = NULL;
+                                               }
+                                               si->si_refreshEnd = slap_get_time();
+       Debug( LDAP_DEBUG_ANY, "do_syncrep1: %s finished refresh\n",
+               si->si_ridtxt, 0, 0 );
+                                       }
                                        ber_scanf( ber, /*"{"*/ "}" );
                                        if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST &&
                                                si->si_refreshDone )
@@ -1397,6 +1429,12 @@ do_syncrep2(
                if ( ldap_pvt_thread_pool_pausing( &connection_pool )) {
                        slap_sync_cookie_free( &syncCookie, 0 );
                        slap_sync_cookie_free( &syncCookie_req, 0 );
+                       if ( si->si_refreshCount ) {
+                               LDAP_SLIST_REMOVE( &op->o_extra, si->si_refreshTxn, OpExtra, oe_next );
+                               op->o_bd->bd_info->bi_op_txn( op, SLAP_TXN_COMMIT, &si->si_refreshTxn );
+                               si->si_refreshCount = 0;
+                               si->si_refreshTxn = NULL;
+                       }
                        return SYNC_PAUSED;
                }
        }
@@ -1757,6 +1795,11 @@ syncrepl_accesslog_mods(
                if ( !colon ) {
                        /* Invalid */
                        continue;
+               } else if ( colon == bv.bv_val ) {
+                       /* ITS#6545: An empty attribute signals that a new mod
+                        * is about to start */
+                       mod = NULL;
+                       continue;
                }
 
                bv.bv_len = colon - bv.bv_val;
@@ -2065,6 +2108,33 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
        if ( !mod )
                return SLAP_CB_CONTINUE;
 
+       {
+               int i, sid;
+               sid = slap_parse_csn_sid( &mod->sml_nvalues[0] );
+               ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
+               for ( i =0; i<si->si_cookieState->cs_num; i++ ) {
+#ifdef CHATTY_SYNCLOG
+                       Debug( LDAP_DEBUG_SYNC, "syncrepl_op_modify: %s CSN for sid %d: %s\n",
+                               si->si_ridtxt, i, si->si_cookieState->cs_vals[i].bv_val );
+#endif
+                       /* new SID */
+                       if ( sid < si->si_cookieState->cs_sids[i] )
+                               break;
+                       if ( si->si_cookieState->cs_sids[i] == sid ) {
+                               if ( ber_bvcmp( &mod->sml_nvalues[0], &si->si_cookieState->cs_vals[i] ) <= 0 ) {
+                                       Debug( LDAP_DEBUG_SYNC, "syncrepl_op_modify: %s entryCSN too old, ignoring %s (%s)\n",
+                                               si->si_ridtxt, mod->sml_nvalues[0].bv_val, op->o_req_dn.bv_val );
+                                       ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+                                       slap_graduate_commit_csn( op );
+                                       /* tell accesslog this was a failure */
+                                       rs->sr_err = LDAP_TYPE_OR_VALUE_EXISTS;
+                                       return LDAP_SUCCESS;
+                               }
+                       }
+               }
+               ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+       }
+
        rc = overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on );
        if ( rc == 0 ) {
                Attribute *a;
@@ -2078,6 +2148,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
        }
        /* equal? Should never happen */
        if ( match == 0 ) {
+               slap_graduate_commit_csn( op );
                /* tell accesslog this was a failure */
                rs->sr_err = LDAP_TYPE_OR_VALUE_EXISTS;
                return LDAP_SUCCESS;
@@ -2126,6 +2197,8 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
                SlapReply rs1 = {0};
                resolve_ctxt rx;
                slap_callback cb = { NULL, syncrepl_resolve_cb, NULL, NULL };
+        Filter lf[3] = {0};
+        AttributeAssertion aa[2] = {0};
 
                rx.rx_si = si;
                rx.rx_mods = newlist;
@@ -2153,7 +2226,21 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
                op2.ors_filterstr.bv_len = sprintf(op2.ors_filterstr.bv_val,
                        "(&(entryCSN>=%s)(reqDN=%s)%s)",
                        bv.bv_val, op->o_req_ndn.bv_val, si->si_logfilterstr.bv_val );
-               op2.ors_filter = str2filter_x( op, op2.ors_filterstr.bv_val );
+
+        lf[0].f_choice = LDAP_FILTER_AND;
+        lf[0].f_and = lf+1;
+        lf[1].f_choice = LDAP_FILTER_GE;
+        lf[1].f_ava = aa;
+        lf[1].f_av_desc = slap_schema.si_ad_entryCSN;
+        lf[1].f_av_value = bv;
+        lf[1].f_next = lf+2;
+        lf[2].f_choice = LDAP_FILTER_EQUALITY;
+        lf[2].f_ava = aa+1;
+        lf[2].f_av_desc = ad_reqDN;
+        lf[2].f_av_value = op->o_req_ndn;
+        lf[2].f_next = si->si_logfilter;
+
+               op2.ors_filter = lf;
 
                op2.o_callback = &cb;
                op2.o_bd = select_backend( &op2.o_req_ndn, 1 );
@@ -2171,6 +2258,7 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
                sc->sc_private = mx;
                sc->sc_next = op->o_callback;
                sc->sc_cleanup = NULL;
+               sc->sc_writewait = NULL;
                op->o_callback = sc;
                op->orm_no_opattrs = 1;
                mx->mx_orig = op->orm_modlist;
@@ -2751,6 +2839,9 @@ presentlist_find(
        Avlnode **a2 = (Avlnode **)av;
        unsigned short s;
 
+       if (!av)
+               return NULL;
+
        memcpy(&s, val->bv_val, 2);
        return avl_find( a2[s], val->bv_val+2, syncuuid_cmp );
 #else
@@ -2933,8 +3024,22 @@ syncrepl_entry(
                slap_queue_csn( op, syncCSN );
        }
 
-       if ( !si->si_refreshDone && si->si_lazyCommit )
-               op->o_lazyCommit = SLAP_CONTROL_NONCRITICAL;
+       if ( !si->si_refreshDone ) {
+               if ( si->si_lazyCommit )
+                       op->o_lazyCommit = SLAP_CONTROL_NONCRITICAL;
+               if ( si->si_refreshCount == 500 ) {
+                       LDAP_SLIST_REMOVE( &op->o_extra, si->si_refreshTxn, OpExtra, oe_next );
+                       op->o_bd->bd_info->bi_op_txn( op, SLAP_TXN_COMMIT, &si->si_refreshTxn );
+                       si->si_refreshCount = 0;
+                       si->si_refreshTxn = NULL;
+               }
+               if ( op->o_bd->bd_info->bi_op_txn ) {
+                       if ( !si->si_refreshCount ) {
+                               op->o_bd->bd_info->bi_op_txn( op, SLAP_TXN_BEGIN, &si->si_refreshTxn );
+                       }
+                       si->si_refreshCount++;
+               }
+       }
 
        slap_op_time( &op->o_time, &op->o_tincr );
        switch ( syncstate ) {
@@ -4535,6 +4640,9 @@ syncinfo_free( syncinfo_t *sie, int free_all )
                if ( sie->si_logfilterstr.bv_val ) {
                        ch_free( sie->si_logfilterstr.bv_val );
                }
+               if ( sie->si_logfilter ) {
+                       filter_free( sie->si_logfilter );
+               }
                if ( sie->si_base.bv_val ) {
                        ch_free( sie->si_base.bv_val );
                }
@@ -5256,6 +5364,15 @@ parse_syncrepl_line(
                return 1;
        }
 
+       if ( si->si_got & GOT_LOGFILTER ) {
+               si->si_logfilter = str2filter( si->si_logfilterstr.bv_val );
+               if ( si->si_logfilter == NULL ) {
+                       Debug( LDAP_DEBUG_ANY, "syncrepl %s " SEARCHBASESTR "=\"%s\": unable to parse logfilter=\"%s\"\n", 
+                               si->si_ridtxt, c->be->be_suffix ? c->be->be_suffix[ 0 ].bv_val : "(null)", si->si_logfilterstr.bv_val );
+                       return 1;
+               }
+       }
+
        return 0;
 }
 
@@ -5637,7 +5754,7 @@ syncrepl_config( ConfigArgs *c )
                                         * happen when running on the cn=config DB.
                                         */
                                        if ( si->si_re ) {
-                                               if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
+                                               if ( si->si_be == c->be || ldap_pvt_thread_mutex_trylock( &si->si_mutex )) {
                                                        isrunning = 1;
                                                } else {
                                                        /* There is no active thread, but we must still
@@ -5657,8 +5774,7 @@ syncrepl_config( ConfigArgs *c )
                                                                ldap_pvt_runqueue_stoptask( &slapd_rq, re );
                                                                isrunning = 1;
                                                        }
-                                                       if ( ldap_pvt_thread_pool_retract( &connection_pool,
-                                                                       re->routine, re ) > 0 )
+                                                       if ( ldap_pvt_thread_pool_retract( re->pool_cookie ) > 0 )
                                                                isrunning = 0;
 
                                                        ldap_pvt_runqueue_remove( &slapd_rq, re );