/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2003-2017 The OpenLDAP Foundation.
+ * Copyright 2003-2018 The OpenLDAP Foundation.
* Portions Copyright 2003 by IBM Corporation.
* Portions Copyright 2003-2008 by Howard Chu, Symas Corporation.
* All rights reserved.
typedef struct cookie_state {
ldap_pvt_thread_mutex_t cs_mutex;
+ ldap_pvt_thread_cond_t cs_cond;
struct berval *cs_vals;
int *cs_sids;
int cs_num;
int cs_age;
int cs_ref;
+ int cs_updating;
/* pending changes, not yet committed */
ldap_pvt_thread_mutex_t cs_pmutex;
struct berval *cookieCSN );
static int syncrepl_updateCookie(
syncinfo_t *, Operation *,
- struct sync_cookie * );
+ struct sync_cookie *, int save );
static struct berval * slap_uuidstr_from_normalized(
struct berval *, struct berval *, void * );
static int syncrepl_add_glue_ancestors(
if ( ( rc = syncrepl_message_to_op( si, op, msg ) ) == LDAP_SUCCESS &&
syncCookie.ctxcsn )
{
- rc = syncrepl_updateCookie( si, op, &syncCookie );
+ rc = syncrepl_updateCookie( si, op, &syncCookie, 0 );
} else switch ( rc ) {
case LDAP_ALREADY_EXISTS:
case LDAP_NO_SUCH_OBJECT:
syncstate, syncUUID, syncCookie.ctxcsn ) ) == LDAP_SUCCESS &&
syncCookie.ctxcsn )
{
- rc = syncrepl_updateCookie( si, op, &syncCookie );
+ rc = syncrepl_updateCookie( si, op, &syncCookie, 0 );
}
}
if ( punlock >= 0 ) {
}
if ( syncCookie.ctxcsn && match < 0 && err == LDAP_SUCCESS )
{
- rc = syncrepl_updateCookie( si, op, &syncCookie );
+ rc = syncrepl_updateCookie( si, op, &syncCookie, 1 );
}
if ( si->si_refreshCount ) {
LDAP_SLIST_REMOVE( &op->o_extra, si->si_refreshTxn, OpExtra, oe_next );
if ( syncCookie.ctxcsn )
{
- rc = syncrepl_updateCookie( si, op, &syncCookie);
+ rc = syncrepl_updateCookie( si, op, &syncCookie, 1 );
}
if ( si->si_presentlist ) {
presentlist_free( si->si_presentlist );
op->o_callback = &cb;
slap_op_time( &op->o_time, &op->o_tincr );
+ Debug( LDAP_DEBUG_SYNC, "syncrepl_message_to_op: %s tid %x\n",
+ si->si_ridtxt, op->o_tid, 0 );
+
switch( op->o_tag ) {
case LDAP_REQ_ADD:
case LDAP_REQ_MODIFY:
int freecsn = 1;
Debug( LDAP_DEBUG_SYNC,
- "syncrepl_entry: %s LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_%s)\n",
- si->si_ridtxt, syncrepl_state2str( syncstate ), 0 );
+ "syncrepl_entry: %s LDAP_RES_SEARCH_ENTRY(LDAP_SYNC_%s) tid %x\n",
+ si->si_ridtxt, syncrepl_state2str( syncstate ), op->o_tid );
if (( syncstate == LDAP_SYNC_PRESENT || syncstate == LDAP_SYNC_ADD ) ) {
if ( !si->si_refreshPresent && !si->si_refreshDone ) {
syncrepl_updateCookie(
syncinfo_t *si,
Operation *op,
- struct sync_cookie *syncCookie )
+ struct sync_cookie *syncCookie,
+ int save )
{
Backend *be = op->o_bd;
Modifications mod;
mod.sml_next = NULL;
ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
+ while ( si->si_cookieState->cs_updating )
+ ldap_pvt_thread_cond_wait( &si->si_cookieState->cs_cond, &si->si_cookieState->cs_mutex );
#ifdef CHECK_CSN
for ( i=0; i<syncCookie->numcsns; i++ ) {
ch_free( sc.sids );
return 0;
}
+
+ si->si_cookieState->cs_updating = 1;
+ ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
+
op->o_bd = si->si_wbe;
slap_queue_csn( op, &first );
op->o_req_ndn = si->si_contextdn;
/* update contextCSN */
- op->o_dont_replicate = 1;
+ op->o_dont_replicate = !save;
+
+ /* avoid timestamp collisions */
+ if ( save )
+ slap_op_time( &op->o_time, &op->o_tincr );
mod.sml_numvals = sc.numcsns;
mod.sml_values = sc.ctxcsn;
Entry *e = slap_create_context_csn_entry( op->o_bd, NULL );
rs_reinit( &rs_modify, REP_RESULT );
rc = slap_mods2entry( &mod, &e, 0, 1, &text, txtbuf, textlen);
+ slap_queue_csn( op, &first );
+ op->o_tag = LDAP_REQ_ADD;
op->ora_e = e;
rc = op->o_bd->be_add( op, &rs_modify );
if ( e == op->ora_e )
op->orm_no_opattrs = 0;
op->o_dont_replicate = 0;
+ ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex );
if ( rs_modify.sr_err == LDAP_SUCCESS ) {
slap_sync_cookie_free( &si->si_syncCookie, 0 );
}
#endif
+ si->si_cookieState->cs_updating = 0;
+ ldap_pvt_thread_cond_broadcast( &si->si_cookieState->cs_cond );
ldap_pvt_thread_mutex_unlock( &si->si_cookieState->cs_mutex );
op->o_bd = be;
if ( !sie->si_cookieState->cs_ref ) {
ch_free( sie->si_cookieState->cs_sids );
ber_bvarray_free( sie->si_cookieState->cs_vals );
+ ldap_pvt_thread_cond_destroy( &sie->si_cookieState->cs_cond );
ldap_pvt_thread_mutex_destroy( &sie->si_cookieState->cs_mutex );
ch_free( sie->si_cookieState->cs_psids );
ber_bvarray_free( sie->si_cookieState->cs_pvals );
si->si_cookieState = ch_calloc( 1, sizeof( cookie_state ));
ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_mutex );
ldap_pvt_thread_mutex_init( &si->si_cookieState->cs_pmutex );
+ ldap_pvt_thread_cond_init( &si->si_cookieState->cs_cond );
c->be->be_syncinfo = si;
}