X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fsyncrepl.c;h=c2a757a4e467d2702c4740adda569dae87e257e4;hb=0a5f1e8516d386784ed7f605e5d03c7ee6d7cedd;hp=92d51347eca627edc378f37f9edb88d0fcc0b7b9;hpb=64dd6a07606ae45e80742f77e6273eb6abd14cd1;p=openldap diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 92d51347ec..c2a757a4e4 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -1,33 +1,19 @@ +/* syncrepl.c -- Replication Engine which uses the LDAP Sync protocol */ /* $OpenLDAP$ */ -/* - * Replication Engine which uses the LDAP Sync protocol - */ -/* - * Copyright 2003 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file - */ -/* Copyright (c) 2003 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. +/* This work is part of OpenLDAP Software . * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ -/* Modified by Howard Chu + * Copyright 2003 The OpenLDAP Foundation. + * Portions Copyright 2003 by IBM Corporation. + * Portions Copyright 2003 by Howard Chu, Symas Corporation. + * All rights reserved. * - * Copyright (c) 2003 by Howard Chu, Symas Corporation + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. * - * Modifications provided under the terms of the OpenLDAP public license. + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ #include "portable.h" @@ -50,10 +36,9 @@ static const struct berval slap_syncrepl_bvc = BER_BVC(SYNCREPL_STR); static const struct berval slap_syncrepl_cn_bvc = BER_BVC(CN_STR SYNCREPL_STR); +static int syncuuid_cmp( const void *, const void * ); static void avl_ber_bvfree( void * ); - -static void -syncrepl_del_nonpresent( Operation *, syncinfo_t * ); +static void syncrepl_del_nonpresent( Operation *, syncinfo_t * ); /* callback functions */ static int dn_callback( struct slap_op *, struct slap_rep * ); @@ -188,10 +173,15 @@ do_syncrep1( syncinfo_t *si ) { int rc; + int cmdline_cookie_found = 0; char syncrepl_cbuf[sizeof(CN_STR SYNCREPL_STR)]; struct berval syncrepl_cn_bv; + struct sync_cookie *sc = NULL; struct sync_cookie syncCookie = { NULL, -1, NULL }; + struct berval *psub; + + psub = &si->si_be->be_nsuffix[0]; /* Init connection to master */ @@ -306,37 +296,90 @@ do_syncrep1( /* get syncrepl cookie of shadow replica from subentry */ - assert( si->si_id < 1000 ); + assert( si->si_rid < 1000 ); syncrepl_cn_bv.bv_val = syncrepl_cbuf; syncrepl_cn_bv.bv_len = snprintf(syncrepl_cbuf, sizeof(syncrepl_cbuf), - CN_STR "syncrepl%d", si->si_id ); - build_new_dn( &op->o_req_ndn, &si->si_base, &syncrepl_cn_bv, - op->o_tmpmemctx ); + CN_STR "syncrepl%ld", si->si_rid ); + build_new_dn( &op->o_req_ndn, psub, &syncrepl_cn_bv, op->o_tmpmemctx ); op->o_req_dn = op->o_req_ndn; - if ( slap_sync_cookie != NULL ) { - slap_sync_cookie_free( &si->si_syncCookie, 0 ); - slap_parse_sync_cookie( slap_sync_cookie ); - if ( slap_sync_cookie->ctxcsn == NULL || - slap_sync_cookie->ctxcsn->bv_val == NULL ) { - slap_init_sync_cookie_ctxcsn( slap_sync_cookie ); + LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) { + if ( si->si_rid == sc->rid ) { + cmdline_cookie_found = 1; + break; } - slap_dup_sync_cookie( &si->si_syncCookie, slap_sync_cookie ); - slap_sync_cookie_free( slap_sync_cookie, 1 ); - slap_sync_cookie = NULL; } - /* use in-memory version if it exists */ - if ( si->si_syncCookie.octet_str == NULL ) { + if ( cmdline_cookie_found ) { + /* cookie is supplied in the command line */ BerVarray cookie = NULL; struct berval cookie_bv; + + LDAP_STAILQ_REMOVE( &slap_sync_cookie, sc, sync_cookie, sc_next ); + slap_sync_cookie_free( &si->si_syncCookie, 0 ); + + /* read stored cookie if it exists */ backend_attribute( op, NULL, &op->o_req_ndn, slap_schema.si_ad_syncreplCookie, &cookie ); - if ( cookie ) { + + if ( !cookie ) { + /* no stored cookie */ + if ( sc->ctxcsn == NULL || + sc->ctxcsn->bv_val == NULL ) { + /* if cmdline cookie does not have ctxcsn */ + /* component, set it to an initial value */ + slap_init_sync_cookie_ctxcsn( sc ); + } + slap_dup_sync_cookie( &si->si_syncCookie, sc ); + slap_sync_cookie_free( sc, 1 ); + sc = NULL; + } else { + /* stored cookie */ + struct berval newcookie = { 0, NULL }; ber_dupbv( &cookie_bv, &cookie[0] ); ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv ); slap_parse_sync_cookie( &si->si_syncCookie ); + ber_bvarray_free( si->si_syncCookie.octet_str ); + si->si_syncCookie.octet_str = NULL; ber_bvarray_free_x( cookie, op->o_tmpmemctx ); + if ( sc->sid != -1 ) { + /* command line cookie wins */ + si->si_syncCookie.sid = sc->sid; + } + if ( sc->ctxcsn != NULL ) { + /* command line cookie wins */ + if ( si->si_syncCookie.ctxcsn ) { + ber_bvarray_free( si->si_syncCookie.ctxcsn ); + si->si_syncCookie.ctxcsn = NULL; + } + ber_dupbv( &cookie_bv, &sc->ctxcsn[0] ); + ber_bvarray_add( &si->si_syncCookie.ctxcsn, &cookie_bv ); + } + if ( sc->rid != -1 ) { + /* command line cookie wins */ + si->si_syncCookie.rid = sc->rid; + } + slap_sync_cookie_free( sc, 1 ); + sc = NULL; + slap_compose_sync_cookie( NULL, &newcookie, + &si->si_syncCookie.ctxcsn[0], + si->si_syncCookie.sid, si->si_syncCookie.rid ); + ber_bvarray_add( &si->si_syncCookie.octet_str, &newcookie ); + } + } else { + /* no command line cookie is specified */ + if ( si->si_syncCookie.octet_str == NULL ) { + BerVarray cookie = NULL; + struct berval cookie_bv; + /* try to read stored cookie */ + backend_attribute( op, NULL, &op->o_req_ndn, + slap_schema.si_ad_syncreplCookie, &cookie ); + if ( cookie ) { + ber_dupbv( &cookie_bv, &cookie[0] ); + ber_bvarray_add( &si->si_syncCookie.octet_str, &cookie_bv ); + slap_parse_sync_cookie( &si->si_syncCookie ); + ber_bvarray_free_x( cookie, op->o_tmpmemctx ); + } } } @@ -388,8 +431,7 @@ do_syncrep2( struct sync_cookie syncCookie_req = { NULL, -1, NULL }; struct berval cookie = { 0, NULL }; - int rc; - int err; + int rc, err, i; ber_len_t len; slap_callback cb; @@ -407,7 +449,7 @@ do_syncrep2( int refreshDeletes = 0; int refreshDone = 1; - BerVarray syncUUIDs; + BerVarray syncUUIDs = NULL; ber_tag_t si_tag; if ( slapd_abrupt_shutdown ) { @@ -415,6 +457,9 @@ do_syncrep2( goto done; } + ber_init2( ber, NULL, LBER_USE_DER ); + ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, "do_syncrep2\n", 0, 0, 0 ); #else @@ -589,15 +634,15 @@ do_syncrep2( ber_scanf( ber, "}" ); break; case LDAP_TAG_SYNC_ID_SET: - /* FIXME : to be supported */ ber_scanf( ber, "t{", &tag ); - if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) - { + if ( ber_peek_tag( ber, &len ) == + LDAP_TAG_SYNC_COOKIE ) { ber_scanf( ber, "m", &cookie ); if ( cookie.bv_val ) { struct berval tmp_bv; ber_dupbv( &tmp_bv, &cookie ); - ber_bvarray_add( &syncCookie.octet_str, &tmp_bv); + ber_bvarray_add( &syncCookie.octet_str, + &tmp_bv ); } if ( syncCookie.octet_str && syncCookie.octet_str[0].bv_val ) @@ -610,16 +655,24 @@ do_syncrep2( } ber_scanf( ber, "[W]", &syncUUIDs ); ber_scanf( ber, "}" ); + for ( i = 0; syncUUIDs[i].bv_val; i++ ) { + struct berval *syncuuid_bv; + syncuuid_bv = ber_dupbv( NULL, &syncUUIDs[i] ); + avl_insert( &si->si_presentlist, + (caddr_t) syncuuid_bv, + syncuuid_cmp, avl_dup_error ); + } + ber_memfree_x( syncUUIDs, op->o_tmpmemctx ); break; default: #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "do_syncrep2 : unknown syncinfo tag (%d)\n", - si_tag, 0, 0 ); + "do_syncrep2 : unknown syncinfo tag (%ld)\n", + (long) si_tag, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "do_syncrep2 : unknown syncinfo tag (%d)\n", - si_tag, 0, 0 ); + "do_syncrep2 : unknown syncinfo tag (%ld)\n", + (long) si_tag, 0, 0 ); #endif ldap_memfree( retoid ); ber_bvfree( retdata ); @@ -902,7 +955,8 @@ syncrepl_message_to_entry( sl_free( ndn.bv_val, op->o_tmpmemctx ); sl_free( dn.bv_val, op->o_tmpmemctx ); - if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE ) { + if ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_DELETE ) + { return NULL; } @@ -974,16 +1028,6 @@ done: return e; } -int -syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 ) -{ - const struct berval *uuid1 = v_uuid1; - const struct berval *uuid2 = v_uuid2; - int rc = uuid1->bv_len - uuid2->bv_len; - if ( rc ) return rc; - return ( strcmp( uuid1->bv_val, uuid2->bv_val ) ); -} - int syncrepl_entry( syncinfo_t* si, @@ -998,6 +1042,7 @@ syncrepl_entry( Backend *be = op->o_bd; slap_callback cb; struct berval *syncuuid_bv = NULL; + struct berval syncUUID_strrep = { 0, NULL }; SlapReply rs = {REP_RESULT}; Filter f = {0}; @@ -1020,12 +1065,8 @@ syncrepl_entry( f.f_choice = LDAP_FILTER_EQUALITY; f.f_ava = &ava; ava.aa_desc = slap_schema.si_ad_entryUUID; - rc = asserted_value_validate_normalize( - ava.aa_desc, ad_mr(ava.aa_desc, SLAP_MR_EQUALITY), - SLAP_MR_EQUALITY, syncUUID, &ava.aa_value, &text, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - return rc; - } + slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx ); + ava.aa_value = *syncUUID; op->ors_filter = &f; op->ors_filterstr.bv_len = (sizeof("entryUUID=")-1) + syncUUID->bv_len; @@ -1170,8 +1211,8 @@ syncrepl_entry( done : - if ( ava.aa_value.bv_val ) { - ber_memfree_x( ava.aa_value.bv_val, op->o_tmpmemctx ); + if ( syncUUID_strrep.bv_val ) { + ber_memfree_x( syncUUID_strrep.bv_val, op->o_tmpmemctx ); } if ( si->si_syncUUID_ndn.bv_val ) { ber_memfree_x( si->si_syncUUID_ndn.bv_val, op->o_tmpmemctx ); @@ -1437,10 +1478,10 @@ syncrepl_updateCookie( modtail = &mod->sml_next; ber_dupbv( &cnbva[0], (struct berval *) &slap_syncrepl_bvc ); - assert( si->si_id < 1000 ); + assert( si->si_rid < 1000 ); cnbva[0].bv_len = snprintf( cnbva[0].bv_val, slap_syncrepl_bvc.bv_len, - "syncrepl%d", si->si_id ); + "syncrepl%ld", si->si_rid ); mod = (Modifications *) ch_calloc( 1, sizeof( Modifications )); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_desc = slap_schema.si_ad_cn; @@ -1490,10 +1531,10 @@ syncrepl_updateCookie( e = ( Entry * ) ch_calloc( 1, sizeof( Entry )); slap_syncrepl_cn_bv.bv_val = syncrepl_cbuf; - assert( si->si_id < 1000 ); + assert( si->si_rid < 1000 ); slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val, slap_syncrepl_cn_bvc.bv_len, - "cn=syncrepl%d", si->si_id ); + "cn=syncrepl%ld", si->si_rid ); build_new_dn( &slap_syncrepl_dn_bv, pdn, &slap_syncrepl_cn_bv, op->o_tmpmemctx ); @@ -1731,6 +1772,73 @@ slap_create_syncrepl_entry( return e; } +struct berval * +slap_uuidstr_from_normalized( + struct berval* uuidstr, + struct berval* normalized, + void *ctx ) +{ + struct berval *new; + unsigned char nibble; + int i, d = 0; + + if ( normalized == NULL ) + return NULL; + + if ( normalized->bv_len != 16 ) { + return NULL; + } + + if ( uuidstr ) { + new = uuidstr; + } else { + new = (struct berval *)sl_malloc( sizeof(struct berval), ctx ); + } + + new->bv_len = 36; + + if (( new->bv_val = sl_malloc( new->bv_len + 1, ctx )) == NULL) { + if ( !uuidstr ) + sl_free( new, ctx ); + return NULL; + } + + for ( i = 0; i < 16; i++ ) { + if ( i == 4 || i == 6 || i == 8 || i == 10 ) { + new->bv_val[(i<<1)+d] = '-'; + d += 1; + } + + nibble = (normalized->bv_val[i] >> 4) & 0xF; + if ( nibble < 10 ) { + new->bv_val[(i<<1)+d] = nibble + '0'; + } else { + new->bv_val[(i<<1)+d] = nibble - 10 + 'a'; + } + + nibble = (normalized->bv_val[i]) & 0xF; + if ( nibble < 10 ) { + new->bv_val[(i<<1)+d+1] = nibble + '0'; + } else { + new->bv_val[(i<<1)+d+1] = nibble - 10 + 'a'; + } + } + + new->bv_val[new->bv_len] = '\0'; + + return new; +} + +static int +syncuuid_cmp( const void* v_uuid1, const void* v_uuid2 ) +{ + const struct berval *uuid1 = v_uuid1; + const struct berval *uuid2 = v_uuid2; + int rc = uuid1->bv_len - uuid2->bv_len; + if ( rc ) return rc; + return ( strcmp( uuid1->bv_val, uuid2->bv_val ) ); +} + static void avl_ber_bvfree( void *bv ) {