+/* 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 <http://www.openldap.org/>.
*
- * 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
+ * <http://www.OpenLDAP.org/license.html>.
*/
#include "portable.h"
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 * );
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 */
/* 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 );
+ }
}
}
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;
int refreshDeletes = 0;
int refreshDone = 1;
- BerVarray syncUUIDs;
+ BerVarray syncUUIDs = NULL;
ber_tag_t si_tag;
if ( slapd_abrupt_shutdown ) {
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
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 )
}
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 );
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;
}
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,
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};
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;
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 );
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;
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 );
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 )
{