typedef struct opcookie {
slap_overinst *son;
syncmatches *smatches;
+ modtarget *smt;
struct berval sdn; /* DN of entry, for deletes */
struct berval sndn;
struct berval suuid; /* UUID of entry */
struct berval sctxcsn;
- short ssid; /* sid of op csn */
+ short osid; /* sid of op csn */
+ short rsid; /* sid of relay */
short sreference; /* Is the entry a reference? */
} opcookie;
ctrls[1] = NULL;
csns[0] = opc->sctxcsn;
BER_BVZERO( &csns[1] );
- slap_compose_sync_cookie( op, &cookie, csns, so->s_rid, slap_serverID );
+ slap_compose_sync_cookie( op, &cookie, csns, so->s_rid, slap_serverID ? slap_serverID : -1 );
- Debug( LDAP_DEBUG_SYNC, "syncprov_sendresp: cookie=%s\n", cookie.bv_val, 0, 0 );
+#ifdef LDAP_DEBUG
+ if ( so->s_sid > 0 ) {
+ Debug( LDAP_DEBUG_SYNC, "syncprov_sendresp: to=%03x, cookie=%s\n",
+ so->s_sid, cookie.bv_val, 0 );
+ } else {
+ Debug( LDAP_DEBUG_SYNC, "syncprov_sendresp: cookie=%s\n",
+ cookie.bv_val, 0, 0 );
+ }
+#endif
e_uuid.e_attrs = &a_uuid;
a_uuid.a_desc = slap_schema.si_ad_entryUUID;
syncprov_info_t *si = opc->son->on_bi.bi_private;
slap_compose_sync_cookie( NULL, &cookie, si->si_ctxcsn,
- so->s_rid, slap_serverID);
+ so->s_rid, slap_serverID ? slap_serverID : -1);
}
srsize = sizeof(syncres) + opc->suuid.bv_len + 1 +
fbase_cookie fc;
syncops *ss, *sprev, *snext;
- struct sync_cookie *scook;
Entry *e = NULL;
Attribute *a;
int rc;
ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
}
- scook = op->o_controls[slap_cids.sc_LDAPsync];
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
for (ss = si->si_ops, sprev = (syncops *)&si->si_ops; ss;
sprev = ss, ss=snext)
if ( ss->s_op->o_abandon )
continue;
- /* Don't send ops back to the originator */
- if ( opc->ssid && opc->ssid == ss->s_sid ) {
- Debug( LDAP_DEBUG_SYNC, "syncprov_matchops: skipping original sid %03x\n",
- opc->ssid, 0, 0 );
- continue;
- }
+ /* First time thru, check for possible skips */
+ if ( saveit || op->o_tag == LDAP_REQ_ADD ) {
- /* Don't send ops back to the messenger */
- if ( scook && scook->sid == ss->s_sid ) {
- Debug( LDAP_DEBUG_SYNC, "syncprov_matchops: skipping relayed sid %03x\n",
- scook->sid, 0, 0 );
- continue;
+ /* Don't send ops back to the originator */
+ if ( opc->osid > 0 && opc->osid == ss->s_sid ) {
+ Debug( LDAP_DEBUG_SYNC, "syncprov_matchops: skipping original sid %03x\n",
+ opc->osid, 0, 0 );
+ continue;
+ }
+
+ /* Don't send ops back to the messenger */
+ if ( opc->rsid > 0 && opc->rsid == ss->s_sid ) {
+ Debug( LDAP_DEBUG_SYNC, "syncprov_matchops: skipping relayed sid %03x\n",
+ opc->rsid, 0, 0 );
+ continue;
+ }
}
/* validate base */
oh.oh_connid = ss->s_op->o_connid;
op2.o_hdr = &oh;
op2.o_extra = op->o_extra;
+ rc = test_filter( &op2, e, ss->s_op->ors_filter );
}
+ Debug( LDAP_DEBUG_TRACE, "syncprov_matchops: sid %03x fscope %d rc %d\n",
+ ss->s_sid, fc.fscope, rc );
+
/* check if current o_req_dn is in scope and matches filter */
- if ( fc.fscope && test_filter( &op2, e, ss->s_op->ors_filter ) ==
- LDAP_COMPARE_TRUE ) {
+ if ( fc.fscope && rc == LDAP_COMPARE_TRUE ) {
if ( saveit ) {
sm = op->o_tmpalloc( sizeof(syncmatches), op->o_tmpmemctx );
sm->sm_next = opc->smatches;
}
/* Remove op from lock table */
- mtdummy.mt_op = op;
- ldap_pvt_thread_mutex_lock( &si->si_mods_mutex );
- mt = avl_find( si->si_mods, &mtdummy, sp_avl_cmp );
+ mt = opc->smt;
if ( mt ) {
modinst *mi = mt->mt_mods;
/* If there are more, promote the next one */
- ldap_pvt_thread_mutex_lock( &mt->mt_mutex );
if ( mi->mi_next ) {
+ ldap_pvt_thread_mutex_lock( &mt->mt_mutex );
mt->mt_mods = mi->mi_next;
mt->mt_op = mt->mt_mods->mi_op;
ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
} else {
+ ldap_pvt_thread_mutex_lock( &si->si_mods_mutex );
avl_delete( &si->si_mods, mt, sp_avl_cmp );
- ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
+ ldap_pvt_thread_mutex_unlock( &si->si_mods_mutex );
ldap_pvt_thread_mutex_destroy( &mt->mt_mutex );
ch_free( mt );
}
}
- ldap_pvt_thread_mutex_unlock( &si->si_mods_mutex );
if ( !BER_BVISNULL( &opc->suuid ))
op->o_tmpfree( opc->suuid.bv_val, op->o_tmpmemctx );
if ( !BER_BVISNULL( &opc->sndn ))
if ( delcsn[0].bv_len ) {
slap_compose_sync_cookie( op, &cookie, delcsn, srs->sr_state.rid,
- slap_serverID );
+ slap_serverID ? slap_serverID : -1 );
Debug( LDAP_DEBUG_SYNC, "syncprov_playlog: cookie=%s\n", cookie.bv_val, 0, 0 );
}
cb->sc_next = op->o_callback;
op->o_callback = cb;
+ opc->osid = -1;
+ opc->rsid = -1;
if ( op->o_csn.bv_val ) {
- opc->ssid = slap_parse_csn_sid( &op->o_csn );
- } else {
- opc->ssid = -1;
+ opc->osid = slap_parse_csn_sid( &op->o_csn );
+ }
+ if ( op->o_controls ) {
+ struct sync_cookie *scook =
+ op->o_controls[slap_cids.sc_LDAPsync];
+ if ( scook )
+ opc->rsid = scook->sid;
}
/* If there are active persistent searches, lock this operation.
* Currently it's not an issue because there are
* no dynamic config deletes...
*/
+ if ( slapd_shutdown )
+ return SLAPD_ABANDON;
+
if ( !ldap_pvt_thread_pool_pausecheck( &connection_pool ))
ldap_pvt_thread_yield();
ldap_pvt_thread_mutex_lock( &mt->mt_mutex );
avl_insert( &si->si_mods, mt, sp_avl_cmp, avl_dup_error );
ldap_pvt_thread_mutex_unlock( &si->si_mods_mutex );
}
+ opc->smt = mt;
}
if (( have_psearches || si->si_logs ) && op->o_tag != LDAP_REQ_ADD )
/* If we're in delta-sync mode, always send a cookie */
if ( si->si_nopres && si->si_usehint && a ) {
struct berval cookie;
- slap_compose_sync_cookie( op, &cookie, a->a_nvals, srs->sr_state.rid, slap_serverID );
+ slap_compose_sync_cookie( op, &cookie, a->a_nvals, srs->sr_state.rid, slap_serverID ? slap_serverID : -1 );
rs->sr_err = syncprov_state_ctrl( op, rs, rs->sr_entry,
LDAP_SYNC_ADD, rs->sr_ctrls, 0, 1, &cookie );
} else {
if ( ss->ss_flags & SS_CHANGED ) {
slap_compose_sync_cookie( op, &cookie, ss->ss_ctxcsn,
- srs->sr_state.rid, slap_serverID );
+ srs->sr_state.rid, slap_serverID ? slap_serverID : -1 );
Debug( LDAP_DEBUG_SYNC, "syncprov_search_response: cookie=%s\n", cookie.bv_val, 0, 0 );
}
/* If nothing has changed, shortcut it */
if ( srs->sr_state.numcsns == numcsns ) {
- int i, j;
+ int i, j, newer;
for ( i=0; i<srs->sr_state.numcsns; i++ ) {
for ( j=0; j<numcsns; j++ ) {
if ( srs->sr_state.sids[i] != sids[j] )
continue;
- if ( !bvmatch( &srs->sr_state.ctxcsn[i], &ctxcsn[j] ))
+ newer = ber_bvcmp( &srs->sr_state.ctxcsn[i], &ctxcsn[j] );
+ /* If our state is newer, tell consumer about changes */
+ if ( newer < 0 )
changed = SS_CHANGED;
+ else if ( newer > 0 ) {
+ /* our state is older, tell consumer nothing */
+ if ( sop ) {
+ syncops **sp = &si->si_ops;
+
+ ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
+ while ( *sp != sop )
+ sp = &(*sp)->s_next;
+ *sp = sop->s_next;
+ ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
+ ch_free( sop );
+ }
+ rs->sr_err = LDAP_SUCCESS;
+ rs->sr_ctrls = NULL;
+ send_ldap_result( op, rs );
+ return rs->sr_err;
+ }
break;
}
if ( changed )