/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2000-2014 The OpenLDAP Foundation.
+ * Copyright 2000-2017 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static ID2 *scope_chunk_get( Operation *op )
{
- struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
ID2 *ret = NULL;
ldap_pvt_thread_pool_getkey( op->o_threadctx, (void *)scope_chunk_get,
static void scope_chunk_ret( Operation *op, ID2 *scopes )
{
- struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
void *ret = NULL;
ldap_pvt_thread_pool_getkey( op->o_threadctx, (void *)scope_chunk_get,
ID key;
MDB_val data;
int flag;
+ int nentries;
} ww_ctx;
/* ITS#7904 if we get blocked while writing results to client,
* case return an LDAP_BUSY error - let the client know this search
* couldn't succeed, but might succeed on a retry.
*/
+static void
+mdb_rtxn_snap( Operation *op, ww_ctx *ww )
+{
+ /* save cursor position and release read txn */
+ if ( ww->mcd ) {
+ MDB_val key, data;
+ mdb_cursor_get( ww->mcd, &key, &data, MDB_GET_CURRENT );
+ memcpy( &ww->key, key.mv_data, sizeof(ID) );
+ ww->data.mv_size = data.mv_size;
+ ww->data.mv_data = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
+ memcpy(ww->data.mv_data, data.mv_data, data.mv_size);
+ }
+ mdb_txn_reset( ww->txn );
+ ww->flag = 1;
+}
+
static void
mdb_writewait( Operation *op, slap_callback *sc )
{
ww_ctx *ww = sc->sc_private;
if ( !ww->flag ) {
- if ( ww->mcd ) {
- MDB_val key, data;
- mdb_cursor_get( ww->mcd, &key, &data, MDB_GET_CURRENT );
- memcpy( &ww->key, key.mv_data, sizeof(ID) );
- ww->data.mv_size = data.mv_size;
- ww->data.mv_data = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
- memcpy(ww->data.mv_data, data.mv_data, data.mv_size);
- }
- mdb_txn_reset( ww->txn );
- ww->flag = 1;
+ mdb_rtxn_snap( op, ww );
}
}
static int
-mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd )
+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 ( ww->mcd ) {
- MDB_val key, data;
- key.mv_size = sizeof(ID);
+
+ key.mv_size = sizeof(ID);
+ if ( ww->mcd ) { /* scope-based search using dn2id_walk */
+ MDB_val data;
+
+ if ( isc->numrdns )
+ mdb_dn2id_wrestore( op, isc );
+
key.mv_data = &ww->key;
data = ww->data;
rc = mdb_cursor_get( mcd, &key, &data, MDB_GET_BOTH );
}
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; i<isc->scopes[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;
}
}
wwctx.flag = 0;
+ wwctx.nentries = 0;
/* If we're running in our own read txn */
if ( moi == &opinfo ) {
cb.sc_writewait = mdb_writewait;
goto done;
}
- rs->sr_err = mdb_entry_decode( op, ltid, &edata, &e );
+ rs->sr_err = mdb_entry_decode( op, ltid, &edata, id, &e );
if ( rs->sr_err ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error in mdb_entry_decode";
ber_bvarray_free( erefs );
rs->sr_ref = NULL;
- if ( wwctx.flag ) {
- rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd );
- if ( rs->sr_err ) {
- send_ldap_result( op, rs );
- goto done;
- }
- }
-
goto loop_continue;
}
/* check size limit */
if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {
- mdb_entry_return( op, e );
+ if (e != base)
+ mdb_entry_return( op, e );
e = NULL;
send_paged_response( op, rs, &lastid, tentries );
goto done;
}
goto done;
}
- if ( wwctx.flag ) {
- rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd );
- if ( rs->sr_err ) {
- send_ldap_result( op, rs );
- goto done;
- }
- }
}
} else {
}
loop_continue:
+ if ( moi == &opinfo && !wwctx.flag && mdb->mi_rtxn_size ) {
+ wwctx.nentries++;
+ if ( wwctx.nentries >= mdb->mi_rtxn_size ) {
+ MDB_envinfo ei;
+ wwctx.nentries = 0;
+ mdb_env_info(mdb->mi_dbenv, &ei);
+ if ( ei.me_last_txnid > mdb_txn_id( ltid ))
+ mdb_rtxn_snap( op, &wwctx );
+ }
+ }
+ if ( wwctx.flag ) {
+ rs->sr_err = mdb_waitfixup( op, &wwctx, mci, mcd, &isc );
+ if ( rs->sr_err ) {
+ send_ldap_result( op, rs );
+ goto done;
+ }
+ }
+
if( e != NULL ) {
if ( e != base )
mdb_entry_return( op, e );