/* syncprov.c - syncrepl provider */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2004-2017 The OpenLDAP Foundation.
+ * Copyright 2004-2018 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
int sl_numcsns;
int sl_num;
int sl_size;
+ int sl_playing;
slog_entry *sl_head;
slog_entry *sl_tail;
ldap_pvt_thread_mutex_t sl_mutex;
opm.o_bd->bd_info = on->on_info->oi_orig;
opm.o_managedsait = SLAP_CONTROL_NONCRITICAL;
opm.o_no_schema_check = 1;
+ opm.o_dont_replicate = 1;
opm.o_opid = -1;
opm.o_bd->be_modify( &opm, &rsm );
* wipe out anything in the log if we see them.
*/
ldap_pvt_thread_mutex_lock( &sl->sl_mutex );
+ /* can only do this if no one else is reading the log at the moment */
+ if (!sl->sl_playing) {
while ( se = sl->sl_head ) {
sl->sl_head = se->se_next;
ch_free( se );
}
sl->sl_tail = NULL;
sl->sl_num = 0;
+ }
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
return;
}
}
}
sl->sl_num++;
+ if (!sl->sl_playing) {
while ( sl->sl_num > sl->sl_size ) {
int i;
se = sl->sl_head;
ch_free( se );
sl->sl_num--;
}
+ }
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
}
}
num = sl->sl_num;
i = 0;
nmods = 0;
+ sl->sl_playing++;
+ ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
uuids = op->o_tmpalloc( (num+1) * sizeof( struct berval ) +
num * UUID_LEN, op->o_tmpmemctx );
AC_MEMCPY(uuids[j].bv_val, se->se_uuid.bv_val, UUID_LEN);
uuids[j].bv_len = UUID_LEN;
}
+ ldap_pvt_thread_mutex_lock( &sl->sl_mutex );
+ sl->sl_playing--;
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
ndel = i;
op->o_tmpfree( uuids, op->o_tmpmemctx );
}
+static int
+syncprov_new_ctxcsn( opcookie *opc, syncprov_info_t *si, int csn_changed, int numvals, BerVarray vals )
+{
+ unsigned i;
+ int j, sid;
+
+ for ( i=0; i<numvals; i++ ) {
+ sid = slap_parse_csn_sid( &vals[i] );
+ for ( j=0; j<si->si_numcsns; j++ ) {
+ if ( sid < si->si_sids[j] )
+ break;
+ if ( sid == si->si_sids[j] ) {
+ if ( ber_bvcmp( &vals[i], &si->si_ctxcsn[j] ) > 0 ) {
+ ber_bvreplace( &si->si_ctxcsn[j], &vals[i] );
+ csn_changed = 1;
+ }
+ break;
+ }
+ }
+
+ if ( j == si->si_numcsns || sid != si->si_sids[j] ) {
+ slap_insert_csn_sids( (struct sync_cookie *)&si->si_ctxcsn,
+ j, sid, &vals[i] );
+ csn_changed = 1;
+ }
+ }
+ if ( csn_changed )
+ si->si_dirty = 0;
+ ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
+
+ if ( csn_changed ) {
+ syncops *ss;
+ ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
+ for ( ss = si->si_ops; ss; ss = ss->s_next ) {
+ if ( ss->s_op->o_abandon )
+ continue;
+ /* Send the updated csn to all syncrepl consumers,
+ * including the server from which it originated.
+ * The syncrepl consumer and syncprov provider on
+ * the originating server may be configured to store
+ * their csn values in different entries.
+ */
+ syncprov_qresp( opc, ss, LDAP_SYNC_NEW_COOKIE );
+ }
+ ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
+ }
+ return csn_changed;
+}
+
static int
syncprov_op_response( Operation *op, SlapReply *rs )
{
}
/* Don't do any processing for consumer contextCSN updates */
- if ( op->o_dont_replicate ) {
- if ( op->o_tag == LDAP_REQ_MODIFY &&
- op->orm_modlist->sml_op == LDAP_MOD_REPLACE &&
- op->orm_modlist->sml_desc == slap_schema.si_ad_contextCSN ) {
+ if ( SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) &&
+ op->o_tag == LDAP_REQ_MODIFY &&
+ op->orm_modlist &&
+ op->orm_modlist->sml_op == LDAP_MOD_REPLACE &&
+ op->orm_modlist->sml_desc == slap_schema.si_ad_contextCSN ) {
/* Catch contextCSN updates from syncrepl. We have to look at
* all the attribute values, as there may be more than one csn
* that changed, and only one can be passed in the csn queue.
*/
- Modifications *mod = op->orm_modlist;
- unsigned i;
- int j, sid;
-
- for ( i=0; i<mod->sml_numvals; i++ ) {
- sid = slap_parse_csn_sid( &mod->sml_values[i] );
- for ( j=0; j<si->si_numcsns; j++ ) {
- if ( sid < si->si_sids[j] )
- break;
- if ( sid == si->si_sids[j] ) {
- if ( ber_bvcmp( &mod->sml_values[i], &si->si_ctxcsn[j] ) > 0 ) {
- ber_bvreplace( &si->si_ctxcsn[j], &mod->sml_values[i] );
- csn_changed = 1;
- }
- break;
- }
- }
-
- if ( j == si->si_numcsns || sid != si->si_sids[j] ) {
- slap_insert_csn_sids( (struct sync_cookie *)&si->si_ctxcsn,
- j, sid, &mod->sml_values[i] );
- csn_changed = 1;
- }
- }
+ csn_changed = syncprov_new_ctxcsn( opc, si, csn_changed,
+ op->orm_modlist->sml_numvals, op->orm_modlist->sml_values );
if ( csn_changed )
- si->si_dirty = 0;
- ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
-
- if ( csn_changed ) {
- syncops *ss;
- ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
- for ( ss = si->si_ops; ss; ss = ss->s_next ) {
- if ( ss->s_op->o_abandon )
- continue;
- /* Send the updated csn to all syncrepl consumers,
- * including the server from which it originated.
- * The syncrepl consumer and syncprov provider on
- * the originating server may be configured to store
- * their csn values in different entries.
- */
- syncprov_qresp( opc, ss, LDAP_SYNC_NEW_COOKIE );
- }
- ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
- }
- } else {
- ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
- }
+ si->si_numops++;
+ goto leave;
+ }
+ if ( op->o_dont_replicate ) {
if ( csn_changed )
si->si_numops++;
+ ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
goto leave;
}
+ /* If we're adding the context entry, parse all of its contextCSNs */
+ if ( op->o_tag == LDAP_REQ_ADD &&
+ dn_match( &op->o_req_ndn, &si->si_contextdn )) {
+ Attribute *a = attr_find( op->ora_e->e_attrs, slap_schema.si_ad_contextCSN );
+ if ( a ) {
+ csn_changed = syncprov_new_ctxcsn( opc, si, csn_changed, a->a_numvals, a->a_vals );
+ if ( csn_changed )
+ si->si_numops++;
+ goto added;
+ }
+ }
+
if ( csn_changed )
si->si_numops++;
if ( si->si_chkops || si->si_chktime ) {
si->si_dirty = !csn_changed;
ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
+added:
if ( do_check ) {
ldap_pvt_thread_rdwr_rlock( &si->si_csn_rwlock );
syncprov_checkpoint( op, on );
int i, sid;
sid = slap_parse_csn_sid( &a->a_nvals[0] );
- /* Don't send changed entries back to the originator */
- if ( sid == srs->sr_state.sid && srs->sr_state.numcsns ) {
- Debug( LDAP_DEBUG_SYNC,
- "Entry %s changed by peer, ignored\n",
- rs->sr_entry->e_name.bv_val, 0, 0 );
- return LDAP_SUCCESS;
- }
-
/* If not a persistent search */
if ( !ss->ss_so ) {
/* Make sure entry is less than the snapshot'd contextCSN */