/* syncprov.c - syncrepl provider */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2004-2005 The OpenLDAP Foundation.
+ * Copyright 2004-2006 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
syncres *sr;
Entry *e;
opcookie opc;
- int rc;
+ int rc = 0;
opc.son = on;
op->o_bd->bd_info = (BackendInfo *)on->on_info;
op->o_private = NULL;
op->o_callback = NULL;
- syncprov_qplay( op, on, so );
+ (void)syncprov_qplay( op, on, so );
/* decrement use count... */
syncprov_free_syncop( so );
so->s_flags |= PS_FIND_BASE;
}
if ( so->s_flags & PS_IS_DETACHED ) {
+ int wake=0;
ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
if ( !so->s_qtask ) {
so->s_qtask = ldap_pvt_runqueue_insert( &slapd_rq, RUNQ_INTERVAL,
syncprov_qtask, so, "syncprov_qtask",
so->s_op->o_conn->c_peer_name.bv_val );
++so->s_inuse;
+ wake = 1;
} else {
if (!ldap_pvt_runqueue_isrunning( &slapd_rq, so->s_qtask ) &&
!so->s_qtask->next_sched.tv_sec ) {
ldap_pvt_runqueue_resched( &slapd_rq, so->s_qtask, 0 );
so->s_qtask->interval.tv_sec = RUNQ_INTERVAL;
++so->s_inuse;
+ wake = 1;
}
}
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+ if ( wake )
+ slap_wake_listener();
}
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
return LDAP_SUCCESS;
int rc;
struct berval newdn;
int freefdn = 0;
+ BackendDB *b0 = op->o_bd, db;
fc.fdn = &op->o_req_ndn;
/* compute new DN */
freefdn = 1;
}
if ( op->o_tag != LDAP_REQ_ADD ) {
+ if ( !SLAP_ISOVERLAY( op->o_bd )) {
+ db = *op->o_bd;
+ op->o_bd = &db;
+ }
op->o_bd->bd_info = (BackendInfo *)on->on_info;
rc = be_entry_get_rw( op, fc.fdn, NULL, NULL, 0, &e );
/* If we're sending responses now, make a copy and unlock the DB */
e = e2;
}
op->o_bd->bd_info = (BackendInfo *)on;
- if ( rc ) return;
+ if ( rc ) {
+ op->o_bd = b0;
+ return;
+ }
} else {
e = op->ora_e;
}
if ( freefdn ) {
op->o_tmpfree( fc.fdn->bv_val, op->o_tmpmemctx );
}
+ op->o_bd = b0;
}
static int
se->se_next = NULL;
se->se_tag = op->o_tag;
- se->se_uuid.bv_val = (char *)(se+1);
+ se->se_uuid.bv_val = (char *)(&se[1]);
AC_MEMCPY( se->se_uuid.bv_val, opc->suuid.bv_val, opc->suuid.bv_len );
se->se_uuid.bv_len = opc->suuid.bv_len;
sl->sl_mincsn.bv_len = se->se_csn.bv_len;
ch_free( se );
sl->sl_num--;
- if ( !sl->sl_head ) {
- sl->sl_tail = NULL;
- }
}
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
}
/* enter with sl->sl_mutex locked, release before returning */
static void
syncprov_playlog( Operation *op, SlapReply *rs, sessionlog *sl,
- struct berval *oldcsn, struct berval *ctxcsn )
+ sync_control *srs, struct berval *ctxcsn )
{
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
slog_entry *se;
int i, j, ndel, num, nmods, mmods;
+ char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
BerVarray uuids;
+ struct berval delcsn;
if ( !sl->sl_num ) {
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
uuids = op->o_tmpalloc( (num+1) * sizeof( struct berval ) +
num * UUID_LEN, op->o_tmpmemctx );
-
uuids[0].bv_val = (char *)(uuids + num + 1);
+ delcsn.bv_len = 0;
+ delcsn.bv_val = cbuf;
+
/* Make a copy of the relevant UUIDs. Put the Deletes up front
* and everything else at the end. Do this first so we can
* unlock the list mutex.
*/
for ( se=sl->sl_head; se; se=se->se_next ) {
- if ( ber_bvcmp( &se->se_csn, oldcsn ) < 0 ) continue;
+ if ( ber_bvcmp( &se->se_csn, &srs->sr_state.ctxcsn ) <= 0 ) continue;
if ( ber_bvcmp( &se->se_csn, ctxcsn ) > 0 ) break;
if ( se->se_tag == LDAP_REQ_DELETE ) {
j = i;
i++;
+ AC_MEMCPY( cbuf, se->se_csn.bv_val, se->se_csn.bv_len );
+ delcsn.bv_len = se->se_csn.bv_len;
} else {
nmods++;
j = num - nmods;
mf.f_av_value = uuids[i];
cb.sc_private = NULL;
fop.ors_slimit = 1;
+ frs.sr_nentries = 0;
rc = fop.o_bd->be_search( &fop, &frs );
/* If entry was not found, add to delete list */
fop.o_bd->bd_info = (BackendInfo *)on;
}
if ( ndel ) {
+ struct berval cookie;
+
+ slap_compose_sync_cookie( op, &cookie, &delcsn, srs->sr_state.rid );
uuids[ndel].bv_val = NULL;
- syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, NULL, 0, uuids, 1 );
+ syncprov_sendinfo( op, rs, LDAP_TAG_SYNC_ID_SET, &cookie, 0, uuids, 1 );
+ op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
}
+ op->o_tmpfree( uuids, op->o_tmpmemctx );
}
static int
op2->ors_filterstr.bv_val = ptr;
strcpy( ptr, so->s_filterstr.bv_val );
op2->ors_filterstr.bv_len = so->s_filterstr.bv_len;
- op2->ors_filter = str2filter( ptr );
+ op2->ors_filter = filter_dup( op->ors_filter, NULL );
so->s_op = op2;
/* Copy any cached group ACLs individually */
LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op2, o_next );
so->s_flags |= PS_IS_DETACHED;
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
+
+ /* Prevent anyone else from trying to send a result for this op */
+ op->o_abandon = 1;
}
static int
}
if ( a ) {
/* Make sure entry is less than the snapshot'd contextCSN */
- if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 )
+ if ( ber_bvcmp( &a->a_nvals[0], &ss->ss_ctxcsn ) > 0 ) {
+ Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s greater than snapshot %s\n",
+ rs->sr_entry->e_name.bv_val,
+ a->a_nvals[0].bv_val,
+ ss->ss_ctxcsn.bv_val );
return LDAP_SUCCESS;
+ }
/* Don't send the ctx entry twice */
if ( !BER_BVISNULL( &srs->sr_state.ctxcsn ) &&
- bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) )
+ bvmatch( &a->a_nvals[0], &srs->sr_state.ctxcsn ) ) {
+ Debug( LDAP_DEBUG_SYNC, "Entry %s CSN %s matches ctx %s\n",
+ rs->sr_entry->e_name.bv_val,
+ a->a_nvals[0].bv_val,
+ srs->sr_state.ctxcsn.bv_val );
return LDAP_SUCCESS;
+ }
}
rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
op->o_tmpmemctx );
/* syncprov_findbase expects to be called as a callback... */
sc.sc_private = &opc;
opc.son = on;
+ ldap_pvt_thread_mutex_init( &so.s_mutex );
cb = op->o_callback;
op->o_callback = ≻
rs->sr_err = syncprov_findbase( op, &fc );
op->o_callback = cb;
+ ldap_pvt_thread_mutex_destroy( &so.s_mutex );
if ( rs->sr_err != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
if ( ber_bvcmp( &srs->sr_state.ctxcsn, &sl->sl_mincsn ) >= 0 ) {
do_present = 0;
/* mutex is unlocked in playlog */
- syncprov_playlog( op, rs, sl, &srs->sr_state.ctxcsn, &ctxcsn );
+ syncprov_playlog( op, rs, sl, srs, &ctxcsn );
} else {
ldap_pvt_thread_mutex_unlock( &sl->sl_mutex );
}
if ( si ) {
if ( si->si_logs ) {
+ slog_entry *se = si->si_logs->sl_head;
+
+ while ( se ) {
+ slog_entry *se_next = se->se_next;
+ ch_free( se );
+ se = se_next;
+ }
+
ch_free( si->si_logs );
}
ldap_pvt_thread_mutex_destroy( &si->si_mods_mutex );