]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
Fix prev commit
[openldap] / servers / slapd / syncrepl.c
index 9953eee7a94d2602a80a5a788219c4b312b66bfd..ea3da5f929513ec5e2990d86f6fd69234fc3e842 100644 (file)
@@ -434,7 +434,7 @@ do_syncrep2(
        int     rc, err, i;
        ber_len_t       len;
 
-       int rc_efree;
+       int rc_efree = 1;
 
        struct berval   *psub;
        Modifications   *modlist = NULL;
@@ -507,12 +507,14 @@ do_syncrep2(
                                                        syncCookie.octet_str[0].bv_val )
                                                slap_parse_sync_cookie( &syncCookie );
                                }
-                               entry = syncrepl_message_to_entry( si, op, msg,
-                                       &modlist, syncstate );
-                               rc_efree = syncrepl_entry( si, op, entry, modlist, syncstate,
-                                                       &syncUUID, &syncCookie_req );
-                               if ( syncCookie.octet_str && syncCookie.octet_str[0].bv_val ) {
-                                       syncrepl_updateCookie( si, op, psub, &syncCookie );
+                               if ( syncrepl_message_to_entry( si, op, msg,
+                                       &modlist, &entry, syncstate ) == LDAP_SUCCESS ) {
+                                       rc_efree = syncrepl_entry( si, op, entry, modlist,
+                                                               syncstate, &syncUUID, &syncCookie_req );
+                                       if ( syncCookie.octet_str &&
+                                                syncCookie.octet_str[0].bv_val ) {
+                                               syncrepl_updateCookie( si, op, psub, &syncCookie );
+                                       }
                                }
                                ldap_controls_free( rctrls );
                                if ( modlist ) {
@@ -520,6 +522,7 @@ do_syncrep2(
                                }
                                if ( rc_efree && entry ) {
                                        entry_free( entry );
+                                       entry = NULL;
                                }
                                break;
 
@@ -570,7 +573,7 @@ do_syncrep2(
                                                &syncCookie_req.ctxcsn[0], &syncCookie.ctxcsn[0], &text );
                                }
                                if ( syncCookie.octet_str && syncCookie.octet_str->bv_val
-                                        && match < 0 ) {
+                                        && match < 0 && err == LDAP_SUCCESS ) {
                                        syncrepl_updateCookie( si, op, psub, &syncCookie );
                                }
                                if ( rctrls ) {
@@ -581,7 +584,8 @@ do_syncrep2(
                                         *      1) err code : LDAP_BUSY ...
                                         *      2) on err policy : stop service, stop sync, retry
                                         */
-                                       if ( refreshDeletes == 0 && match < 0 ) {
+                                       if ( refreshDeletes == 0 && match < 0 &&
+                                                err == LDAP_SUCCESS ) {
                                                syncrepl_del_nonpresent( op, si );
                                        } else {
                                                avl_free( si->si_presentlist, avl_ber_bvfree );
@@ -894,12 +898,13 @@ do_syncrepl(
        return NULL;
 }
 
-Entry*
+int
 syncrepl_message_to_entry(
        syncinfo_t      *si,
        Operation       *op,
        LDAPMessage     *msg,
        Modifications   **modlist,
+       Entry                   **entry,
        int             syncstate
 )
 {
@@ -926,7 +931,7 @@ syncrepl_message_to_entry(
                Debug( LDAP_DEBUG_ANY,
                        "Message type should be entry (%d)", ldap_msgtype( msg ), 0, 0 );
 #endif
-               return NULL;
+               return -1;
        }
 
        op->o_tag = LDAP_REQ_ADD;
@@ -941,7 +946,7 @@ syncrepl_message_to_entry(
                Debug( LDAP_DEBUG_ANY,
                        "syncrepl_message_to_entry : dn get failed (%d)", rc, 0, 0 );
 #endif
-               return NULL;
+               return rc;
        }
 
        dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx );
@@ -952,10 +957,15 @@ syncrepl_message_to_entry(
 
        if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE )
        {
-               return NULL;
+               return LDAP_SUCCESS;
+       }
+
+       if ( entry == NULL ) {
+               return -1;
        }
 
        e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
+       *entry = e;
        e->e_name = op->o_req_dn;
        e->e_nname = op->o_req_ndn;
 
@@ -1020,9 +1030,14 @@ done:
                e = NULL;
        }
 
-       return e;
+       return rc;
 }
 
+static struct berval uuidbva[] = {
+       BER_BVNULL,
+       BER_BVNULL
+};
+
 int
 syncrepl_entry(
        syncinfo_t* si,
@@ -1046,6 +1061,13 @@ syncrepl_entry(
        int ret = LDAP_SUCCESS;
        const char *text;
 
+       struct berval pdn = { 0, NULL };
+       struct berval org_req_dn = { 0, NULL };
+       struct berval org_req_ndn = { 0, NULL };
+       struct berval org_dn = { 0, NULL };
+       struct berval org_ndn = { 0, NULL };
+       int     org_managedsait;
+
        if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD ))
        {
                syncuuid_bv = ber_dupbv( NULL, syncUUID );
@@ -1072,6 +1094,7 @@ syncrepl_entry(
                syncUUID->bv_val, syncUUID->bv_len );
        op->ors_filterstr.bv_val[op->ors_filterstr.bv_len] = '\0';
 
+       op->o_tag = LDAP_REQ_SEARCH;
        op->ors_scope = LDAP_SCOPE_SUBTREE;
 
        /* get syncrepl cookie of shadow replica from subentry */
@@ -1085,7 +1108,9 @@ syncrepl_entry(
 
        si->si_syncUUID_ndn.bv_val = NULL;
 
-       rc = be->be_search( op, &rs );
+       if ( limits_check( op, &rs ) == 0 ) {
+               rc = be->be_search( op, &rs );
+       }
 
        if ( op->ors_filterstr.bv_val ) {
                sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx );
@@ -1113,6 +1138,39 @@ syncrepl_entry(
                op->o_req_ndn = si->si_syncUUID_ndn;
                op->o_tag = LDAP_REQ_DELETE;
                rc = be->be_delete( op, &rs );
+
+               org_req_dn = op->o_req_dn;
+               org_req_ndn = op->o_req_ndn;
+               org_dn = op->o_dn;
+               org_ndn = op->o_ndn;
+               org_managedsait = get_manageDSAit( op );
+               op->o_dn = op->o_bd->be_rootdn;
+               op->o_ndn = op->o_bd->be_rootndn;
+               op->o_managedsait = 1;
+
+               while ( rs.sr_err == LDAP_SUCCESS &&
+                               op->o_delete_glue_parent ) {
+                       op->o_delete_glue_parent = 0;
+                       if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
+                               slap_callback cb = { NULL };
+                               cb.sc_response = slap_null_cb;
+                               dnParent( &op->o_req_ndn, &pdn );
+                               op->o_req_dn = pdn;
+                               op->o_req_ndn = pdn;
+                               op->o_callback = &cb;
+                               op->o_bd->be_delete( op, &rs );
+                       } else {
+                               break;
+                   }
+               }
+
+               op->o_managedsait = org_managedsait;
+               op->o_dn = org_dn;
+               op->o_ndn = org_ndn;
+               op->o_req_dn = org_req_dn;
+               op->o_req_ndn = org_req_ndn;
+               op->o_delete_glue_parent = 0;
+
                op->o_no_psearch = 0;
        }
 
@@ -1136,10 +1194,26 @@ syncrepl_entry(
 
                        if ( rc != LDAP_SUCCESS ) {
                                if ( rc == LDAP_ALREADY_EXISTS ) {
+                                       Modifications *mod;
+                                       Modifications *modtail;
+
+                                       for ( mod = modlist; mod != NULL; mod = mod->sml_next ) {
+                                               modtail = mod;
+                                       }
+
+                                       mod = (Modifications *)ch_calloc(1, sizeof(Modifications));
+                                       ber_dupbv( &uuidbva[0], syncUUID );
+                                       mod->sml_op = LDAP_MOD_REPLACE;
+                                       mod->sml_desc = slap_schema.si_ad_entryUUID;
+                                       mod->sml_type = mod->sml_desc->ad_cname;
+                                       mod->sml_bvalues = uuidbva;
+                                       modtail->sml_next = mod;
+                                       
                                        op->o_tag = LDAP_REQ_MODIFY;
                                        op->orm_modlist = modlist;
                                        op->o_req_dn = e->e_name;
                                        op->o_req_ndn = e->e_nname;
+
                                        rc = be->be_modify( op, &rs );
                                        if ( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
@@ -1190,7 +1264,7 @@ syncrepl_entry(
 
        case LDAP_SYNC_DELETE :
                /* Already deleted */
-               ret = 1;
+               ret = 0;
                goto done;
 
        default :
@@ -1216,6 +1290,12 @@ done :
        return ret;
 }
 
+static struct berval gcbva[] = {
+       BER_BVC("top"),
+       BER_BVC("glue"),
+       BER_BVNULL
+};
+
 static void
 syncrepl_del_nonpresent(
        Operation *op,
@@ -1226,6 +1306,20 @@ syncrepl_del_nonpresent(
        slap_callback   cb = { NULL };
        SlapReply       rs = {REP_RESULT};
        struct nonpresent_entry *np_list, *np_prev;
+       int rc;
+       Modifications *ml;
+       Modifications *mlnext;
+       Modifications *mod;
+       Modifications *modlist = NULL;
+       Modifications **modtail = &modlist;
+       Attribute       *attr;
+
+       struct berval pdn = { 0, NULL };
+       struct berval org_req_dn = { 0, NULL };
+       struct berval org_req_ndn = { 0, NULL };
+       struct berval org_dn = { 0, NULL };
+       struct berval org_ndn = { 0, NULL };
+       int     org_managedsait;
 
        op->o_req_dn = si->si_base;
        op->o_req_ndn = si->si_base;
@@ -1245,7 +1339,13 @@ syncrepl_del_nonpresent(
        op->ors_filterstr = si->si_filterstr;
 
        op->o_nocaching = 1;
-       be->be_search( op, &rs );
+       op->o_managedsait = 0;
+
+       if ( limits_check( op, &rs ) == 0 ) {
+               be->be_search( op, &rs );
+       }
+
+       op->o_managedsait = 1;
        op->o_nocaching = 0;
 
        if ( op->ors_filter ) filter_free_x( op, op->ors_filter );
@@ -1262,7 +1362,69 @@ syncrepl_del_nonpresent(
                        cb.sc_private = si;
                        op->o_req_dn = *np_prev->npe_name;
                        op->o_req_ndn = *np_prev->npe_nname;
-                       op->o_bd->be_delete( op, &rs );
+                       rc = op->o_bd->be_delete( op, &rs );
+
+                       if ( rc == LDAP_NOT_ALLOWED_ON_NONLEAF ) {
+                               mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
+                               mod->sml_op = LDAP_MOD_REPLACE;
+                               mod->sml_desc = slap_schema.si_ad_objectClass;
+                               mod->sml_type = mod->sml_desc->ad_cname;
+                               mod->sml_bvalues = &gcbva[0];
+                               *modtail = mod;
+                               modtail = &mod->sml_next;
+
+                               mod = (Modifications *) ch_calloc( 1, sizeof( Modifications ));
+                               mod->sml_op = LDAP_MOD_REPLACE;
+                               mod->sml_desc = slap_schema.si_ad_structuralObjectClass;
+                               mod->sml_type = mod->sml_desc->ad_cname;
+                               mod->sml_bvalues = &gcbva[1];
+                               *modtail = mod;
+                               modtail = &mod->sml_next;
+
+                               op->o_tag = LDAP_REQ_MODIFY;
+                               op->orm_modlist = modlist;
+
+                               rc = be->be_modify( op, &rs );
+
+                               for ( ml = modlist; ml != NULL; ml = mlnext ) {
+                                       mlnext = ml->sml_next;
+                                       free( ml );
+                               }
+                       }
+
+                       org_req_dn = op->o_req_dn;
+                       org_req_ndn = op->o_req_ndn;
+                       org_dn = op->o_dn;
+                       org_ndn = op->o_ndn;
+                       org_managedsait = get_manageDSAit( op );
+                       op->o_dn = op->o_bd->be_rootdn;
+                       op->o_ndn = op->o_bd->be_rootndn;
+                       op->o_managedsait = 1;
+
+                       while ( rs.sr_err == LDAP_SUCCESS &&
+                                       op->o_delete_glue_parent ) {
+                               op->o_delete_glue_parent = 0;
+                               if ( !be_issuffix( op->o_bd, &op->o_req_ndn )) {
+                                       slap_callback cb = { NULL };
+                                       cb.sc_response = slap_null_cb;
+                                       dnParent( &op->o_req_ndn, &pdn );
+                                       op->o_req_dn = pdn;
+                                       op->o_req_ndn = pdn;
+                                       op->o_callback = &cb;
+                                       /* give it a root privil ? */
+                                       op->o_bd->be_delete( op, &rs );
+                               } else {
+                                       break;
+                           }
+                       }
+
+                       op->o_managedsait = org_managedsait;
+                       op->o_dn = org_dn;
+                       op->o_ndn = org_ndn;
+                       op->o_req_dn = org_req_dn;
+                       op->o_req_ndn = org_req_ndn;
+                       op->o_delete_glue_parent = 0;
+
                        ber_bvfree( np_prev->npe_name );
                        ber_bvfree( np_prev->npe_nname );
                        op->o_req_dn.bv_val = NULL;
@@ -1275,11 +1437,6 @@ syncrepl_del_nonpresent(
 }
 
 
-static struct berval gcbva[] = {
-       BER_BVC("top"),
-       BER_BVC("glue")
-};
-
 void
 syncrepl_add_glue(
        Operation* op,
@@ -1349,8 +1506,7 @@ syncrepl_add_glue(
                a->a_vals = ch_calloc( 3, sizeof( struct berval ));
                ber_dupbv( &a->a_vals[0], &gcbva[0] );
                ber_dupbv( &a->a_vals[1], &gcbva[1] );
-               a->a_vals[2].bv_len = 0;
-               a->a_vals[2].bv_val = NULL;
+               ber_dupbv( &a->a_vals[2], &gcbva[2] );
 
                a->a_nvals = a->a_vals;
 
@@ -1362,8 +1518,7 @@ syncrepl_add_glue(
 
                a->a_vals = ch_calloc( 2, sizeof( struct berval ));
                ber_dupbv( &a->a_vals[0], &gcbva[1] );
-               a->a_vals[1].bv_len = 0;
-               a->a_vals[1].bv_val = NULL;
+               ber_dupbv( &a->a_vals[1], &gcbva[2] );
 
                a->a_nvals = a->a_vals;
 
@@ -1716,7 +1871,8 @@ null_callback(
        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_NO_SUCH_OBJECT &&
+               rs->sr_err != LDAP_NOT_ALLOWED_ON_NONLEAF )
        {
 #ifdef NEW_LOGGING
                LDAP_LOG( OPERATION, ERR,