From: Howard Chu Date: Fri, 24 Jul 2015 17:34:11 +0000 (+0100) Subject: ITS#8203 more fixes for #8036/#7904. X-Git-Tag: OPENLDAP_REL_ENG_2_4_42~9 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6f5f113612f9175e589d1509005b1af78b2b5f68;p=openldap ITS#8203 more fixes for #8036/#7904. --- diff --git a/servers/slapd/back-mdb/dn2id.c b/servers/slapd/back-mdb/dn2id.c index d1845f7109..43b82ce076 100644 --- a/servers/slapd/back-mdb/dn2id.c +++ b/servers/slapd/back-mdb/dn2id.c @@ -922,3 +922,45 @@ mdb_dn2id_walk( } return rc; } + +/* restore the nrdn/rdn pointers after a txn reset */ +void mdb_dn2id_wrestore ( + Operation *op, + IdScopes *isc +) +{ + MDB_val key, data; + diskNode *d; + int rc, n, nrlen; + char *ptr; + + /* We only need to restore up to the n-1th element, + * the nth element will be replaced anyway + */ + key.mv_size = sizeof(ID); + for ( n=0; nnumrdns-1; n++ ) { + key.mv_data = &isc->scopes[n+1].mid; + rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET ); + if ( rc ) + continue; + /* we can't use this data directly since its nrlen + * is missing the high bit setting, so copy it and + * set it properly. we just copy enough to satisfy + * mdb_dup_compare. + */ + d = data.mv_data; + nrlen = ((d->nrdnlen[0] & 0x7f) << 8) | d->nrdnlen[1]; + ptr = op->o_tmpalloc( nrlen+2, op->o_tmpmemctx ); + memcpy( ptr, data.mv_data, nrlen+2 ); + key.mv_data = &isc->scopes[n].mid; + data.mv_data = ptr; + data.mv_size = 1; + *ptr |= 0x80; + mdb_cursor_get( isc->mc, &key, &data, MDB_GET_BOTH ); + + /* now we're back to where we wanted to be */ + d = data.mv_data; + isc->nrdns[n].bv_val = d->nrdn; + isc->rdns[n].bv_val = d->nrdn+isc->nrdns[n].bv_len+1; + } +} diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h index 22cdaab72f..b7f9c632d0 100644 --- a/servers/slapd/back-mdb/proto-mdb.h +++ b/servers/slapd/back-mdb/proto-mdb.h @@ -146,6 +146,10 @@ int mdb_dn2id_walk( Operation *op, struct IdScopes *isc ); +void mdb_dn2id_wrestore( + Operation *op, + struct IdScopes *isc ); + MDB_cmp_func mdb_dup_compare; /* diff --git a/servers/slapd/back-mdb/search.c b/servers/slapd/back-mdb/search.c index 1a99f974db..14a2c6bc4f 100644 --- a/servers/slapd/back-mdb/search.c +++ b/servers/slapd/back-mdb/search.c @@ -358,30 +358,22 @@ mdb_writewait( Operation *op, slap_callback *sc ) } static int -mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd, ID2 *scopes ) +mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd, IdScopes *isc ) { + MDB_val key; int rc = 0; ww->flag = 0; mdb_txn_renew( ww->txn ); mdb_cursor_renew( ww->txn, mci ); mdb_cursor_renew( ww->txn, mcd ); - if ( scopes[0].mid > 1 ) { - MDB_val key; - int i; - key.mv_size = sizeof(ID); - for ( i=1; imcd ) { /* scope-based search using dn2id_walk */ + MDB_val data; - if ( ww->mcd ) { - MDB_val key, data; + if ( isc->numrdns ) + mdb_dn2id_wrestore( op, isc ); - key.mv_size = sizeof(ID); key.mv_data = &ww->key; data = ww->data; rc = mdb_cursor_get( mcd, &key, &data, MDB_GET_BOTH ); @@ -400,6 +392,14 @@ mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd, ID2 } op->o_tmpfree( ww->data.mv_data, op->o_tmpmemctx ); ww->data.mv_data = NULL; + } else if ( isc->scopes[0].mid > 1 ) { /* candidate-based search */ + int i; + for ( i=1; iscopes[0].mid; i++ ) { + if ( !isc->scopes[i].mval.mv_data ) + continue; + key.mv_data = &isc->scopes[i].mid; + mdb_cursor_get( mcd, &key, &isc->scopes[i].mval, MDB_SET ); + } } return rc; } @@ -1049,7 +1049,7 @@ notfound: rs->sr_ref = NULL; if ( wwctx.flag ) { - rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, scopes ); + rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, &isc ); if ( rs->sr_err ) { send_ldap_result( op, rs ); goto done; @@ -1111,7 +1111,7 @@ notfound: goto done; } if ( wwctx.flag ) { - rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, scopes ); + rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, &isc ); if ( rs->sr_err ) { send_ldap_result( op, rs ); goto done;