ITS#10080 Fix refreshAndPersist synchronization problem with glue + rwm

This commit is contained in:
Hiroyuki Homma 2024-01-10 15:06:49 +09:00 committed by Quanah Gibson-Mount
parent db3d964ee8
commit 8074a30beb
4 changed files with 532 additions and 40 deletions

View File

@ -369,6 +369,8 @@ glue_sub_search( Operation *op, SlapReply *rs, BackendDB *b0,
BackendInfo *bi = op->o_bd->bd_info;
int rc = SLAP_CB_CONTINUE;
for ( on=on->on_next; on; on=on->on_next ) {
if ( on->on_bi.bi_flags & SLAPO_BFLAG_DISABLED )
continue;
op->o_bd->bd_info = (BackendInfo *)on;
if ( on->on_bi.bi_op_search ) {
rc = on->on_bi.bi_op_search( op, rs );
@ -550,6 +552,11 @@ glue_op_search ( Operation *op, SlapReply *rs )
rs->sr_err = glue_sub_search( op, rs, b0, on );
}
if ( rs->sr_err == SLAPD_NO_REPLY ) {
gs.err = rs->sr_err;
break;
}
switch ( gs.err ) {
/*
@ -716,7 +723,8 @@ end_of_loop:;
}
rs->sr_ctrls = gs.ctrls;
send_ldap_result( op, rs );
if ( rs->sr_err != SLAPD_NO_REPLY )
send_ldap_result( op, rs );
op->o_bd = b0;
op->o_bd->bd_info = bi0;

View File

@ -1815,6 +1815,16 @@ rwm_response( Operation *op, SlapReply *rs )
break;
}
if ( op->o_tag == LDAP_REQ_ADD && op->ora_e ) {
/*
* Rewrite back the dn and attributes of the added entry op->ora_e
*/
SlapReply rs2 = *rs;
rs2.sr_entry = op->ora_e;
rs2.sr_flags |= REP_ENTRY_MODIFIABLE;
return rwm_send_entry( op, &rs2 );
}
return SLAP_CB_CONTINUE;
}

View File

@ -698,6 +698,7 @@ syncprov_findcsn( Operation *op, find_csn_t mode, struct berval *csn )
"FIND_PRESENT",
csn ? csn->bv_val : "" );
again:
fop = *op;
fop.o_sync_mode &= SLAP_CONTROL_MASK; /* turn off sync_mode */
/* We want pure entries, not referrals */
@ -714,7 +715,6 @@ syncprov_findcsn( Operation *op, find_csn_t mode, struct berval *csn )
fop.ors_filter = &cf;
fop.ors_filterstr.bv_val = buf;
again:
switch( mode ) {
case FIND_MAXCSN:
cf.f_choice = LDAP_FILTER_GE;
@ -1319,17 +1319,9 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
Entry *e = NULL;
Attribute *a;
int rc, gonext;
struct berval newdn;
int freefdn = 0;
BackendDB *b0 = op->o_bd, db;
fc.fdn = &op->o_req_ndn;
/* compute new DN */
if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) {
ber_dupbv_x( &newdn, &op->orr_nnewDN, op->o_tmpmemctx );
fc.fdn = &newdn;
freefdn = 1;
}
fc.fdn = saveit ? &op->o_req_ndn : &opc->sndn;
if ( !saveit && op->o_tag == LDAP_REQ_DELETE ) {
/* Delete succeeded, there is no entry */
} else if ( op->o_tag != LDAP_REQ_ADD ) {
@ -1362,8 +1354,13 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
}
if ( saveit || op->o_tag == LDAP_REQ_ADD ) {
ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
if ( op->o_tag == LDAP_REQ_MODRDN ) {
ber_dupbv_x( &opc->sdn, &op->orr_newDN, op->o_tmpmemctx );
ber_dupbv_x( &opc->sndn, &op->orr_nnewDN, op->o_tmpmemctx );
} else {
ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
}
opc->sreference = is_entry_referral( e );
a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
if ( a )
@ -1371,11 +1368,6 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
Debug( LDAP_DEBUG_SYNC, "%s syncprov_matchops: "
"%srecording uuid for dn=%s on opc=%p\n",
op->o_log_prefix, a ? "" : "not ", opc->sdn.bv_val, opc );
} else if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) {
op->o_tmpfree( opc->sndn.bv_val, op->o_tmpmemctx );
op->o_tmpfree( opc->sdn.bv_val, op->o_tmpmemctx );
ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
}
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
@ -1520,9 +1512,6 @@ syncprov_matchops( Operation *op, opcookie *opc, int saveit )
else if ( opc->se )
entry_free( opc->se );
}
if ( freefdn ) {
op->o_tmpfree( fc.fdn->bv_val, op->o_tmpmemctx );
}
op->o_bd = b0;
}
@ -2955,6 +2944,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
{
searchstate *ss = op->o_callback->sc_private;
slap_overinst *on = ss->ss_on;
syncops *so = ss->ss_so;
syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
sync_control *srs = op->o_controls[slap_cids.sc_LDAPsync];
@ -2983,7 +2973,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
sid = slap_parse_csn_sid( &a->a_nvals[0] );
/* If not a persistent search */
if ( !ss->ss_so ) {
if ( !so ) {
/* Make sure entry is less than the snapshot'd contextCSN */
for ( i=0; i<ss->ss_numcsns; i++ ) {
if ( sid == ss->ss_sids[i] && ber_bvcmp( &a->a_nvals[0],
@ -3048,7 +3038,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
/* Is this a regular refresh?
* Note: refresh never gets here if there were no changes
*/
if ( !ss->ss_so ) {
if ( !so ) {
rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
op->o_tmpmemctx );
rs->sr_ctrls[1] = NULL;
@ -3059,6 +3049,7 @@ syncprov_search_response( Operation *op, SlapReply *rs )
op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
} else {
/* It's RefreshAndPersist, transition to Persist phase */
rs->sr_err = SLAPD_NO_REPLY;
syncprov_sendinfo( op, rs, ( ss->ss_flags & SS_PRESENT ) ?
LDAP_TAG_SYNC_REFRESH_PRESENT : LDAP_TAG_SYNC_REFRESH_DELETE,
( ss->ss_flags & SS_CHANGED ) ? &cookie : NULL,
@ -3076,21 +3067,21 @@ syncprov_search_response( Operation *op, SlapReply *rs )
return SLAPD_ABANDON;
} else {
ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex );
ldap_pvt_thread_mutex_lock( &so->s_mutex );
/* Turn off the refreshing flag */
ss->ss_so->s_flags ^= PS_IS_REFRESHING;
so->s_flags ^= PS_IS_REFRESHING;
Debug( LDAP_DEBUG_SYNC, "%s syncprov_search_response: "
"detaching op\n", op->o_log_prefix );
syncprov_detach_op( op, ss->ss_so, on );
syncprov_detach_op( op, so, on );
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
/* If there are queued responses, fire them off */
if ( ss->ss_so->s_res )
syncprov_qstart( ss->ss_so );
ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex );
return SLAPD_NO_REPLY;
if ( so->s_res )
syncprov_qstart( so );
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
return rs->sr_err;
}
}
}
@ -3098,6 +3089,33 @@ syncprov_search_response( Operation *op, SlapReply *rs )
return SLAP_CB_CONTINUE;
}
static int
syncprov_search_cb( Operation *op, SlapReply *rs )
{
/*
* Prevent the glue overlay from processing subordinates when it is
* configured (explicitly or implicitly) below the syncprov overlay.
*/
if ( rs->sr_type == REP_RESULT )
op->o_no_subordinate_glue = 1;
return SLAP_CB_CONTINUE;
}
static int
syncprov_search_cleanup( Operation *op, SlapReply *rs )
{
if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_INTERMEDIATE ||
rs->sr_err == SLAPD_ABANDON || op->o_abandon ) {
searchstate *ss = op->o_callback->sc_private;
if ( ss && ss->ss_numcsns ) {
ber_bvarray_free_x( ss->ss_ctxcsn, op->o_tmpmemctx );
op->o_tmpfree( ss->ss_sids, op->o_tmpmemctx );
}
slap_freeself_cb( op, rs );
}
return SLAP_CB_CONTINUE;
}
static int
syncprov_op_search( Operation *op, SlapReply *rs )
{
@ -3114,6 +3132,14 @@ syncprov_op_search( Operation *op, SlapReply *rs )
int minsid, maxsid;
int dirty = 0;
if ( op->o_sync > SLAP_CONTROL_IGNORED ) {
cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
cb->sc_response = syncprov_search_cb;
cb->sc_cleanup = syncprov_search_cleanup;
cb->sc_next = op->o_callback;
op->o_callback = cb;
}
if ( !(op->o_sync_mode & SLAP_SYNC_REFRESH) ) return SLAP_CB_CONTINUE;
if ( op->ors_deref & LDAP_DEREF_SEARCHING ) {
@ -3320,6 +3346,10 @@ bailout:
}
rs->sr_ctrls = NULL;
send_ldap_result( op, rs );
if ( numcsns ) {
ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
op->o_tmpfree( sids, op->o_tmpmemctx );
}
return rs->sr_err;
}
}
@ -3342,6 +3372,10 @@ no_change: if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) {
rs->sr_err = LDAP_SUCCESS;
send_ldap_result( op, rs );
rs->sr_ctrls = NULL;
if ( numcsns ) {
ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
op->o_tmpfree( sids, op->o_tmpmemctx );
}
return rs->sr_err;
}
Debug( LDAP_DEBUG_SYNC, "%s syncprov_op_search: "
@ -3429,10 +3463,6 @@ no_change: if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) {
/* No, so a reload is required */
/* the 2.2 consumer doesn't send this hint */
if ( si->si_usehint && srs->sr_rhint == 0 ) {
if ( ctxcsn )
ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
if ( sids )
op->o_tmpfree( sids, op->o_tmpmemctx );
rs->sr_err = LDAP_SYNC_REFRESH_REQUIRED;
rs->sr_text = "sync cookie is stale";
goto bailout;
@ -3452,13 +3482,8 @@ no_change: if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) {
} else {
gotstate = 1;
/* If changed and doing Present lookup, send Present UUIDs */
if ( syncprov_findcsn( op, FIND_PRESENT, 0 ) != LDAP_SUCCESS ) {
if ( ctxcsn )
ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
if ( sids )
op->o_tmpfree( sids, op->o_tmpmemctx );
if ( syncprov_findcsn( op, FIND_PRESENT, 0 ) != LDAP_SUCCESS )
goto bailout;
}
}
} else {
/* The consumer knows nothing, we know nothing. OK. */
@ -3516,6 +3541,7 @@ shortcut:
ss->ss_numcsns = numcsns;
ss->ss_sids = sids;
cb->sc_response = syncprov_search_response;
cb->sc_cleanup = syncprov_search_cleanup;
cb->sc_private = ss;
cb->sc_next = op->o_callback;
op->o_callback = cb;

View File

@ -0,0 +1,448 @@
#! /bin/sh
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2022 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by 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>.
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
if test $BACKLDAP = ldapno; then
echo "LDAP backend not available, test skipped"
exit 0
fi
if test $RWM = rwmno; then
echo "rwm (rewrite/remap) overlay not available, test skipped"
exit 0
fi
if test $SYNCPROV = syncprovno; then
echo "Syncrepl provider overlay not available, test skipped"
exit 0
fi
RMTSUFFIX="dc=remote,$BASEDN"
RMTROOTDN="cn=Manager,$RMTSUFFIX"
RMTDIR=$TESTDIR/remote
PR1DIR=$TESTDIR/provider1
PR2DIR=$TESTDIR/provider2
RMTCONF=$RMTDIR/slapd.d
PR1CONF=$PR1DIR/slapd.d
PR2CONF=$PR2DIR/slapd.d
ENTRIES=$TESTDIR/entries.ldif
SYNC1OUT=$TESTDIR/syncrepl1.out
SYNC2OUT=$TESTDIR/syncrepl2.out
mkdir -p $RMTDIR $RMTCONF $RMTDIR/db
mkdir -p $PR1DIR $PR1CONF $PR1DIR/db
mkdir -p $PR2DIR $PR2CONF $PR2DIR/db
cd $TESTDIR
KILLPIDS=
$SLAPPASSWD -g -n > $CONFIGPWF
cat <<EOF > $CONFLDIF
dn: cn=config
objectClass: olcGlobal
cn: config
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcRootPW:< file://$CONFIGPWF
dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema
include: file://$ABS_SCHEMADIR/core.ldif
include: file://$ABS_SCHEMADIR/cosine.ldif
include: file://$ABS_SCHEMADIR/nis.ldif
include: file://$ABS_SCHEMADIR/inetorgperson.ldif
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulePath: $TESTWD/../servers/slapd/overlays
EOF
[ "$BACKENDTYPE" = mod ] && echo "olcModuleLoad: $TESTWD/../servers/slapd/back-$BACKEND/back_$BACKEND.la" >> $CONFLDIF
echo "Initializing remote configurations..."
cat $CONFLDIF - <<EOF | $SLAPADD -F $RMTCONF -n 0
dn: olcDatabase={1}$BACKEND,cn=config
objectClass: olcDatabaseConfig
${nullExclude}objectClass: olc${BACKEND}Config
olcDatabase: {1}$BACKEND
${nullExclude}olcDbDirectory: $RMTDIR/db
olcSuffix: $RMTSUFFIX
olcRootDN: $RMTROOTDN
olcRootPW: $PASSWD
EOF
RC=$?
if test $RC != 0 ; then
echo "slapadd failed ($RC)!"
exit $RC
fi
[ "$BACKLDAP" = ldapmod ] && echo "olcModuleLoad: $TESTWD/../servers/slapd/back-ldap/back_ldap.la" >> $CONFLDIF
[ "$RWM" = rwmmod ] && echo "olcModuleLoad: rwm.la" >> $CONFLDIF
[ "$SYNCPROV" = syncprovmod ] && echo "olcModuleLoad: syncprov.la" >> $CONFLDIF
cat <<EOF >> $CONFLDIF
dn: olcDatabase={1}ldap,cn=config
objectClass: olcDatabaseConfig
objectClass: olcLDAPConfig
olcDatabase: {1}ldap
olcSuffix: ou=remote,ou=users,$BASEDN
olcSubordinate: TRUE
olcDbURI: $URI1
olcDbIDAssertBind: bindmethod=simple
binddn="$RMTROOTDN"
credentials=$PASSWD
mode=none
olcDbIDAssertAuthzFrom: dn.exact:$MANAGERDN
olcRootDN: $MANAGERDN
dn: olcOverlay={0}rwm,olcDatabase={1}ldap,cn=config
objectClass: olcOverlayConfig
objectClass: olcRwmConfig
olcOverlay: {0}rwm
olcRwmRewrite: rwm-suffixmassage "ou=users,$RMTSUFFIX"
EOF
echo "Initializing provider1 configurations..."
cat $CONFLDIF - <<EOF | $SLAPADD -F $PR1CONF -n 0
dn: olcDatabase={2}$BACKEND,cn=config
objectClass: olcDatabaseConfig
${nullExclude}objectClass: olc${BACKEND}Config
olcDatabase: {2}$BACKEND
${nullExclude}olcDbDirectory: $PR1DIR/db
olcSuffix: $BASEDN
olcRootDN: $MANAGERDN
olcRootPW: $PASSWD
dn: olcOverlay={0}syncprov,olcDatabase={2}$BACKEND,cn=config
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: {0}syncprov
EOF
RC=$?
if test $RC != 0 ; then
echo "slapadd failed ($RC)!"
exit $RC
fi
echo "Initializing provider2 configurations..."
cat $CONFLDIF - <<EOF | $SLAPADD -F $PR2CONF -n 0
dn: olcDatabase={2}$BACKEND,cn=config
objectClass: olcDatabaseConfig
${nullExclude}objectClass: olc${BACKEND}Config
olcDatabase: {2}$BACKEND
${nullExclude}olcDbDirectory: $PR2DIR/db
olcSuffix: $BASEDN
olcRootDN: $MANAGERDN
olcRootPW: $PASSWD
dn: olcOverlay={0}glue,olcDatabase={2}$BACKEND,cn=config
objectClass: olcOverlayConfig
objectClass: olcConfig
olcOverlay: {0}glue
dn: olcOverlay={1}syncprov,olcDatabase={2}$BACKEND,cn=config
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: {1}syncprov
EOF
RC=$?
if test $RC != 0 ; then
echo "slapadd failed ($RC)!"
exit $RC
fi
echo "Starting remote slapd on TCP/IP port $PORT1..."
cd $RMTDIR
$SLAPD -F slapd.d -h $URI1 -d $LVL > $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$KILLPIDS $PID"
cd $TESTWD
sleep 1
echo "Using ldapsearch to check that remote slapd is running..."
for i in 0 1 2 3 4 5; do
$LDAPSEARCH -s base -b "" -H $URI1 \
'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 0 ; then
break
fi
echo "Waiting 5 seconds for slapd to start..."
sleep 5
done
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Starting provider1 slapd on TCP/IP port $PORT2..."
cd $PR1DIR
$SLAPD -F slapd.d -h $URI2 -d $LVL > $LOG2 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$KILLPIDS $PID"
cd $TESTWD
sleep 1
echo "Using ldapsearch to check that provider1 slapd is running..."
for i in 0 1 2 3 4 5; do
$LDAPSEARCH -s base -b "" -H $URI2 \
'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 0 ; then
break
fi
echo "Waiting 5 seconds for slapd to start..."
sleep 5
done
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Starting provider2 slapd on TCP/IP port $PORT3..."
cd $PR2DIR
$SLAPD -F slapd.d -h $URI3 -d $LVL > $LOG3 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$KILLPIDS $PID"
cd $TESTWD
sleep 1
echo "Using ldapsearch to check that provider2 slapd is running..."
for i in 0 1 2 3 4 5; do
$LDAPSEARCH -s base -b "" -H $URI3 \
'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 0 ; then
break
fi
echo "Waiting 5 seconds for slapd to start..."
sleep 5
done
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Populating remote database entries..."
$LDAPADD -D "$RMTROOTDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
dn: $RMTSUFFIX
objectClass: dcObject
objectClass: organization
dc: `echo $RMTSUFFIX | sed 's/^dc=\([^,]*\),.*/\1/'`
o: Example, Inc
dn: ou=users,$RMTSUFFIX
objectClass: organizationalUnit
ou: users
dn: cn=remote_user,ou=users,$RMTSUFFIX
objectClass: person
cn: remote_user
sn: remote_user
userPassword: $PASSWD
EOF
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed to populate remote database entries ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
cat <<EOF > $ENTRIES
dn: $BASEDN
objectClass: dcObject
objectClass: organization
dc: example
o: Example, Inc
dn: ou=users,$BASEDN
objectClass: organizationalUnit
ou: users
dn: ou=local,ou=users,$BASEDN
objectClass: organizationalUnit
ou: local
dn: cn=local_user,ou=local,ou=users,$BASEDN
objectClass: person
cn: local_user
sn: local_user
userPassword: $PASSWD
EOF
echo "Populating provider1 database entries..."
$LDAPADD -D "$MANAGERDN" -H $URI2 -w $PASSWD < $ENTRIES >> $TESTOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed to populate provider1 database entries ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Populating provider2 database entries..."
$LDAPADD -D "$MANAGERDN" -H $URI3 -w $PASSWD < $ENTRIES >> $TESTOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapadd failed to populate provider2 database entries ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Starting refreshAndPersist search on provider1..."
$LDAPRSEARCH -D $MANAGERDN -H $URI2 -w $PASSWD -MM -E sync=rp -b $BASEDN '*' + 2>&1 > $SYNC1OUT &
PID=$!
RC=32
for i in 0 1 2 3 4 5; do
echo "Waiting for refreshDone message..."
sleep $SLEEP0
if grep '^# refresh done, switching to persist stage' $SYNC1OUT; then
awk '/^result:/{print; exit $2}' $SYNC1OUT
RC=$?
break
fi
done
if test $RC != 0 ; then
echo "refresh failed ($RC)!"
kill $PID
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Using ldapmodify to modify local entry on provider1..."
$LDAPMODIFY -D $MANAGERDN -H $URI2 -w $PASSWD <<EOF >> $TESTOUT 2>&1
dn: cn=local_user,ou=local,ou=users,$BASEDN
changeType: modify
replace: description
description: Syncrepl local_user
EOF
RC=32
for i in 0 1 2 3 4 5; do
echo "Waiting for syncrepl to receive changes..."
sleep $SLEEP0
if grep -q '^description: Syncrepl local_user' $SYNC1OUT; then
RC=0
break
fi
done
kill $PID
if test $RC != 0 ; then
echo "syncrepl failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Check that remote entries are NOT replicated..."
if grep 'ou=remote,' $SYNC1OUT; then
echo "remote entries were unexpectedly replicated!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit 1
fi
echo "Starting refreshAndPersist search on provider2..."
$LDAPRSEARCH -D $MANAGERDN -H $URI3 -w $PASSWD -MM -E sync=rp -b $BASEDN '*' + 2>&1 > $SYNC2OUT &
PID=$!
RC=32
for i in 0 1 2 3 4 5; do
echo "Waiting for refreshDone message..."
sleep $SLEEP0
if grep '^# refresh done, switching to persist stage' $SYNC2OUT; then
awk '/^result:/{print; exit $2}' $SYNC2OUT
RC=$?
break
fi
done
if test $RC != 0 ; then
echo "refresh failed ($RC)!"
kill $PID
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Using ldapmodify to modify local entry on privider2..."
$LDAPMODIFY -D $MANAGERDN -H $URI3 -w $PASSWD <<EOF >> $TESTOUT 2>&1
dn: cn=local_user,ou=local,ou=users,$BASEDN
changeType: modify
replace: description
description: Syncrepl local_user
EOF
RC=32
for i in 0 1 2 3 4 5; do
echo "Waiting for syncrepl to receive changes..."
sleep $SLEEP0
if grep -q '^description: Syncrepl local_user' $SYNC2OUT; then
RC=0
break
fi
done
if test $RC != 0 ; then
echo "syncrepl failed ($RC)!"
kill $PID
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Using ldapmodify to modify remote entry on privider2..."
$LDAPMODIFY -D $MANAGERDN -H $URI3 -w $PASSWD <<EOF >> $TESTOUT 2>&1
dn: cn=remote_user,ou=remote,ou=users,$BASEDN
changeType: modify
replace: description
description: Syncrepl remote_user
EOF
RC=32
for i in 0 1 2 3 4 5; do
echo "Waiting for syncrepl to receive changes..."
sleep $SLEEP0
if grep -q '^description: Syncrepl remote_user' $SYNC2OUT; then
RC=0
break
fi
done
kill $PID
if test $RC != 0 ; then
echo "syncrepl failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
test $KILLSERVERS != no && kill -HUP $KILLPIDS
echo ">>>>> Test succeeded"
exit 0