X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fsyncrepl.c;h=0cd130e123de9513aa25cf56a33ee5fd6d689f70;hb=9c5fe98a79afc5303a1e82a93fd759532f289d27;hp=1ef88a66e6f0a41b378f64f1cf28e1510394d9ee;hpb=782d1be0ad8f1c81583810de52f4c6ee3d64d0c6;p=openldap diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index 1ef88a66e6..0cd130e123 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,8 +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 void -syncrepl_del_nonpresent( Operation *, syncinfo_t * ); +static int syncuuid_cmp( const void *, const void * ); +static void avl_ber_bvfree( void * ); +static void syncrepl_del_nonpresent( Operation *, syncinfo_t * ); /* callback functions */ static int dn_callback( struct slap_op *, struct slap_rep * ); @@ -125,8 +112,8 @@ init_syncrepl(syncinfo_t *si) static int ldap_sync_search( syncinfo_t *si, - void *ctx, - struct berval *syncCookie ) + void *ctx +) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; @@ -139,8 +126,10 @@ ldap_sync_search( ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx ); - if ( syncCookie ) { - ber_printf( ber, "{eO}", abs(si->si_type), syncCookie ); + if ( si->si_syncCookie.octet_str && + si->si_syncCookie.octet_str[0].bv_val ) { + ber_printf( ber, "{eO}", abs(si->si_type), + &si->si_syncCookie.octet_str[0] ); } else { ber_printf( ber, "{e}", abs(si->si_type) ); } @@ -184,12 +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; - BerVarray syncCookie; + struct sync_cookie *sc = NULL; + struct sync_cookie syncCookie = { NULL, -1, NULL }; + struct berval *psub; - si->si_sync_mode = LDAP_SYNC_STATE_MODE; + psub = &si->si_be->be_nsuffix[0]; /* Init connection to master */ @@ -197,11 +189,11 @@ do_syncrep1( if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "do_syncrepl: ldap_initialize failed (%s)\n", + "do_syncrep1: ldap_initialize failed (%s)\n", si->si_provideruri, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "do_syncrepl: ldap_initialize failed (%s)\n", + "do_syncrep1: ldap_initialize failed (%s)\n", si->si_provideruri, 0, 0 ); #endif return rc; @@ -216,7 +208,7 @@ do_syncrep1( rc = ldap_start_tls_s( si->si_ld, NULL, NULL ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, "do_syncrepl: " + LDAP_LOG ( OPERATION, ERR, "do_syncrep1: " "%s: ldap_start_tls failed (%d)\n", si->si_tls == SYNCINFO_TLS_CRITICAL ? "Error" : "Warning", rc, 0 ); @@ -272,11 +264,11 @@ do_syncrep1( */ if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, "do_syncrepl: " + LDAP_LOG ( OPERATION, ERR, "do_syncrep1: " "ldap_sasl_interactive_bind_s failed (%d)\n", rc, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "do_syncrepl: " + Debug( LDAP_DEBUG_ANY, "do_syncrep1: " "ldap_sasl_interactive_bind_s failed (%d)\n", rc, 0, 0 ); #endif @@ -292,10 +284,10 @@ do_syncrep1( rc = ldap_bind_s( si->si_ld, si->si_binddn, si->si_passwd, si->si_bindmethod ); if ( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, "do_syncrepl: " + LDAP_LOG ( OPERATION, ERR, "do_syncrep1: " "ldap_bind_s failed (%d)\n", rc, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "do_syncrepl: " + Debug( LDAP_DEBUG_ANY, "do_syncrep1: " "ldap_bind_s failed (%d)\n", rc, 0, 0 ); #endif goto done; @@ -304,32 +296,104 @@ 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; - syncCookie = NULL; - backend_attribute( op, NULL, &op->o_req_ndn, - slap_schema.si_ad_syncreplCookie, &syncCookie ); + LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) { + if ( si->si_rid == sc->rid ) { + cmdline_cookie_found = 1; + break; + } + } + + 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 ) { + /* 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 ); + } + } + } + + rc = ldap_sync_search( si, op->o_tmpmemctx ); - rc = ldap_sync_search( si, op->o_tmpmemctx, syncCookie ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, "do_syncrepl: " + LDAP_LOG ( OPERATION, ERR, "do_syncrep1: " "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 ); #else - Debug( LDAP_DEBUG_ANY, "do_syncrepl: " + Debug( LDAP_DEBUG_ANY, "do_syncrep1: " "ldap_search_ext: %s (%d)\n", ldap_err2string( rc ), rc, 0 ); #endif } - if ( syncCookie ) { - ber_dupbv( &si->si_syncCookie, syncCookie ); - ber_bvarray_free_x( syncCookie, op->o_tmpmemctx ); - } done: if ( rc ) { @@ -359,20 +423,16 @@ do_syncrep2( char *retoid = NULL; struct berval *retdata = NULL; - int sync_info_arrived = 0; Entry *entry = NULL; int syncstate; struct berval syncUUID = { 0, NULL }; - struct berval syncCookie = { 0, NULL }; - struct berval syncCookie_req; + struct sync_cookie syncCookie = { NULL, -1, NULL }; + 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; - int syncinfo_arrived = 0; - - slap_callback cb; int rc_efree; @@ -385,22 +445,28 @@ do_syncrep2( struct timeval *tout_p = NULL; struct timeval tout = { 0, 0 }; + int refreshDeletes = 0; + int refreshDone = 1; + BerVarray syncUUIDs = NULL; + ber_tag_t si_tag; + if ( slapd_abrupt_shutdown ) { rc = -2; 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 Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2\n", 0, 0, 0 ); #endif - op->o_callback = &cb; - psub = &si->si_be->be_nsuffix[0]; - syncCookie_req = si->si_syncCookie; + slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie ); if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ){ tout_p = &tout; @@ -419,28 +485,36 @@ do_syncrep2( msg != NULL; msg = ldap_next_message( si->si_ld, msg ) ) { - syncCookie.bv_len = 0; syncCookie.bv_val = NULL; switch( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: ldap_get_entry_controls( si->si_ld, msg, &rctrls ); - if ( rctrls ) { - rctrlp = *rctrls; - ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); - ber_scanf( ber, "{em", &syncstate, &syncUUID ); - if ( ber_peek_tag( ber, &len ) == LDAP_SYNC_TAG_COOKIE ) { - ber_scanf( ber, "m}", &syncCookie ); + /* we can't work without the control */ + if ( !rctrls ) { + rc = -1; + goto done; + } + rctrlp = *rctrls; + ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); + ber_scanf( ber, "{em", &syncstate, &syncUUID ); + 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 ); } + if ( syncCookie.octet_str && + 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, !syncinfo_arrived ); - if ( syncCookie.bv_len ) { + 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 ( rctrls ) { - ldap_controls_free( rctrls ); - } + ldap_controls_free( rctrls ); if ( modlist ) { slap_mods_free( modlist ); } @@ -452,10 +526,10 @@ do_syncrep2( case LDAP_RES_SEARCH_REFERENCE: #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "do_syncrepl : reference received\n", 0, 0, 0 ); + "do_syncrep2 : reference received\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "do_syncrepl : reference received\n", 0, 0, 0 ); + "do_syncrep2 : reference received\n", 0, 0, 0 ); #endif break; @@ -467,18 +541,37 @@ do_syncrep2( ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER ); ber_scanf( ber, "{" /*"}"*/); - if ( ber_peek_tag( ber, &len ) == LDAP_SYNC_TAG_COOKIE ) + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { - ber_scanf( ber, "m", &syncCookie ); + 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); + } + if ( syncCookie.octet_str && + syncCookie.octet_str[0].bv_val ) + slap_parse_sync_cookie( &syncCookie ); + } + if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) + { + ber_scanf( ber, "b", &refreshDeletes ); } + ber_scanf( ber, "}" ); } - value_match( &match, slap_schema.si_ad_entryCSN, - slap_schema.si_ad_entryCSN->ad_type->sat_ordering, - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - &syncCookie_req, &syncCookie, &text ); - if ( syncCookie.bv_len && match < 0) { - syncrepl_updateCookie( si, op, - psub, &syncCookie ); + if ( syncCookie_req.ctxcsn == NULL ) { + match = -1; + } else if ( syncCookie.ctxcsn == NULL ) { + match = 1; + } else { + value_match( &match, slap_schema.si_ad_entryCSN, + slap_schema.si_ad_entryCSN->ad_type->sat_ordering, + SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, + &syncCookie_req.ctxcsn[0], &syncCookie.ctxcsn[0], &text ); + } + if ( syncCookie.octet_str && syncCookie.octet_str->bv_val + && match < 0 ) { + syncrepl_updateCookie( si, op, psub, &syncCookie ); } if ( rctrls ) { ldap_controls_free( rctrls ); @@ -488,10 +581,11 @@ do_syncrep2( * 1) err code : LDAP_BUSY ... * 2) on err policy : stop service, stop sync, retry */ - if ( si->si_sync_mode == LDAP_SYNC_STATE_MODE && match - < 0 ) - { + if ( refreshDeletes == 0 && match < 0 ) { syncrepl_del_nonpresent( op, si ); + } else { + avl_free( si->si_presentlist, avl_ber_bvfree ); + si->si_presentlist = NULL; } } rc = -2; @@ -502,65 +596,118 @@ do_syncrep2( rc = ldap_parse_intermediate( si->si_ld, msg, &retoid, &retdata, NULL, 0 ); if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) { - sync_info_arrived = 1; + int si_refreshDelete = 0; + int si_refreshPresent = 0; ber_init2( ber, retdata, LBER_USE_DER ); - ber_scanf( ber, "{e" /*"}"*/, &syncstate ); - if ( ber_peek_tag( ber, &len ) - == LDAP_SYNC_TAG_COOKIE ) { - ber_scanf( ber, /*"{"*/ "m}", &syncCookie ); - } else { - if ( syncstate == LDAP_SYNC_NEW_COOKIE ) { + switch ( si_tag = ber_peek_tag( ber, &len )) { + ber_tag_t tag; + case LDAP_TAG_SYNC_NEW_COOKIE: + ber_scanf( ber, "tm", &tag, &cookie ); + break; + case LDAP_TAG_SYNC_REFRESH_DELETE: + si_refreshDelete = 1; + case LDAP_TAG_SYNC_REFRESH_PRESENT: + si_refreshPresent = 1; + ber_scanf( ber, "t{", &tag ); + 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); + } + if ( syncCookie.octet_str && + syncCookie.octet_str[0].bv_val ) + slap_parse_sync_cookie( &syncCookie ); + } + if ( ber_peek_tag( ber, &len ) == + LDAP_TAG_REFRESHDONE ) + { + ber_scanf( ber, "b", &refreshDone ); + } + ber_scanf( ber, "}" ); + break; + case LDAP_TAG_SYNC_ID_SET: + ber_scanf( ber, "t{", &tag ); + 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 ); + } + if ( syncCookie.octet_str && + syncCookie.octet_str[0].bv_val ) + slap_parse_sync_cookie( &syncCookie ); + } + if ( ber_peek_tag( ber, &len ) == + LDAP_TAG_REFRESHDELETES ) + { + ber_scanf( ber, "b", &refreshDeletes ); + } + 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_syncrepl : cookie required\n", 0, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "do_syncrep2 : unknown syncinfo tag (%ld)\n", + (long) si_tag, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, - "do_syncrepl : cookie required\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "do_syncrep2 : unknown syncinfo tag (%ld)\n", + (long) si_tag, 0, 0 ); #endif - } + ldap_memfree( retoid ); + ber_bvfree( retdata ); + continue; } - value_match( &match, slap_schema.si_ad_entryCSN, - slap_schema.si_ad_entryCSN->ad_type->sat_ordering, - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - &syncCookie_req, &syncCookie, &text ); + if ( syncCookie_req.ctxcsn == NULL ) { + match = -1; + } else if ( syncCookie.ctxcsn == NULL ) { + match = 1; + } else { + value_match( &match, slap_schema.si_ad_entryCSN, + slap_schema.si_ad_entryCSN->ad_type->sat_ordering, + SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, + &syncCookie_req.ctxcsn[0], + &syncCookie.ctxcsn[0], &text ); + } - if ( syncCookie.bv_len && match < 0 ) { + if ( syncCookie.ctxcsn && syncCookie.ctxcsn[0].bv_val + && match < 0 ) { syncrepl_updateCookie( si, op, psub, &syncCookie); } - if ( syncstate == LDAP_SYNC_STATE_MODE_DONE ) { + if ( si_refreshPresent == 1 ) { if ( match < 0 ) { syncrepl_del_nonpresent( op, si ); } - si->si_sync_mode = LDAP_SYNC_LOG_MODE; - } else if ( syncstate == LDAP_SYNC_LOG_MODE_DONE ) { - si->si_sync_mode = LDAP_SYNC_PERSIST_MODE; - } else if ( syncstate == LDAP_SYNC_REFRESH_DONE ) { - si->si_sync_mode = LDAP_SYNC_PERSIST_MODE; - } else if ( syncstate != LDAP_SYNC_NEW_COOKIE || - syncstate != LDAP_SYNC_LOG_MODE_DONE ) - { -#ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "do_syncrepl : unknown sync info\n", 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, - "do_syncrepl : unknown sync info\n", 0, 0, 0 ); -#endif - } + } ldap_memfree( retoid ); ber_bvfree( retdata ); break; } else { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR,"do_syncrepl :" + LDAP_LOG( OPERATION, ERR,"do_syncrep2 :" " unknown intermediate " "response\n", 0, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "do_syncrepl : " + Debug( LDAP_DEBUG_ANY, "do_syncrep2 : " "unknown intermediate response (%d)\n", rc, 0, 0 ); #endif @@ -571,45 +718,49 @@ do_syncrep2( break; default: #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, "do_syncrepl : " + LDAP_LOG( OPERATION, ERR, "do_syncrep2 : " "unknown message\n", 0, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, "do_syncrepl : " + Debug( LDAP_DEBUG_ANY, "do_syncrep2 : " "unknown message\n", 0, 0, 0 ); #endif break; } + if ( syncCookie.octet_str ) { + slap_sync_cookie_free( &syncCookie_req, 0 ); + slap_dup_sync_cookie( &syncCookie_req, &syncCookie ); + slap_sync_cookie_free( &syncCookie, 0 ); + } } ldap_msgfree( res ); res = NULL; } if ( rc == -1 ) { - int errno; const char *errstr; - ldap_get_option( si->si_ld, LDAP_OPT_ERROR_NUMBER, &errno ); - errstr = ldap_err2string( errno ); + ldap_get_option( si->si_ld, LDAP_OPT_ERROR_NUMBER, &rc ); + errstr = ldap_err2string( rc ); #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, - "do_syncrepl : %s\n", errstr, 0, 0 ); + "do_syncrep2 : %s\n", errstr, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, - "do_syncrepl : %s\n", errstr, 0, 0 ); + "do_syncrep2 : %s\n", errstr, 0, 0 ); #endif } done: + slap_sync_cookie_free( &syncCookie, 0 ); + slap_sync_cookie_free( &syncCookie_req, 0 ); + if ( res ) ldap_msgfree( res ); if ( rc && si->si_ld ) { ldap_unbind( si->si_ld ); si->si_ld = NULL; - /* just close and report success */ - if ( rc == -2 ) - rc = 0; } return rc; @@ -626,6 +777,8 @@ do_syncrepl( Operation op = {0}; int rc = LDAP_SUCCESS; int first = 0; + int dostop = 0; + ber_socket_t s; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, "do_syncrepl\n", 0, 0, 0 ); @@ -644,6 +797,14 @@ do_syncrepl( return NULL; } + if ( slapd_abrupt_shutdown && si->si_ld ) { + ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s ); + connection_client_stop( s ); + ldap_unbind( si->si_ld ); + si->si_ld = NULL; + return NULL; + } + conn.c_connid = -1; conn.c_send_ldap_result = slap_send_ldap_result; conn.c_send_search_entry = slap_send_search_entry; @@ -652,8 +813,7 @@ do_syncrepl( conn.c_peer_name = slap_empty_bv; /* set memory context */ -#define SLAB_SIZE 1048576 - op.o_tmpmemctx = sl_mem_create( SLAB_SIZE, ctx ); + op.o_tmpmemctx = sl_mem_create( SLMALLOC_SLAB_SIZE, ctx ); op.o_tmpmfuncs = &sl_mfuncs; op.o_dn = si->si_updatedn; @@ -665,6 +825,13 @@ do_syncrepl( op.o_conn = &conn; op.o_connid = op.o_conn->c_connid; + op.o_sync_state.ctxcsn = NULL; + op.o_sync_state.sid = -1; + op.o_sync_state.octet_str = NULL; + op.o_sync_slog_size = -1; + LDAP_STAILQ_FIRST( &op.o_sync_slog_list ) = NULL; + op.o_sync_slog_list.stqh_last = &LDAP_STAILQ_FIRST(&op.o_sync_slog_list); + /* Establish session, do search */ if ( !si->si_ld ) { first = 1; @@ -673,7 +840,6 @@ do_syncrepl( /* Process results */ if ( rc == LDAP_SUCCESS ) { - ber_socket_t s; ldap_get_option( si->si_ld, LDAP_OPT_DESC, &s ); rc = do_syncrep2( &op, si ); @@ -689,13 +855,11 @@ do_syncrepl( } else { connection_client_enable( s ); } - } else { - connection_client_stop( s ); + } else if ( !first ) { + dostop = 1; } } else { - ch_free( si->si_syncCookie.bv_val ); - si->si_syncCookie.bv_val = NULL; - si->si_syncCookie.bv_len = 0; + if ( rc == -2 ) rc = 0; } } @@ -710,15 +874,21 @@ do_syncrepl( ldap_pvt_runqueue_stoptask( &syncrepl_rq, rtask ); } + if ( dostop ) { + connection_client_stop( s ); + } + if ( rc && rc != LDAP_SERVER_DOWN ) { ldap_pvt_runqueue_remove( &syncrepl_rq, rtask ); - } else if ( rc == LDAP_SERVER_DOWN || - si->si_type == LDAP_SYNC_REFRESH_ONLY ) { - rc = 0; } else { - rc = 1; + if ( rc == LDAP_SERVER_DOWN || + si->si_type == LDAP_SYNC_REFRESH_ONLY ) { + rc = 0; + } else { + rc = 1; + } + ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, rc ); } - ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, rc ); ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex ); return NULL; @@ -780,7 +950,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; } @@ -852,16 +1023,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, @@ -870,21 +1031,22 @@ syncrepl_entry( Modifications* modlist, int syncstate, struct berval* syncUUID, - int refresh + struct sync_cookie* syncCookie_req ) { Backend *be = op->o_bd; - slap_callback cb; + slap_callback cb = { NULL }; struct berval *syncuuid_bv = NULL; + struct berval syncUUID_strrep = { 0, NULL }; SlapReply rs = {REP_RESULT}; Filter f = {0}; AttributeAssertion ava = {0}; int rc = LDAP_SUCCESS; int ret = LDAP_SUCCESS; + const char *text; - if ( refresh && - ( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) + if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD )) { syncuuid_bv = ber_dupbv( NULL, syncUUID ); avl_insert( &si->si_presentlist, (caddr_t) syncuuid_bv, @@ -895,6 +1057,13 @@ syncrepl_entry( return e ? 1 : 0; } + f.f_choice = LDAP_FILTER_EQUALITY; + f.f_ava = &ava; + ava.aa_desc = slap_schema.si_ad_entryUUID; + 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; op->ors_filterstr.bv_val = (char *) sl_malloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); @@ -903,11 +1072,6 @@ syncrepl_entry( syncUUID->bv_val, syncUUID->bv_len ); op->ors_filterstr.bv_val[op->ors_filterstr.bv_len] = '\0'; - f.f_choice = LDAP_FILTER_EQUALITY; - f.f_ava = &ava; - ava.aa_desc = slap_schema.si_ad_entryUUID; - ava.aa_value = *syncUUID; - op->ors_filter = &f; op->ors_scope = LDAP_SCOPE_SUBTREE; /* get syncrepl cookie of shadow replica from subentry */ @@ -930,13 +1094,26 @@ syncrepl_entry( cb.sc_response = null_callback; cb.sc_private = si; - if ( rc == LDAP_SUCCESS && si->si_syncUUID_ndn.bv_val && - si->si_sync_mode != LDAP_SYNC_LOG_MODE ) + if ( rc == LDAP_SUCCESS && si->si_syncUUID_ndn.bv_val ) { + char *subseq_ptr; + + if ( syncstate != LDAP_SYNC_DELETE ) { + op->o_no_psearch = 1; + } + + ber_dupbv( &op->o_sync_csn, syncCookie_req->ctxcsn ); + if ( op->o_sync_csn.bv_val ) { + subseq_ptr = strstr( op->o_sync_csn.bv_val, "#0000" ); + subseq_ptr += 4; + *subseq_ptr = '1'; + } + op->o_req_dn = si->si_syncUUID_ndn; op->o_req_ndn = si->si_syncUUID_ndn; op->o_tag = LDAP_REQ_DELETE; rc = be->be_delete( op, &rs ); + op->o_no_psearch = 0; } switch ( syncstate ) { @@ -947,8 +1124,8 @@ syncrepl_entry( rc == LDAP_NO_SUCH_OBJECT ) { attr_delete( &e->e_attrs, slap_schema.si_ad_entryUUID ); - attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, - syncUUID, op->o_tmpmemctx ); + attr_merge_one( e, slap_schema.si_ad_entryUUID, + syncUUID, &ava.aa_value ); op->o_tag = LDAP_REQ_ADD; op->ora_e = e; @@ -1011,15 +1188,7 @@ syncrepl_entry( } case LDAP_SYNC_DELETE : - if ( si->si_sync_mode == LDAP_SYNC_LOG_MODE ) { - if ( si->si_syncUUID_ndn.bv_val ) { - op->o_req_dn = si->si_syncUUID_ndn; - op->o_req_ndn = si->si_syncUUID_ndn; - op->o_tag = LDAP_REQ_DELETE; - rc = be->be_delete( op, &rs ); - } - } - /* Already deleted otherwise */ + /* Already deleted */ ret = 1; goto done; @@ -1037,6 +1206,9 @@ syncrepl_entry( done : + 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 ); } @@ -1050,7 +1222,7 @@ syncrepl_del_nonpresent( ) { Backend* be = op->o_bd; - slap_callback cb; + slap_callback cb = { NULL }; SlapReply rs = {REP_RESULT}; struct nonpresent_entry *np_list, *np_prev; @@ -1114,7 +1286,7 @@ syncrepl_add_glue( ) { Backend *be = op->o_bd; - slap_callback cb; + slap_callback cb = { NULL }; Attribute *a; int rc; int suffrdns; @@ -1265,7 +1437,7 @@ syncrepl_updateCookie( syncinfo_t *si, Operation *op, struct berval *pdn, - struct berval *syncCookie + struct sync_cookie *syncCookie ) { Backend *be = op->o_bd; @@ -1286,9 +1458,12 @@ syncrepl_updateCookie( struct berval slap_syncrepl_dn_bv = BER_BVNULL; struct berval slap_syncrepl_cn_bv = BER_BVNULL; - slap_callback cb; + slap_callback cb = { NULL }; SlapReply rs = {REP_RESULT}; + slap_sync_cookie_free( &si->si_syncCookie, 0 ); + slap_dup_sync_cookie( &si->si_syncCookie, syncCookie ); + mod = (Modifications *) ch_calloc( 1, sizeof( Modifications )); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_desc = slap_schema.si_ad_objectClass; @@ -1298,10 +1473,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; @@ -1311,7 +1486,7 @@ syncrepl_updateCookie( modtail = &mod->sml_next; if ( scbva[0].bv_val ) ch_free( scbva[0].bv_val ); - ber_dupbv( &scbva[0], syncCookie ); + ber_dupbv( &scbva[0], &si->si_syncCookie.octet_str[0] ); mod = (Modifications *) ch_calloc( 1, sizeof( Modifications )); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_desc = slap_schema.si_ad_syncreplCookie; @@ -1351,10 +1526,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 ); @@ -1466,18 +1641,6 @@ done : return; } -void -avl_ber_bvfree( void *bv ) -{ - if( bv == NULL ) { - return; - } - if ( ((struct berval *)bv)->bv_val != NULL ) { - ch_free ( ((struct berval *)bv)->bv_val ); - } - ch_free ( (char *) bv ); -} - static int dn_callback( Operation* op, @@ -1603,3 +1766,83 @@ 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 ) +{ + if( bv == NULL ) { + return; + } + if ( ((struct berval *)bv)->bv_val != NULL ) { + ch_free ( ((struct berval *)bv)->bv_val ); + } + ch_free ( (char *) bv ); +} +