diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index b95397f4726c330a0f6a8408b0b09b7a4a7317e6..f10c36b600e72370bfcbf9ce80bfd6d659047fc3 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -41,7 +41,6 @@ typedef struct cookie_state { ldap_pvt_thread_mutex_t cs_mutex; int cs_num; int cs_age; - int cs_ref; struct berval *cs_vals; int *cs_sids; } cookie_state; @@ -864,7 +863,6 @@ do_syncrep2( } } } - op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie; } } rc = 0; @@ -971,7 +969,6 @@ do_syncrep2( if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { slap_parse_sync_cookie( &syncCookie, NULL ); - op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie; } } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) @@ -1050,7 +1047,6 @@ do_syncrep2( } if (!BER_BVISNULL( &syncCookie.octet_str ) ) { slap_parse_sync_cookie( &syncCookie, NULL ); - op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie; } break; case LDAP_TAG_SYNC_REFRESH_DELETE: @@ -1081,7 +1077,6 @@ do_syncrep2( if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { slap_parse_sync_cookie( &syncCookie, NULL ); - op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie; } } /* Defaults to TRUE */ @@ -1117,7 +1112,6 @@ do_syncrep2( if ( !BER_BVISNULL( &syncCookie.octet_str ) ) { slap_parse_sync_cookie( &syncCookie, NULL ); - op->o_controls[slap_cids.sc_LDAPsync] = &syncCookie; compare_csns( &syncCookie_req, &syncCookie, &m ); } } @@ -1256,27 +1250,16 @@ do_syncrepl( int rc = LDAP_SUCCESS; int dostop = 0; ber_socket_t s; - int i, defer = 1, fail = 0, freeinfo = 0; + int i, defer = 1, fail = 0; Backend *be; - if ( si == NULL ) - return NULL; - if ( slapd_shutdown ) - return NULL; - Debug( LDAP_DEBUG_TRACE, "=>do_syncrepl %s\n", si->si_ridtxt, 0, 0 ); - /* Don't get stuck here while a pause is initiated */ - while ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) { - if ( slapd_shutdown ) - return NULL; - if ( !ldap_pvt_thread_pool_pausecheck( &connection_pool )) - ldap_pvt_thread_yield(); - } + if ( si == NULL ) + return NULL; - if ( si->si_ctype < 1 ) { - goto deleted; - } + /* There will never be more than one instance active */ + ldap_pvt_thread_mutex_lock( &si->si_mutex ); switch( abs( si->si_type ) ) { case LDAP_SYNC_REFRESH_ONLY: @@ -1303,6 +1286,10 @@ do_syncrepl( connection_fake_init( &conn, &opbuf, ctx ); op = &opbuf.ob_op; + /* use global malloc for now */ + op->o_tmpmemctx = NULL; + op->o_tmpmfuncs = &ch_mfuncs; + op->o_managedsait = SLAP_CONTROL_NONCRITICAL; be = si->si_be; @@ -1361,13 +1348,8 @@ reload: goto reload; } -deleted: /* We got deleted while running on cn=config */ - if ( si->si_ctype < 1 ) { - if ( si->si_ctype == -1 ) { - si->si_ctype = 0; - freeinfo = 1; - } + if ( !si->si_ctype ) { if ( si->si_conn ) dostop = 1; rc = -1; @@ -1434,7 +1416,7 @@ deleted: break; } - if ( si->si_ctype < 1 + if ( !si->si_ctype || !si->si_retrynum || si->si_retrynum[i] == RETRYNUM_TAIL ) { if ( si->si_re ) { ldap_pvt_runqueue_remove( &slapd_rq, rtask ); @@ -1457,22 +1439,24 @@ deleted: if ( rc ) { if ( fail == RETRYNUM_TAIL ) { Debug( LDAP_DEBUG_ANY, - "do_syncrepl: %s rc %d quitting\n", - si->si_ridtxt, rc, 0 ); + "do_syncrepl: %s quitting\n", + si->si_ridtxt, 0, 0 ); } else if ( fail > 0 ) { Debug( LDAP_DEBUG_ANY, - "do_syncrepl: %s rc %d retrying (%d retries left)\n", - si->si_ridtxt, rc, fail ); + "do_syncrepl: %s retrying (%d retries left)\n", + si->si_ridtxt, fail, 0 ); } else { Debug( LDAP_DEBUG_ANY, - "do_syncrepl: %s rc %d retrying\n", - si->si_ridtxt, rc, 0 ); + "do_syncrepl: %s retrying\n", + si->si_ridtxt, 0, 0 ); } } /* Do final delete cleanup */ - if ( freeinfo ) { - syncinfo_free( si, 0 ); + if ( !si->si_ctype ) { + cookie_state *cs = si->si_cookieState; + syncinfo_free( si, ( !be->be_syncinfo || + be->be_syncinfo->si_cookieState != cs )); } return NULL; } @@ -1594,7 +1578,6 @@ syncrepl_message_to_op( prdn = BER_BVNULL, nrdn = BER_BVNULL, psup = BER_BVNULL, nsup = BER_BVNULL; int rc, deleteOldRdn = 0, freeReqDn = 0; - int do_graduate = 0; if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) { Debug( LDAP_DEBUG_ANY, "syncrepl_message_to_op: %s " @@ -1627,16 +1610,7 @@ syncrepl_message_to_op( if ( !ber_bvstrcasecmp( &bv, &ls->ls_dn ) ) { bdn = bvals[0]; - rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_ANY, - "syncrepl_message_to_op: %s " - "dn \"%s\" normalization failed (%d)", - si->si_ridtxt, bdn.bv_val, rc ); - rc = -1; - ch_free( bvals ); - goto done; - } + dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); ber_dupbv( &op->o_req_dn, &dn ); ber_dupbv( &op->o_req_ndn, &ndn ); slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); @@ -1672,7 +1646,6 @@ syncrepl_message_to_op( &slap_schema.si_ad_entryCSN->ad_cname ) ) { slap_queue_csn( op, bvals ); - do_graduate = 1; } ch_free( bvals ); } @@ -1717,7 +1690,6 @@ syncrepl_message_to_op( Debug( LDAP_DEBUG_SYNC, "syncrepl_message_to_op: %s be_add %s (%d)\n", si->si_ridtxt, op->o_req_dn.bv_val, rc ); - do_graduate = 0; } if ( e == op->ora_e ) be_entry_release_w( op, op->ora_e ); @@ -1730,7 +1702,6 @@ syncrepl_message_to_op( "syncrepl_message_to_op: %s be_modify %s (%d)\n", si->si_ridtxt, op->o_req_dn.bv_val, rc ); op->o_bd = si->si_be; - do_graduate = 0; } break; case LDAP_REQ_MODRDN: @@ -1774,19 +1745,16 @@ syncrepl_message_to_op( Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC, "syncrepl_message_to_op: %s be_modrdn %s (%d)\n", si->si_ridtxt, op->o_req_dn.bv_val, rc ); - do_graduate = 0; break; case LDAP_REQ_DELETE: rc = op->o_bd->be_delete( op, &rs ); Debug( rc ? LDAP_DEBUG_ANY : LDAP_DEBUG_SYNC, "syncrepl_message_to_op: %s be_delete %s (%d)\n", si->si_ridtxt, op->o_req_dn.bv_val, rc ); - do_graduate = 0; break; } done: - if ( do_graduate ) - slap_graduate_commit_csn( op ); + slap_graduate_commit_csn( op ); op->o_bd = si->si_be; op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_csn ); @@ -1868,21 +1836,7 @@ syncrepl_message_to_entry( return -1; } - rc = dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - /* One of the things that could happen is that the schema - * is not lined-up; this could result in unknown attributes. - * A value non conformant to the syntax should be unlikely, - * except when replicating between different versions - * of the software, or when syntax validation bugs are fixed - */ - Debug( LDAP_DEBUG_ANY, - "syncrepl_message_to_entry: " - "%s dn \"%s\" normalization failed (%d)", - si->si_ridtxt, bdn.bv_val, rc ); - return rc; - } - + dnPrettyNormal( NULL, &bdn, &dn, &ndn, op->o_tmpmemctx ); ber_dupbv( &op->o_req_dn, &dn ); ber_dupbv( &op->o_req_ndn, &ndn ); slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); @@ -2210,8 +2164,8 @@ retry_add:; rc = op->o_bd->be_add( op, &rs_add ); Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_add %s (%d)\n", - si->si_ridtxt, op->o_req_dn.bv_val, rc ); + "syncrepl_entry: %s be_add (%d)\n", + si->si_ridtxt, rc, 0 ); switch ( rs_add.sr_err ) { case LDAP_SUCCESS: if ( op->ora_e == entry ) { @@ -2273,11 +2227,10 @@ retry_add:; default: Debug( LDAP_DEBUG_ANY, - "syncrepl_entry: %s be_add %s failed (%d)\n", - si->si_ridtxt, op->o_req_dn.bv_val, rs_add.sr_err ); + "syncrepl_entry: %s be_add failed (%d)\n", + si->si_ridtxt, rs_add.sr_err, 0 ); break; } - syncCSN = NULL; op->o_bd = be; goto done; } @@ -2368,12 +2321,6 @@ retry_add:; break; } } - if ( !mod->sml_numvals ) { - /* Drop this op */ - *ml = mod->sml_next; - mod->sml_next = NULL; - slap_mods_free( mod, 1 ); - } break; } } @@ -2413,7 +2360,7 @@ retry_add:; } } } - + /* RDNs must be NUL-terminated for back-ldap */ noldp = op->orr_newrdn; ber_dupbv_x( &op->orr_newrdn, &noldp, op->o_tmpmemctx ); @@ -2470,16 +2417,14 @@ retry_add:; slap_mods_free( op->orr_modlist, 1 ); Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_modrdn %s (%d)\n", - si->si_ridtxt, op->o_req_dn.bv_val, rc ); + "syncrepl_entry: %s be_modrdn (%d)\n", + si->si_ridtxt, rc, 0 ); op->o_bd = be; /* Renamed entries may still have other mods so just fallthru */ op->o_req_dn = entry->e_name; op->o_req_ndn = entry->e_nname; /* Use CSN on the modify */ - if ( just_rename ) - syncCSN = NULL; - else if ( syncCSN ) + if ( syncCSN && !just_rename ) slap_queue_csn( op, syncCSN ); } if ( dni.mods ) { @@ -2492,23 +2437,18 @@ retry_add:; slap_mods_free( op->orm_modlist, 1 ); op->orm_no_opattrs = 0; Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_modify %s (%d)\n", - si->si_ridtxt, op->o_req_dn.bv_val, rc ); + "syncrepl_entry: %s be_modify (%d)\n", + si->si_ridtxt, rc, 0 ); if ( rs_modify.sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "syncrepl_entry: %s be_modify failed (%d)\n", si->si_ridtxt, rs_modify.sr_err, 0 ); } - syncCSN = NULL; op->o_bd = be; } else if ( !dni.renamed ) { Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: %s entry unchanged, ignored (%s)\n", si->si_ridtxt, op->o_req_dn.bv_val, 0 ); - if ( syncCSN ) { - slap_graduate_commit_csn( op ); - syncCSN = NULL; - } } goto done; case LDAP_SYNC_DELETE : @@ -2519,8 +2459,8 @@ retry_add:; op->o_bd = si->si_wbe; rc = op->o_bd->be_delete( op, &rs_delete ); Debug( LDAP_DEBUG_SYNC, - "syncrepl_entry: %s be_delete %s (%d)\n", - si->si_ridtxt, op->o_req_dn.bv_val, rc ); + "syncrepl_entry: %s be_delete (%d)\n", + si->si_ridtxt, rc, 0 ); while ( rs_delete.sr_err == LDAP_SUCCESS && op->o_delete_glue_parent ) { @@ -2537,7 +2477,6 @@ retry_add:; break; } } - syncCSN = NULL; op->o_bd = be; } goto done; @@ -2948,12 +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 }; @@ -2995,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; } @@ -3011,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; @@ -3088,10 +3013,6 @@ syncrepl_updateCookie( return rc; } -/* Compare the attribute from the old entry to the one in the new - * entry. The Modifications from the new entry will either be left - * in place, or changed to an Add or Delete as needed. - */ static void attr_cmp( Operation *op, Attribute *old, Attribute *new, Modifications ***mret, Modifications ***mcur ) @@ -3235,86 +3156,6 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new, *mret = modtail; } -/* Generate a set of modifications to change the old entry into the - * new one. On input ml is a list of modifications equivalent to - * the new entry. It will be massaged and the result will be stored - * in mods. - */ -void syncrepl_diff_entry( Operation *op, Attribute *old, Attribute *new, - Modifications **mods, Modifications **ml, int is_ctx) -{ - Modifications **modtail = mods; - - /* We assume that attributes are saved in the same order - * in the remote and local databases. So if we walk through - * the attributeDescriptions one by one they should match in - * lock step. If not, look for an add or delete. - */ - while ( old && new ) - { - /* If we've seen this before, use its mod now */ - if ( new->a_flags & SLAP_ATTR_IXADD ) { - attr_cmp( op, NULL, new, &modtail, &ml ); - new = new->a_next; - continue; - } - /* Skip contextCSN */ - if ( is_ctx && old->a_desc == - slap_schema.si_ad_contextCSN ) { - old = old->a_next; - continue; - } - - if ( old->a_desc != new->a_desc ) { - Modifications *mod; - Attribute *tmp; - - /* If it's just been re-added later, - * remember that we've seen it. - */ - tmp = attr_find( new, old->a_desc ); - if ( tmp ) { - tmp->a_flags |= SLAP_ATTR_IXADD; - } else { - /* If it's a new attribute, pull it in. - */ - tmp = attr_find( old, new->a_desc ); - if ( !tmp ) { - attr_cmp( op, NULL, new, &modtail, &ml ); - new = new->a_next; - continue; - } - /* Delete old attr */ - mod = ch_malloc( sizeof( Modifications ) ); - mod->sml_op = LDAP_MOD_DELETE; - mod->sml_flags = 0; - mod->sml_desc = old->a_desc; - mod->sml_type = mod->sml_desc->ad_cname; - mod->sml_numvals = 0; - mod->sml_values = NULL; - mod->sml_nvalues = NULL; - *modtail = mod; - modtail = &mod->sml_next; - } - old = old->a_next; - continue; - } - /* kludge - always update modifiersName so that it - * stays co-located with the other mod opattrs. But only - * if we know there are other valid mods. - */ - if ( *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 ); - new = new->a_next; - old = old->a_next; - } - *modtail = *ml; - *ml = NULL; -} - static int dn_callback( Operation* op, @@ -3345,6 +3186,8 @@ dn_callback( * 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, @@ -3435,9 +3278,78 @@ dn_callback( */ } - syncrepl_diff_entry( op, rs->sr_entry->e_attrs, - dni->new_entry->e_attrs, &dni->mods, dni->modlist, - is_ctx ); + modtail = &dni->mods; + ml = dni->modlist; + + /* We assume that attributes are saved in the same order + * in the remote and local databases. So if we walk through + * the attributeDescriptions one by one they should match in + * lock step. If not, look for an add or delete. + */ + for ( old = rs->sr_entry->e_attrs, new = dni->new_entry->e_attrs; + old && new; ) + { + /* If we've seen this before, use its mod now */ + if ( new->a_flags & SLAP_ATTR_IXADD ) { + attr_cmp( op, NULL, new, &modtail, &ml ); + new = new->a_next; + continue; + } + /* Skip contextCSN */ + if ( is_ctx && old->a_desc == + slap_schema.si_ad_contextCSN ) { + old = old->a_next; + continue; + } + + if ( old->a_desc != new->a_desc ) { + Modifications *mod; + Attribute *tmp; + + /* If it's just been re-added later, + * remember that we've seen it. + */ + tmp = attr_find( new, old->a_desc ); + if ( tmp ) { + tmp->a_flags |= SLAP_ATTR_IXADD; + } else { + /* If it's a new attribute, pull it in. + */ + tmp = attr_find( old, new->a_desc ); + if ( !tmp ) { + attr_cmp( op, NULL, new, &modtail, &ml ); + new = new->a_next; + continue; + } + /* Delete old attr */ + mod = ch_malloc( sizeof( Modifications ) ); + mod->sml_op = LDAP_MOD_DELETE; + mod->sml_flags = 0; + mod->sml_desc = old->a_desc; + mod->sml_type = mod->sml_desc->ad_cname; + mod->sml_numvals = 0; + mod->sml_values = NULL; + mod->sml_nvalues = NULL; + *modtail = mod; + modtail = &mod->sml_next; + } + old = old->a_next; + continue; + } + /* kludge - always update modifiersName so that it + * stays co-located with the other mod opattrs. But only + * if we know there are other valid 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 ); + new = new->a_next; + old = old->a_next; + } + *modtail = *ml; + *ml = NULL; } } } else if ( rs->sr_type == REP_RESULT ) { @@ -3640,9 +3552,12 @@ syncinfo_free( syncinfo_t *sie, int free_all ) { syncinfo_t *si_next; - Debug( LDAP_DEBUG_TRACE, "syncinfo_free: %s\n", - sie->si_ridtxt, 0, 0 ); - + if ( free_all && sie->si_cookieState ) { + ch_free( sie->si_cookieState->cs_sids ); + ber_bvarray_free( sie->si_cookieState->cs_vals ); + ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex ); + ch_free( sie->si_cookieState ); + } do { si_next = sie->si_next; @@ -3654,21 +3569,20 @@ syncinfo_free( syncinfo_t *sie, int free_all ) ldap_unbind_ext( sie->si_ld, NULL, NULL ); } + /* re-fetch it, in case it was already removed */ + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + sie->si_re = ldap_pvt_runqueue_find( &slapd_rq, do_syncrepl, sie ); if ( sie->si_re ) { - struct re_s *re = sie->si_re; - sie->si_re = NULL; - - ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); - if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ) ) - ldap_pvt_runqueue_stoptask( &slapd_rq, re ); - ldap_pvt_runqueue_remove( &slapd_rq, re ); - ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, sie->si_re ) ) + ldap_pvt_runqueue_stoptask( &slapd_rq, sie->si_re ); + ldap_pvt_runqueue_remove( &slapd_rq, sie->si_re ); } - - ldap_pvt_thread_mutex_destroy( &sie->si_mutex ); - + + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + ldap_pvt_thread_mutex_destroy( &sie->si_mutex ); + bindconf_free( &sie->si_bindconf ); - + if ( sie->si_filterstr.bv_val ) { ch_free( sie->si_filterstr.bv_val ); } @@ -3744,15 +3658,6 @@ syncinfo_free( syncinfo_t *sie, int free_all ) } ch_free( npe ); } - if ( sie->si_cookieState ) { - sie->si_cookieState->cs_ref--; - if ( !sie->si_cookieState->cs_ref ) { - ch_free( sie->si_cookieState->cs_sids ); - ber_bvarray_free( sie->si_cookieState->cs_vals ); - ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex ); - ch_free( sie->si_cookieState ); - } - } ch_free( sie ); sie = si_next; } while ( free_all && si_next ); @@ -3808,6 +3713,21 @@ enum { GOT_REQUIRED = (GOT_RID|GOT_PROVIDER|GOT_SEARCHBASE) }; +static struct { + struct berval key; + int val; +} scopes[] = { + { BER_BVC("base"), LDAP_SCOPE_BASE }, + { BER_BVC("one"), LDAP_SCOPE_ONELEVEL }, + { BER_BVC("onelevel"), LDAP_SCOPE_ONELEVEL }, /* OpenLDAP extension */ + { BER_BVC("children"), LDAP_SCOPE_SUBORDINATE }, + { BER_BVC("subord"), LDAP_SCOPE_SUBORDINATE }, + { BER_BVC("subordinate"), LDAP_SCOPE_SUBORDINATE }, + { BER_BVC("sub"), LDAP_SCOPE_SUBTREE }, + { BER_BVC("subtree"), LDAP_SCOPE_SUBTREE }, /* OpenLDAP extension */ + { BER_BVNULL, 0 } +}; + static slap_verbmasks datamodes[] = { { BER_BVC("default"), SYNCDATA_DEFAULT }, { BER_BVC("accesslog"), SYNCDATA_ACCESSLOG }, @@ -4025,15 +3945,19 @@ parse_syncrepl_line( { int j; val = c->argv[ i ] + STRLENOF( SCOPESTR "=" ); - j = ldap_pvt_str2scope( val ); - if ( j < 0 ) { + for ( j = 0; !BER_BVISNULL(&scopes[j].key); j++ ) { + if (!strcasecmp( val, scopes[j].key.bv_val ) ) { + si->si_scope = scopes[j].val; + break; + } + } + if ( BER_BVISNULL(&scopes[j].key) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "Error: parse_syncrepl_line: " "unknown scope \"%s\"", val); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return -1; } - si->si_scope = j; si->si_got |= GOT_SCOPE; } else if ( !strncasecmp( c->argv[ i ], ATTRSONLYSTR, STRLENOF( ATTRSONLYSTR ) ) ) @@ -4330,8 +4254,6 @@ add_syncrepl( rc = parse_syncrepl_line( c, si ); if ( rc == 0 ) { - LDAPURLDesc *lud; - /* Must be LDAPv3 because we need controls */ switch ( si->si_bindconf.sb_version ) { case 0: @@ -4349,35 +4271,24 @@ add_syncrepl( return 1; } - if ( ldap_url_parse( si->si_bindconf.sb_uri.bv_val, &lud )) { - snprintf( c->cr_msg, sizeof( c->cr_msg ), - "<%s> invalid URL", c->argv[0] ); - Debug( LDAP_DEBUG_ANY, "%s: %s %s\n", - c->log, c->cr_msg, si->si_bindconf.sb_uri.bv_val ); - return 1; - } - si->si_be = c->be; if ( slapMode & SLAP_SERVER_MODE ) { + Listener **l = slapd_get_listeners(); int isMe = 0; - /* check if consumer points to current server and database. - * If so, ignore this configuration. + + /* check if URL points to current server. If so, ignore + * this configuration. We require an exact match. Just + * in case they really want to do this, they can vary + * the case of the URL to allow it. */ - if ( !SLAP_DBHIDDEN( c->be ) ) { + if ( l && !SLAP_DBHIDDEN( c->be ) ) { int i; - /* if searchbase doesn't match current DB suffix, - * assume it's different - */ - for ( i=0; !BER_BVISNULL( &c->be->be_nsuffix[i] ); i++ ) { - if ( bvmatch( &si->si_base, &c->be->be_nsuffix[i] )) { + for ( i=0; l[i]; i++ ) { + if ( bvmatch( &l[i]->sl_url, &si->si_bindconf.sb_uri ) ) { isMe = 1; break; } } - /* if searchbase matches, see if URLs match */ - if ( isMe && config_check_my_url( si->si_bindconf.sb_uri.bv_val, - lud ) == NULL ) - isMe = 0; } if ( !isMe ) { @@ -4396,7 +4307,6 @@ add_syncrepl( /* mirrormode still needs to see this flag in tool mode */ rc = config_sync_shadow( c ) ? -1 : 0; } - ldap_free_urldesc( lud ); } #ifdef HAVE_TLS @@ -4417,7 +4327,7 @@ add_syncrepl( si->si_cookieState = c->be->be_syncinfo->si_cookieState; - /* add new syncrepl to end of list (same order as when deleting) */ + // 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 { @@ -4426,7 +4336,6 @@ add_syncrepl( c->be->be_syncinfo = si; } - si->si_cookieState->cs_ref++; si->si_next = NULL; @@ -4437,7 +4346,7 @@ add_syncrepl( static void syncrepl_unparse( syncinfo_t *si, struct berval *bv ) { - struct berval bc, uri, bs; + struct berval bc, uri; char buf[BUFSIZ*2], *ptr; ber_len_t len; int i; @@ -4491,10 +4400,13 @@ syncrepl_unparse( syncinfo_t *si, struct berval *bv ) ptr = lutil_strcopy( ptr, si->si_logbase.bv_val ); *ptr++ = '"'; } - if ( ldap_pvt_scope2bv( si->si_scope, &bs ) == LDAP_SUCCESS ) { - if ( WHATSLEFT <= STRLENOF( " " SCOPESTR "=" ) + bs.bv_len ) return; - ptr = lutil_strcopy( ptr, " " SCOPESTR "=" ); - ptr = lutil_strcopy( ptr, bs.bv_val ); + for (i=0; !BER_BVISNULL(&scopes[i].key);i++) { + if ( si->si_scope == scopes[i].val ) { + if ( WHATSLEFT <= STRLENOF( " " SCOPESTR "=" ) + scopes[i].key.bv_len ) return; + ptr = lutil_strcopy( ptr, " " SCOPESTR "=" ); + ptr = lutil_strcopy( ptr, scopes[i].key.bv_val ); + break; + } } if ( si->si_attrsonly ) { if ( WHATSLEFT <= STRLENOF( " " ATTRSONLYSTR "=\"" "\"" ) ) return; @@ -4622,11 +4534,13 @@ 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; + cs = c->be->be_syncinfo->si_cookieState; for ( sip = &c->be->be_syncinfo, i=0; *sip; i++ ) { si = *sip; if ( c->valx == -1 || i == c->valx ) { @@ -4639,20 +4553,11 @@ syncrepl_config( ConfigArgs *c ) if ( ldap_pvt_thread_mutex_trylock( &si->si_mutex )) { isrunning = 1; } else { - if ( si->si_conn ) { - /* If there's a persistent connection, it may - * already have a thread queued. We know it's - * not active, so it must be pending and we - * can simply cancel it now. - */ - ldap_pvt_thread_pool_retract( &connection_pool, - si->si_re->routine, si->si_re ); - } ldap_pvt_thread_mutex_unlock( &si->si_mutex ); } } - if ( isrunning ) { - si->si_ctype = -1; + if ( si->si_re && isrunning ) { + si->si_ctype = 0; si->si_next = NULL; } else { syncinfo_free( si, 0 ); @@ -4666,6 +4571,12 @@ syncrepl_config( ConfigArgs *c ) } if ( !c->be->be_syncinfo ) { 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 ); + } } return 0; }