BerValue oldndn;
BerValue newdn;
BerValue newndn;
+ int do_sub;
} refint_q;
typedef struct refint_data_s {
struct re_s *qtask;
refint_q *qhead;
refint_q *qtail;
+ BackendDB *db;
ldap_pvt_thread_mutex_t qmutex;
} refint_data;
+typedef struct refint_pre_s {
+ slap_overinst *on;
+ int do_sub;
+} refint_pre;
+
#define RUNQ_INTERVAL 36000 /* a long time */
static MatchingRule *mr_dnSubtreeMatch;
ber_dupbv( &id->refint_dn, &refint_dn );
ber_dupbv( &id->refint_ndn, &refint_ndn );
}
+
+ /*
+ ** find the backend that matches our configured basedn;
+ ** make sure it exists and has search and modify methods;
+ **
+ */
+
+ if ( on->on_info->oi_origdb != frontendDB ) {
+ BackendDB *db = select_backend(&id->dn, 1);
+
+ if ( db ) {
+ if ( !db->be_search || !db->be_modify ) {
+ Debug( LDAP_DEBUG_CONFIG,
+ "refint_response: backend missing search and/or modify\n",
+ 0, 0, 0 );
+ return -1;
+ }
+ id->db = db;
+ } else {
+ Debug( LDAP_DEBUG_CONFIG,
+ "refint_response: no backend for our baseDN %s??\n",
+ id->dn.bv_val, 0, 0 );
+ return -1;
+ }
+ }
return(0);
}
na = NULL;
+ /* Are we doing subtree matching or simple equality? */
+ if ( rq->do_sub ) {
for(i = 0, b = a->a_nvals; b[i].bv_val; i++) {
if(dnIsSuffix(&b[i], &rq->oldndn)) {
is_exact = b[i].bv_len == rq->oldndn.bv_len;
ber_bvarray_add_x( &na->new_nvals, &dn, op->o_tmpmemctx );
}
}
+ } else {
+ /* entry has no children, just equality matching */
+ is_exact = attr_valfind( a,
+ SLAP_MR_EQUALITY|SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH|
+ SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, &rq->oldndn, &i, NULL );
+ if ( is_exact == LDAP_SUCCESS ) {
+ na = op->o_tmpcalloc( 1,
+ sizeof( refint_attrs ),
+ op->o_tmpmemctx );
+ na->next = ip->attrs;
+ ip->attrs = na;
+ na->attr = ia->attr;
+ na->ra_numvals = 1;
+ }
+ }
/* Deleting/replacing all values and a nothing DN is configured? */
- if ( na && na->ra_numvals == i && !BER_BVISNULL(&dd->nothing) )
+ if ( na && na->ra_numvals == a->a_numvals && !BER_BVISNULL(&dd->nothing) )
na->dont_empty = 1;
Debug( LDAP_DEBUG_TRACE, "refint_search_cb: %s: %s (#%d)\n",
ftop.f_or = NULL;
op->ors_filter = &ftop;
for(ip = id->attrs; ip; ip = ip->next) {
+ /* this filter can be either EQUALITY or EXT */
fptr = op->o_tmpcalloc( sizeof(Filter) + sizeof(MatchingRuleAssertion),
1, op->o_tmpmemctx );
- /* Use (attr:dnSubtreeMatch:=value) to catch subtree rename
- * and subtree delete where supported */
- fptr->f_choice = LDAP_FILTER_EXT;
fptr->f_mra = (MatchingRuleAssertion *)(fptr+1);
fptr->f_mr_rule = mr_dnSubtreeMatch;
fptr->f_mr_rule_text = mr_dnSubtreeMatch->smr_bvoid;
if ( !rq )
break;
- for (fptr = ftop.f_or; fptr; fptr = fptr->f_next )
+ for (fptr = ftop.f_or; fptr; fptr = fptr->f_next ) {
fptr->f_mr_value = rq->oldndn;
+ /* Use (attr:dnSubtreeMatch:=value) to catch subtree rename
+ * and subtree delete where supported */
+ if (rq->do_sub)
+ fptr->f_choice = LDAP_FILTER_EXT;
+ else
+ fptr->f_choice = LDAP_FILTER_EQUALITY;
+ }
filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
SlapReply *rs
)
{
- slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
- refint_data *id = on->on_bi.bi_private;
+ refint_pre *rp;
+ slap_overinst *on;
+ refint_data *id;
BerValue pdn;
- int ac;
refint_q *rq;
- BackendDB *db = NULL;
refint_attrs *ip;
+ int ac;
/* If the main op failed or is not a Delete or ModRdn, ignore it */
if (( op->o_tag != LDAP_REQ_DELETE && op->o_tag != LDAP_REQ_MODRDN ) ||
rs->sr_err != LDAP_SUCCESS )
return SLAP_CB_CONTINUE;
- /*
- ** validate (and count) the list of attrs;
- **
- */
-
- for(ip = id->attrs, ac = 0; ip; ip = ip->next, ac++);
- if(!ac) {
- Debug( LDAP_DEBUG_TRACE,
- "refint_response called without any attributes\n", 0, 0, 0 );
- return SLAP_CB_CONTINUE;
- }
-
- /*
- ** find the backend that matches our configured basedn;
- ** make sure it exists and has search and modify methods;
- **
- */
-
- if ( on->on_info->oi_origdb != frontendDB ) {
- db = select_backend(&id->dn, 1);
-
- if ( db ) {
- if ( !db->be_search || !db->be_modify ) {
- Debug( LDAP_DEBUG_TRACE,
- "refint_response: backend missing search and/or modify\n",
- 0, 0, 0 );
- return SLAP_CB_CONTINUE;
- }
- } else {
- Debug( LDAP_DEBUG_TRACE,
- "refint_response: no backend for our baseDN %s??\n",
- id->dn.bv_val, 0, 0 );
- return SLAP_CB_CONTINUE;
- }
- }
+ rp = op->o_callback->sc_private;
+ on = rp->on;
+ id = on->on_bi.bi_private;
rq = ch_calloc( 1, sizeof( refint_q ));
ber_dupbv( &rq->olddn, &op->o_req_dn );
ber_dupbv( &rq->oldndn, &op->o_req_ndn );
- rq->db = db;
+ rq->db = id->db;
rq->rdata = id;
+ rq->do_sub = rp->do_sub;
if ( op->o_tag == LDAP_REQ_MODRDN ) {
if ( op->oq_modrdn.rs_newSup ) {
return SLAP_CB_CONTINUE;
}
+/* Check if the target entry exists and has children.
+ * Do nothing if target doesn't exist.
+ */
+static int
+refint_preop(
+ Operation *op,
+ SlapReply *rs
+)
+{
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ refint_data *id = on->on_bi.bi_private;
+ Entry *e;
+ int rc;
+
+ /* are any attrs configured? */
+ if ( !id->attrs )
+ return SLAP_CB_CONTINUE;
+
+ rc = overlay_entry_get_ov( op, &op->o_req_ndn, NULL, NULL, 0, &e, on );
+ if ( rc == LDAP_SUCCESS ) {
+ slap_callback *sc = op->o_tmpcalloc( 1,
+ sizeof(slap_callback)+sizeof(refint_pre), op->o_tmpmemctx );
+ refint_pre *rp = (refint_pre *)(sc+1);
+ rp->on = on;
+ rp->do_sub = 1; /* assume there are children */
+ if ( op->o_bd->be_has_subordinates ) {
+ int has = 0;
+ rc = op->o_bd->be_has_subordinates( op, e, &has );
+ /* there definitely are not children */
+ if ( rc == LDAP_SUCCESS && has == LDAP_COMPARE_FALSE )
+ rp->do_sub = 0;
+ }
+ overlay_entry_release_ov( op, e, 0, on );
+ sc->sc_response = refint_response;
+ sc->sc_private = rp;
+ sc->sc_next = op->o_callback;
+ op->o_callback = sc;
+ }
+ return SLAP_CB_CONTINUE;
+}
+
/*
** init_module is last so the symbols resolve "for free" --
** it expects to be called automagically during dynamic module initialization
refint.on_bi.bi_db_destroy = refint_db_destroy;
refint.on_bi.bi_db_open = refint_open;
refint.on_bi.bi_db_close = refint_close;
- refint.on_response = refint_response;
+ refint.on_bi.bi_op_delete = refint_preop;
+ refint.on_bi.bi_op_modrdn = refint_preop;
refint.on_bi.bi_cf_ocs = refintocs;
rc = config_register_schema ( refintcfg, refintocs );