X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fsyncrepl.c;h=f10c36b600e72370bfcbf9ce80bfd6d659047fc3;hb=7fe91339dfd08d6c4168c8493f5c1f0faca6ba54;hp=e0b7fb810b692620f2cded785ed9eb4c887b7ccd;hpb=bd49d6dc11ce3c58f29928bede5ecedfafd920f5;p=openldap diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index e0b7fb810b..f10c36b600 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2008 The OpenLDAP Foundation. + * Copyright 2003-2009 The OpenLDAP Foundation. * Portions Copyright 2003 by IBM Corporation. * Portions Copyright 2003-2008 by Howard Chu, Symas Corporation. * All rights reserved. @@ -343,7 +343,7 @@ ldap_sync_search( { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; - LDAPControl c[2], *ctrls[3]; + LDAPControl c[3], *ctrls[4]; int rc; int rhint; char *base; @@ -417,14 +417,19 @@ ldap_sync_search( c[0].ldctl_iscritical = si->si_type < 0; ctrls[0] = &c[0]; + c[1].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT; + BER_BVZERO( &c[1].ldctl_value ); + c[1].ldctl_iscritical = 1; + ctrls[1] = &c[1]; + if ( !BER_BVISNULL( &si->si_bindconf.sb_authzId ) ) { - c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; - c[1].ldctl_value = si->si_bindconf.sb_authzId; - c[1].ldctl_iscritical = 1; - ctrls[1] = &c[1]; - ctrls[2] = NULL; + c[2].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; + c[2].ldctl_value = si->si_bindconf.sb_authzId; + c[2].ldctl_iscritical = 1; + ctrls[2] = &c[2]; + ctrls[3] = NULL; } else { - ctrls[1] = NULL; + ctrls[2] = NULL; } rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly, @@ -583,6 +588,8 @@ do_syncrep1( rc = LDAP_DEREF_NEVER; /* actually could allow DEREF_FINDING */ ldap_set_option( si->si_ld, LDAP_OPT_DEREF, &rc ); + ldap_set_option( si->si_ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); + si->si_syncCookie.rid = si->si_rid; /* whenever there are multiple data sources possible, advertise sid */ @@ -1030,6 +1037,17 @@ do_syncrep2( "LDAP_RES_INTERMEDIATE", "NEW_COOKIE" ); ber_scanf( ber, "tm", &tag, &cookie ); + Debug( LDAP_DEBUG_SYNC, + "do_syncrep2: %s NEW_COOKIE: %s\n", + si->si_ridtxt, + cookie.bv_val, 0); + if ( !BER_BVISNULL( &cookie ) ) { + ch_free( syncCookie.octet_str.bv_val ); + ber_dupbv( &syncCookie.octet_str, &cookie ); + } + if (!BER_BVISNULL( &syncCookie.octet_str ) ) { + slap_parse_sync_cookie( &syncCookie, NULL ); + } break; case LDAP_TAG_SYNC_REFRESH_DELETE: case LDAP_TAG_SYNC_REFRESH_PRESENT: @@ -1142,6 +1160,7 @@ do_syncrep2( if ( match < 0 ) { if ( si->si_refreshPresent == 1 && + si_tag != LDAP_TAG_SYNC_NEW_COOKIE && syncCookie_req.numcsns == syncCookie.numcsns ) { syncrepl_del_nonpresent( op, si, NULL, &syncCookie, m ); @@ -1399,7 +1418,10 @@ reload: if ( !si->si_ctype || !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) { - ldap_pvt_runqueue_remove( &slapd_rq, rtask ); + if ( si->si_re ) { + ldap_pvt_runqueue_remove( &slapd_rq, rtask ); + si->si_re = NULL; + } fail = RETRYNUM_TAIL; } else if ( RETRYNUM_VALID( si->si_retrynum[i] ) ) { if ( si->si_retrynum[i] > 0 ) @@ -1432,22 +1454,9 @@ reload: /* Do final delete cleanup */ if ( !si->si_ctype ) { - cookie_state *cs = NULL; - syncinfo_t **sip; - - cs = be->be_syncinfo->si_cookieState; - for ( sip = &be->be_syncinfo; *sip != si; sip = &(*sip)->si_next ); - *sip = si->si_next; - syncinfo_free( si, 0 ); - if ( !be->be_syncinfo ) { - SLAP_DBFLAGS( be ) &= ~(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SYNC_SHADOW); - if ( cs ) { - ch_free( cs->cs_sids ); - ber_bvarray_free( cs->cs_vals ); - ldap_pvt_thread_mutex_destroy( &cs->cs_mutex ); - ch_free( cs ); - } - } + cookie_state *cs = si->si_cookieState; + syncinfo_free( si, ( !be->be_syncinfo || + be->be_syncinfo->si_cookieState != cs )); } return NULL; } @@ -2086,6 +2095,7 @@ syncrepl_entry( op->o_time = slap_get_time(); op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = 1; + op->ors_limit = NULL; op->ors_attrs = slap_anlist_all_attributes; op->ors_attrsonly = 0; @@ -2097,12 +2107,10 @@ syncrepl_entry( dni.new_entry = entry; dni.modlist = modlist; - if ( limits_check( op, &rs_search ) == 0 ) { - rc = be->be_search( op, &rs_search ); - Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_search (%d)\n", - si->si_ridtxt, rc, 0 ); - } + rc = be->be_search( op, &rs_search ); + Debug( LDAP_DEBUG_SYNC, + "syncrepl_entry: %s be_search (%d)\n", + si->si_ridtxt, rc, 0 ); if ( !BER_BVISNULL( &op->ors_filterstr ) ) { slap_sl_free( op->ors_filterstr.bv_val, op->o_tmpmemctx ); @@ -2571,40 +2579,43 @@ syncrepl_del_nonpresent( si->si_refreshDelete ^= NP_DELETE_ONE; } else { Filter *cf, *of; + Filter mmf[2]; + AttributeAssertion mmaa; memset( &an[0], 0, 2 * sizeof( AttributeName ) ); an[0].an_name = slap_schema.si_ad_entryUUID->ad_cname; an[0].an_desc = slap_schema.si_ad_entryUUID; op->ors_attrs = an; op->ors_slimit = SLAP_NO_LIMIT; + op->ors_tlimit = SLAP_NO_LIMIT; + op->ors_limit = NULL; op->ors_attrsonly = 0; op->ors_filter = str2filter_x( op, si->si_filterstr.bv_val ); /* In multimaster, updates can continue to arrive while * we're searching. Limit the search result to entries - * older than all of our cookie CSNs. + * older than our newest cookie CSN. */ if ( SLAP_MULTIMASTER( op->o_bd )) { Filter *f; int i; - cf = op->o_tmpalloc( (sc->numcsns+1) * sizeof(Filter) + - sc->numcsns * sizeof(AttributeAssertion), op->o_tmpmemctx ); - f = cf; + + f = mmf; f->f_choice = LDAP_FILTER_AND; - f->f_next = NULL; + f->f_next = op->ors_filter; f->f_and = f+1; of = f->f_and; + f = of; + f->f_choice = LDAP_FILTER_LE; + f->f_ava = &mmaa; + f->f_av_desc = slap_schema.si_ad_entryCSN; + f->f_next = NULL; + BER_BVZERO( &f->f_av_value ); for ( i=0; inumcsns; i++ ) { - f = of; - f->f_choice = LDAP_FILTER_LE; - f->f_ava = (AttributeAssertion *)(f+1); - f->f_av_desc = slap_schema.si_ad_entryCSN; - f->f_av_value = sc->ctxcsn[i]; - f->f_next = (Filter *)(f->f_ava+1); - of = f->f_next; + if ( ber_bvcmp( &sc->ctxcsn[i], &f->f_av_value ) > 0 ) + f->f_av_value = sc->ctxcsn[i]; } - f->f_next = op->ors_filter; of = op->ors_filter; - op->ors_filter = cf; + op->ors_filter = mmf; filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); } else { cf = NULL; @@ -2612,11 +2623,9 @@ syncrepl_del_nonpresent( } op->o_nocaching = 1; - if ( limits_check( op, &rs_search ) == 0 ) { - rc = be->be_search( op, &rs_search ); - } + + rc = be->be_search( op, &rs_search ); if ( SLAP_MULTIMASTER( op->o_bd )) { - op->o_tmpfree( cf, op->o_tmpmemctx ); op->ors_filter = of; } if ( op->ors_filter ) filter_free_x( op, op->ors_filter, 1 ); @@ -2878,9 +2887,11 @@ syncrepl_updateCookie( { Backend *be = op->o_bd; Modifications mod; - struct berval first = BER_BVNULL; +#ifdef CHECK_CSN + Syntax *syn = slap_schema.si_ad_contextCSN->ad_type->sat_syntax; +#endif - int rc, i, j; + int rc, i, j, csn_changed = 0; ber_len_t len; slap_callback cb = { NULL }; @@ -2895,6 +2906,15 @@ syncrepl_updateCookie( ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex ); +#ifdef CHECK_CSN + for ( i=0; inumcsns; i++ ) { + assert( !syn->ssyn_validate( syn, syncCookie->ctxcsn+i )); + } + for ( i=0; isi_cookieState->cs_num; i++ ) { + assert( !syn->ssyn_validate( syn, si->si_cookieState->cs_vals+i )); + } +#endif + /* clone the cookieState CSNs so we can Replace the whole thing */ mod.sml_numvals = si->si_cookieState->cs_num; mod.sml_values = op->o_tmpalloc(( mod.sml_numvals+1 )*sizeof(struct berval), op->o_tmpmemctx ); @@ -2913,13 +2933,7 @@ syncrepl_updateCookie( if ( memcmp( syncCookie->ctxcsn[i].bv_val, si->si_cookieState->cs_vals[j].bv_val, len ) > 0 ) { mod.sml_values[j] = syncCookie->ctxcsn[i]; - if ( BER_BVISNULL( &first ) ) { - first = syncCookie->ctxcsn[i]; - - } else if ( memcmp( syncCookie->ctxcsn[i].bv_val, first.bv_val, first.bv_len ) > 0 ) - { - first = syncCookie->ctxcsn[i]; - } + csn_changed = 1; } break; } @@ -2929,23 +2943,16 @@ syncrepl_updateCookie( ( mod.sml_numvals+2 )*sizeof(struct berval), op->o_tmpmemctx ); mod.sml_values[mod.sml_numvals++] = syncCookie->ctxcsn[i]; BER_BVZERO( &mod.sml_values[mod.sml_numvals] ); - if ( BER_BVISNULL( &first ) ) { - first = syncCookie->ctxcsn[i]; - } else if ( memcmp( syncCookie->ctxcsn[i].bv_val, first.bv_val, first.bv_len ) > 0 ) - { - first = syncCookie->ctxcsn[i]; - } + csn_changed = 1; } } /* Should never happen, ITS#5065 */ - if ( BER_BVISNULL( &first )) { + if ( !csn_changed ) { ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex ); op->o_tmpfree( mod.sml_values, op->o_tmpmemctx ); return 0; } op->o_bd = si->si_wbe; - slap_queue_csn( op, &first ); - op->o_tag = LDAP_REQ_MODIFY; cb.sc_response = null_callback; @@ -2997,6 +3004,12 @@ syncrepl_updateCookie( if ( mod.sml_next ) slap_mods_free( mod.sml_next, 1 ); op->o_tmpfree( mod.sml_values, op->o_tmpmemctx ); +#ifdef CHECK_CSN + for ( i=0; isi_cookieState->cs_num; i++ ) { + assert( !syn->ssyn_validate( syn, si->si_cookieState->cs_vals+i )); + } +#endif + return rc; } @@ -3169,33 +3182,39 @@ dn_callback( struct berval old_p, new_p; int is_ctx, new_sup = 0; - /* Make sure new entry is actually newer than old entry */ - old = attr_find( rs->sr_entry->e_attrs, - slap_schema.si_ad_entryCSN ); - new = attr_find( dni->new_entry->e_attrs, - slap_schema.si_ad_entryCSN ); - if ( new && old ) { - int rc; - ber_len_t len = old->a_vals[0].bv_len; - if ( len > new->a_vals[0].bv_len ) - len = new->a_vals[0].bv_len; - rc = memcmp( old->a_vals[0].bv_val, - new->a_vals[0].bv_val, len ); - if ( rc > 0 ) { - Debug( LDAP_DEBUG_SYNC, - "dn_callback : new entry is older than ours " - "%s ours %s, new %s\n", - rs->sr_entry->e_name.bv_val, - old->a_vals[0].bv_val, - new->a_vals[0].bv_val ); - return LDAP_SUCCESS; - } else if ( rc == 0 ) { - Debug( LDAP_DEBUG_SYNC, - "dn_callback : entries have identical CSN " - "%s %s\n", - rs->sr_entry->e_name.bv_val, - old->a_vals[0].bv_val, 0 ); - return LDAP_SUCCESS; + /* If old entry is not a glue entry, make sure new entry + * is actually newer than old entry + */ + if ( !is_entry_glue( rs->sr_entry )) { + old = attr_find( rs->sr_entry->e_attrs, + slap_schema.si_ad_objectClass ); + old = attr_find( rs->sr_entry->e_attrs, + slap_schema.si_ad_entryCSN ); + new = attr_find( dni->new_entry->e_attrs, + slap_schema.si_ad_entryCSN ); + if ( new && old ) { + int rc; + ber_len_t len = old->a_vals[0].bv_len; + if ( len > new->a_vals[0].bv_len ) + len = new->a_vals[0].bv_len; + rc = memcmp( old->a_vals[0].bv_val, + new->a_vals[0].bv_val, len ); + if ( rc > 0 ) { + Debug( LDAP_DEBUG_SYNC, + "dn_callback : new entry is older than ours " + "%s ours %s, new %s\n", + rs->sr_entry->e_name.bv_val, + old->a_vals[0].bv_val, + new->a_vals[0].bv_val ); + return LDAP_SUCCESS; + } else if ( rc == 0 ) { + Debug( LDAP_DEBUG_SYNC, + "dn_callback : entries have identical CSN " + "%s %s\n", + rs->sr_entry->e_name.bv_val, + old->a_vals[0].bv_val, 0 ); + return LDAP_SUCCESS; + } } } @@ -3321,8 +3340,8 @@ dn_callback( * stays co-located with the other mod opattrs. But only * if we know there are other valid mods. */ - if ( old->a_desc == slap_schema.si_ad_modifiersName && - dni->mods ) + if ( dni->mods && ( old->a_desc == slap_schema.si_ad_modifiersName || + old->a_desc == slap_schema.si_ad_modifyTimestamp )) attr_cmp( op, NULL, new, &modtail, &ml ); else attr_cmp( op, old, new, &modtail, &ml ); @@ -4304,13 +4323,22 @@ add_syncrepl( BER_BVISNULL( &si->si_bindconf.sb_uri ) ? "(null)" : si->si_bindconf.sb_uri.bv_val, 0, 0 ); if ( c->be->be_syncinfo ) { + syncinfo_t *sip; + si->si_cookieState = c->be->be_syncinfo->si_cookieState; + + // add new syncrepl to end of list (same order as when deleting) + for ( sip = c->be->be_syncinfo; sip->si_next; sip = sip->si_next ); + sip->si_next = si; } else { si->si_cookieState = ch_calloc( 1, sizeof( cookie_state )); ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex ); + + c->be->be_syncinfo = si; } - si->si_next = c->be->be_syncinfo; - c->be->be_syncinfo = si; + + si->si_next = NULL; + return 0; } } @@ -4507,6 +4535,7 @@ syncrepl_config( ConfigArgs *c ) return 1; } else if ( c->op == LDAP_MOD_DELETE ) { cookie_state *cs = NULL; + int isrunning = 0; if ( c->be->be_syncinfo ) { syncinfo_t *si, **sip; int i; @@ -4515,19 +4544,21 @@ syncrepl_config( ConfigArgs *c ) for ( sip = &c->be->be_syncinfo, i=0; *sip; i++ ) { si = *sip; if ( c->valx == -1 || i == c->valx ) { - int isrunning = 0; *sip = si->si_next; /* If the task is currently active, we have to leave * it running. It will exit on its own. This will only * happen when running on the cn=config DB. */ if ( si->si_re ) { - ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); - isrunning = ldap_pvt_runqueue_isrunning( &slapd_rq, si->si_re ); - ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) { + isrunning = 1; + } else { + ldap_pvt_thread_mutex_unlock( &si->si_mutex ); + } } if ( si->si_re && isrunning ) { si->si_ctype = 0; + si->si_next = NULL; } else { syncinfo_free( si, 0 ); } @@ -4539,8 +4570,9 @@ syncrepl_config( ConfigArgs *c ) } } if ( !c->be->be_syncinfo ) { - SLAP_DBFLAGS( c->be ) &= ~(SLAP_DBFLAG_SHADOW|SLAP_DBFLAG_SYNC_SHADOW); - if ( cs ) { + SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_SHADOW_MASK; + if ( cs && !isrunning ) { + ch_free( cs->cs_sids ); ber_bvarray_free( cs->cs_vals ); ldap_pvt_thread_mutex_destroy( &cs->cs_mutex ); ch_free( cs );