]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
ITS#8037 - Add support for relax control to delta-syncrepl
[openldap] / servers / slapd / syncrepl.c
index c020229528af3af19b4793b98534616adb095194..6e157e700c63926a8dd3083c4f79673934ea0cfe 100644 (file)
@@ -162,7 +162,6 @@ static int syncrepl_op_modify( Operation *op, SlapReply *rs );
 /* callback functions */
 static int dn_callback( Operation *, SlapReply * );
 static int nonpresent_callback( Operation *, SlapReply * );
-static int null_callback( Operation *, SlapReply * );
 
 static AttributeDescription *sync_descs[4];
 
@@ -176,6 +175,7 @@ typedef struct logschema {
        struct berval ls_newRdn;
        struct berval ls_delRdn;
        struct berval ls_newSup;
+       struct berval ls_controls;
 } logschema;
 
 static logschema changelog_sc = {
@@ -184,7 +184,8 @@ static logschema changelog_sc = {
        BER_BVC("changes"),
        BER_BVC("newRDN"),
        BER_BVC("deleteOldRDN"),
-       BER_BVC("newSuperior")
+       BER_BVC("newSuperior"),
+       BER_BVC("controls")
 };
 
 static logschema accesslog_sc = {
@@ -193,7 +194,8 @@ static logschema accesslog_sc = {
        BER_BVC("reqMod"),
        BER_BVC("reqNewRDN"),
        BER_BVC("reqDeleteOldRDN"),
-       BER_BVC("reqNewSuperior")
+       BER_BVC("reqNewSuperior"),
+       BER_BVC("reqControls")
 };
 
 static const char *
@@ -409,7 +411,7 @@ ldap_sync_search(
        int rc;
        int rhint;
        char *base;
-       char **attrs, *lattrs[8];
+       char **attrs, *lattrs[9];
        char *filter;
        int attrsonly;
        int scope;
@@ -438,8 +440,9 @@ ldap_sync_search(
                lattrs[3] = ls->ls_newRdn.bv_val;
                lattrs[4] = ls->ls_delRdn.bv_val;
                lattrs[5] = ls->ls_newSup.bv_val;
-               lattrs[6] = slap_schema.si_ad_entryCSN->ad_cname.bv_val;
-               lattrs[7] = NULL;
+               lattrs[6] = ls->ls_controls.bv_val;
+               lattrs[7] = slap_schema.si_ad_entryCSN->ad_cname.bv_val;
+               lattrs[8] = NULL;
 
                rhint = 0;
                base = si->si_logbase.bv_val;
@@ -1795,6 +1798,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;
@@ -2184,11 +2192,8 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
        if ( match < 0 ) {
                Operation op2 = *op;
                AttributeName an[2];
-               const char *text;
                struct berval bv;
-               char *ptr;
-               Modifications *ml;
-               int size, rc;
+               int size;
                SlapReply rs1 = {0};
                resolve_ctxt rx;
                slap_callback cb = { NULL, syncrepl_resolve_cb, NULL, NULL };
@@ -2275,6 +2280,34 @@ syncrepl_op_modify( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
+static int
+syncrepl_null_callback(
+       Operation *op,
+       SlapReply *rs )
+{
+       /* If we're not the last callback in the chain, move to the end */
+       if ( op->o_callback->sc_next ) {
+               slap_callback **sc, *s1;
+               s1 = op->o_callback;
+               op->o_callback = op->o_callback->sc_next;
+               for ( sc = &op->o_callback; *sc; sc = &(*sc)->sc_next ) ;
+               *sc = s1;
+               s1->sc_next = NULL;
+               return SLAP_CB_CONTINUE;
+       }
+       if ( rs->sr_err != LDAP_SUCCESS &&
+               rs->sr_err != LDAP_REFERRAL &&
+               rs->sr_err != LDAP_ALREADY_EXISTS &&
+               rs->sr_err != LDAP_NO_SUCH_OBJECT &&
+               rs->sr_err != LDAP_NOT_ALLOWED_ON_NONLEAF )
+       {
+               Debug( LDAP_DEBUG_ANY,
+                       "syncrepl_null_callback : error code 0x%x\n",
+                       rs->sr_err, 0, 0 );
+       }
+       return LDAP_SUCCESS;
+}
+
 static int
 syncrepl_message_to_op(
        syncinfo_t      *si,
@@ -2286,7 +2319,7 @@ syncrepl_message_to_op(
        Modifications   *modlist = NULL;
        logschema *ls;
        SlapReply rs = { REP_RESULT };
-       slap_callback cb = { NULL, null_callback, NULL, NULL };
+       slap_callback cb = { NULL, syncrepl_null_callback, NULL, NULL };
 
        const char      *text;
        char txtbuf[SLAP_TEXT_BUFLEN];
@@ -2380,6 +2413,22 @@ syncrepl_message_to_op(
                        }
                } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_newSup ) ) {
                        sup = bvals[0];
+               } else if ( !ber_bvstrcasecmp( &bv, &ls->ls_controls ) ) {
+                       int i;
+                       struct berval rel_ctrl_bv;
+
+                       (void)ber_str2bv( "{" LDAP_CONTROL_RELAX, 0, 0, &rel_ctrl_bv );
+                       for ( i = 0; bvals[i].bv_val; i++ ) {
+                               struct berval cbv, tmp;
+
+                               ber_bvchr_post( &cbv, &bvals[i], '}' );
+                               ber_bvchr_post( &tmp, &cbv, '{' );
+                               ber_bvchr_pre( &cbv, &tmp, ' ' );
+                               if ( cbv.bv_len == tmp.bv_len )         /* control w/o value */
+                                       ber_bvchr_pre( &cbv, &tmp, '}' );
+                               if ( !ber_bvcmp( &cbv, &rel_ctrl_bv ) )
+                                       op->o_relax = SLAP_CONTROL_CRITICAL;
+                       }
                } else if ( !ber_bvstrcasecmp( &bv,
                        &slap_schema.si_ad_entryCSN->ad_cname ) )
                {
@@ -3001,7 +3050,7 @@ syncrepl_entry(
                slap_sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx );
        }
 
-       cb.sc_response = null_callback;
+       cb.sc_response = syncrepl_null_callback;
        cb.sc_private = si;
 
        if ( entry && !BER_BVISNULL( &entry->e_name ) ) {
@@ -3421,7 +3470,7 @@ retry_modrdn:;
                                op->o_delete_glue_parent = 0;
                                if ( !be_issuffix( be, &op->o_req_ndn ) ) {
                                        slap_callback cb = { NULL };
-                                       cb.sc_response = slap_null_cb;
+                                       cb.sc_response = syncrepl_null_callback;
                                        dnParent( &op->o_req_ndn, &pdn );
                                        op->o_req_dn = pdn;
                                        op->o_req_ndn = pdn;
@@ -3619,7 +3668,7 @@ syncrepl_del_nonpresent(
                        np_list = LDAP_LIST_NEXT( np_list, npe_link );
                        op->o_tag = LDAP_REQ_DELETE;
                        op->o_callback = &cb;
-                       cb.sc_response = null_callback;
+                       cb.sc_response = syncrepl_null_callback;
                        cb.sc_private = si;
                        op->o_req_dn = *np_prev->npe_name;
                        op->o_req_ndn = *np_prev->npe_nname;
@@ -3661,7 +3710,7 @@ syncrepl_del_nonpresent(
                                op->o_delete_glue_parent = 0;
                                if ( !be_issuffix( be, &op->o_req_ndn ) ) {
                                        slap_callback cb = { NULL };
-                                       cb.sc_response = slap_null_cb;
+                                       cb.sc_response = syncrepl_null_callback;
                                        dnParent( &op->o_req_ndn, &pdn );
                                        op->o_req_dn = pdn;
                                        op->o_req_ndn = pdn;
@@ -3714,7 +3763,7 @@ syncrepl_add_glue_ancestors(
 
        op->o_tag = LDAP_REQ_ADD;
        op->o_callback = &cb;
-       cb.sc_response = null_callback;
+       cb.sc_response = syncrepl_null_callback;
        cb.sc_private = NULL;
 
        dn = e->e_name;
@@ -3856,7 +3905,7 @@ syncrepl_add_glue(
 
        op->o_tag = LDAP_REQ_ADD;
        op->o_callback = &cb;
-       cb.sc_response = null_callback;
+       cb.sc_response = syncrepl_null_callback;
        cb.sc_private = NULL;
 
        op->o_req_dn = e->e_name;
@@ -3968,7 +4017,7 @@ syncrepl_updateCookie(
 
        op->o_tag = LDAP_REQ_MODIFY;
 
-       cb.sc_response = null_callback;
+       cb.sc_response = syncrepl_null_callback;
        cb.sc_private = si;
 
        op->o_callback = &cb;
@@ -4461,24 +4510,6 @@ nonpresent_callback(
        return LDAP_SUCCESS;
 }
 
-static int
-null_callback(
-       Operation*      op,
-       SlapReply*      rs )
-{
-       if ( rs->sr_err != LDAP_SUCCESS &&
-               rs->sr_err != LDAP_REFERRAL &&
-               rs->sr_err != LDAP_ALREADY_EXISTS &&
-               rs->sr_err != LDAP_NO_SUCH_OBJECT &&
-               rs->sr_err != LDAP_NOT_ALLOWED_ON_NONLEAF )
-       {
-               Debug( LDAP_DEBUG_ANY,
-                       "null_callback : error code 0x%x\n",
-                       rs->sr_err, 0, 0 );
-       }
-       return LDAP_SUCCESS;
-}
-
 static struct berval *
 slap_uuidstr_from_normalized(
        struct berval* uuidstr,
@@ -5769,8 +5800,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 );