/* syncprov.c - syncrepl provider */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2004-2012 The OpenLDAP Foundation.
+ * Copyright 2004-2013 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
typedef struct modtarget {
struct modinst *mt_mods;
struct modinst *mt_tail;
- Operation *mt_op;
+ struct berval mt_dn;
ldap_pvt_thread_mutex_t mt_mutex;
} modtarget;
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
-
+ LDAPControl *cp;
+ struct berval bv;
struct berval entryuuid_bv = BER_BVNULL;
ber_init2( ber, 0, LBER_USE_DER );
ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
- ctrls[num_ctrls] = op->o_tmpalloc( sizeof ( LDAPControl ), op->o_tmpmemctx );
-
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
AttributeDescription *desc = a->a_desc;
if ( desc == slap_schema.si_ad_entryUUID ) {
entry_sync_state, &entryuuid_bv );
}
- ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
- ctrls[num_ctrls]->ldctl_iscritical = (op->o_sync == SLAP_CONTROL_CRITICAL);
- ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
-
+ ret = ber_flatten2( ber, &bv, 0 );
+ if ( ret == 0 ) {
+ cp = op->o_tmpalloc( sizeof( LDAPControl ) + bv.bv_len, op->o_tmpmemctx );
+ cp->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
+ cp->ldctl_iscritical = (op->o_sync == SLAP_CONTROL_CRITICAL);
+ cp->ldctl_value.bv_val = (char *)&cp[1];
+ cp->ldctl_value.bv_len = bv.bv_len;
+ AC_MEMCPY( cp->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
+ ctrls[num_ctrls] = cp;
+ }
ber_free_buf( ber );
if ( ret < 0 ) {
int ret;
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
+ LDAPControl *cp;
+ struct berval bv;
ber_init2( ber, NULL, LBER_USE_DER );
ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
- ctrls[num_ctrls] = op->o_tmpalloc( sizeof ( LDAPControl ), op->o_tmpmemctx );
-
ber_printf( ber, "{" );
if ( send_cookie && cookie ) {
ber_printf( ber, "O", cookie );
}
ber_printf( ber, "N}" );
- ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
- ctrls[num_ctrls]->ldctl_iscritical = (op->o_sync == SLAP_CONTROL_CRITICAL);
- ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+ ret = ber_flatten2( ber, &bv, 0 );
+ if ( ret == 0 ) {
+ cp = op->o_tmpalloc( sizeof( LDAPControl ) + bv.bv_len, op->o_tmpmemctx );
+ cp->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
+ cp->ldctl_iscritical = (op->o_sync == SLAP_CONTROL_CRITICAL);
+ cp->ldctl_value.bv_val = (char *)&cp[1];
+ cp->ldctl_value.bv_len = bv.bv_len;
+ AC_MEMCPY( cp->ldctl_value.bv_val, bv.bv_val, bv.bv_len );
+ ctrls[num_ctrls] = cp;
+ }
ber_free_buf( ber );
int rc;
m1 = c1; m2 = c2;
- rc = m1->mt_op->o_req_ndn.bv_len - m2->mt_op->o_req_ndn.bv_len;
+ rc = m1->mt_dn.bv_len - m2->mt_dn.bv_len;
if ( rc ) return rc;
- return ber_bvcmp( &m1->mt_op->o_req_ndn, &m2->mt_op->o_req_ndn );
+ return ber_bvcmp( &m1->mt_dn, &m2->mt_dn );
}
/* syncprov_findbase:
syncprov_sendresp( Operation *op, opcookie *opc, syncops *so, int mode )
{
SlapReply rs = { REP_SEARCH };
- LDAPControl *ctrls[2];
struct berval cookie, csns[2];
Entry e_uuid = {0};
Attribute a_uuid = {0};
if ( so->s_op->o_abandon )
return SLAPD_ABANDON;
- ctrls[1] = NULL;
+ rs.sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2, op->o_tmpmemctx );
+ rs.sr_ctrls[1] = NULL;
+ rs.sr_flags = REP_CTRLS_MUSTBEFREED;
csns[0] = opc->sctxcsn;
BER_BVZERO( &csns[1] );
slap_compose_sync_cookie( op, &cookie, csns, so->s_rid, slap_serverID ? slap_serverID : -1 );
a_uuid.a_desc = slap_schema.si_ad_entryUUID;
a_uuid.a_nvals = &opc->suuid;
rs.sr_err = syncprov_state_ctrl( op, &rs, &e_uuid,
- mode, ctrls, 0, 1, &cookie );
+ mode, rs.sr_ctrls, 0, 1, &cookie );
op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
- rs.sr_ctrls = ctrls;
rs.sr_entry = &e_uuid;
if ( mode == LDAP_SYNC_ADD || mode == LDAP_SYNC_MODIFY ) {
e_uuid = *opc->se;
default:
assert(0);
}
- /* In case someone else freed it already? */
- if ( rs.sr_ctrls ) {
- int i;
- for ( i=0; rs.sr_ctrls[i]; i++ ) {
- if ( rs.sr_ctrls[i] == ctrls[0] ) {
- op->o_tmpfree( ctrls[0]->ldctl_value.bv_val, op->o_tmpmemctx );
- ctrls[0]->ldctl_value.bv_val = NULL;
- break;
- }
- }
- rs.sr_ctrls = NULL;
- }
-
return rs.sr_err;
}
do {
ldap_pvt_thread_mutex_lock( &so->s_mutex );
sr = so->s_res;
- if ( sr )
- so->s_res = sr->s_next;
- if ( !so->s_res )
- so->s_restail = NULL;
/* Exit loop with mutex held */
- if ( !sr || so->s_op->o_abandon )
+ if ( !sr )
break;
+ so->s_res = sr->s_next;
+ if ( !so->s_res )
+ so->s_restail = NULL;
ldap_pvt_thread_mutex_unlock( &so->s_mutex );
- if ( sr->s_mode == LDAP_SYNC_NEW_COOKIE ) {
- SlapReply rs = { REP_INTERMEDIATE };
-
- rc = syncprov_sendinfo( op, &rs, LDAP_TAG_SYNC_NEW_COOKIE,
- &sr->s_csn, 0, NULL, 0 );
- } else {
- opc.sdn = sr->s_dn;
- opc.sndn = sr->s_ndn;
- opc.suuid = sr->s_uuid;
- opc.sctxcsn = sr->s_csn;
- opc.sreference = sr->s_isreference;
- opc.se = sr->s_e;
+ if ( !so->s_op->o_abandon ) {
- rc = syncprov_sendresp( op, &opc, so, sr->s_mode );
+ if ( sr->s_mode == LDAP_SYNC_NEW_COOKIE ) {
+ SlapReply rs = { REP_INTERMEDIATE };
+ rc = syncprov_sendinfo( op, &rs, LDAP_TAG_SYNC_NEW_COOKIE,
+ &sr->s_csn, 0, NULL, 0 );
+ } else {
+ opc.sdn = sr->s_dn;
+ opc.sndn = sr->s_ndn;
+ opc.suuid = sr->s_uuid;
+ opc.sctxcsn = sr->s_csn;
+ opc.sreference = sr->s_isreference;
+ opc.se = sr->s_e;
+
+ rc = syncprov_sendresp( op, &opc, so, sr->s_mode );
+ }
}
+
if ( sr->s_e ) {
if ( !dec_mutexint( sr->s_e->e_private )) {
sr->s_e->e_private = NULL;
entry_free ( sr->s_e );
}
}
-
ch_free( sr );
+ if ( so->s_op->o_abandon )
+ continue;
+
/* Exit loop with mutex held */
ldap_pvt_thread_mutex_lock( &so->s_mutex );
+ break;
- } while (0);
+ } while (1);
/* We now only send one change at a time, to prevent one
* psearch from hogging all the CPU. Resubmit this task if
cb->sc_cleanup = syncprov_ab_cleanup;
cb->sc_next = op->o_callback;
cb->sc_private = so;
+ op->o_callback = cb;
return SLAP_CB_CONTINUE;
}
}
mt->mt_mods = mt->mt_mods->mi_next;
/* If there are more, promote the next one */
if ( mt->mt_mods ) {
- mt->mt_op = mt->mt_mods->mi_op;
ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
} else {
ldap_pvt_thread_mutex_unlock( &mt->mt_mutex );
avl_delete( &si->si_mods, mt, sp_avl_cmp );
ldap_pvt_thread_mutex_unlock( &si->si_mods_mutex );
ldap_pvt_thread_mutex_destroy( &mt->mt_mutex );
+ ch_free( mt->mt_dn.bv_val );
ch_free( mt );
}
}
mi->mi_op = op;
/* See if we're already modifying this entry... */
- mtdummy.mt_op = op;
+ mtdummy.mt_dn = op->o_req_ndn;
ldap_pvt_thread_mutex_lock( &si->si_mods_mutex );
mt = avl_find( si->si_mods, &mtdummy, sp_avl_cmp );
if ( mt ) {
mt = ch_malloc( sizeof(modtarget) );
mt->mt_mods = mi;
mt->mt_tail = mi;
- mt->mt_op = mi->mi_op;
+ ber_dupbv( &mt->mt_dn, &mi->mi_op->o_req_ndn );
ldap_pvt_thread_mutex_init( &mt->mt_mutex );
avl_insert( &si->si_mods, mt, sp_avl_cmp, avl_dup_error );
ldap_pvt_thread_mutex_unlock( &si->si_mods_mutex );
int ss_flags;
} searchstate;
-static int
-syncprov_search_cleanup( Operation *op, SlapReply *rs )
-{
- if ( rs->sr_ctrls ) {
- op->o_tmpfree( rs->sr_ctrls[0], op->o_tmpmemctx );
- op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
- rs->sr_ctrls = NULL;
- }
- return 0;
-}
-
typedef struct SyncOperationBuffer {
Operation sob_op;
Opheader sob_hdr;
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 );
+ op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
} else {
rs->sr_err = syncprov_state_ctrl( op, rs, rs->sr_entry,
LDAP_SYNC_ADD, rs->sr_ctrls, 0, 0, NULL );
rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
op->o_tmpmemctx );
rs->sr_ctrls[1] = NULL;
+ rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
rs->sr_err = syncprov_done_ctrl( op, rs, rs->sr_ctrls,
0, 1, &cookie, ( ss->ss_flags & SS_PRESENT ) ? LDAP_SYNC_REFRESH_PRESENTS :
LDAP_SYNC_REFRESH_DELETES );
* active mods gets added to it.
*/
ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
- if ( slapd_shutdown )
+ if ( slapd_shutdown ) {
+ ch_free( sop );
return SLAPD_ABANDON;
+ }
if ( !ldap_pvt_thread_pool_pausecheck( &connection_pool ))
ldap_pvt_thread_yield();
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
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;
#ifdef SLAP_CONFIG_DELETE
if ( !slapd_shutdown ) {
+ ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
for ( so=si->si_ops, sonext=so; so; so=sonext ) {
SlapReply rs = {REP_RESULT};
rs.sr_err = LDAP_UNAVAILABLE;
syncprov_drop_psearch( so, 0);
}
si->si_ops=NULL;
+ ldap_pvt_thread_mutex_unlock( &si->si_ops_mutex );
}
overlay_unregister_control( be, LDAP_CONTROL_SYNC );
#endif /* SLAP_CONFIG_DELETE */