]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-mdb/search.c
Merge remote-tracking branch 'origin/mdb.RE/0.9'
[openldap] / servers / slapd / back-mdb / search.c
index 9089016ba647d7510d951fb659dd330da559724a..bb3445b8aaabb1b440316d32259c133c118019ec 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2014 The OpenLDAP Foundation.
+ * Copyright 2000-2015 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -140,7 +140,6 @@ static int search_aliases(
        struct berval bv_alias = BER_BVC( "alias" );
        AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
        Filter  af;
-       int first = 1;
 
        aliases = stack;        /* IDL of all aliases in the database */
        curscop = aliases + MDB_IDL_DB_SIZE;    /* Aliases in the current scope */
@@ -328,6 +327,7 @@ typedef struct ww_ctx {
        ID key;
        MDB_val data;
        int flag;
+       int nentries;
 } ww_ctx;
 
 /* ITS#7904 if we get blocked while writing results to client,
@@ -340,35 +340,48 @@ typedef struct ww_ctx {
  * 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 );
@@ -387,6 +400,14 @@ mdb_waitfixup( Operation *op, ww_ctx *ww, MDB_cursor *mci, MDB_cursor *mcd )
                }
                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;
 }
@@ -807,7 +828,7 @@ loop_begin:
                                        scopeok = 1;
                        } else {
                                i = mdb_idl_search( candidates, id );
-                               if ( candidates[i] == id )
+                               if (i <= candidates[0] && candidates[i] == id )
                                        scopeok = 1;
                        }
                        if ( scopeok )
@@ -1035,14 +1056,6 @@ notfound:
                        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;
                }
 
@@ -1097,13 +1110,6 @@ notfound:
                                        }
                                        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 {
@@ -1114,6 +1120,21 @@ notfound:
                }
 
 loop_continue:
+               if ( moi == &opinfo && !wwctx.flag && mdb->mi_rtxn_size ) {
+                       wwctx.nentries++;
+                       if ( wwctx.nentries >= mdb->mi_rtxn_size ) {
+                               wwctx.nentries = 0;
+                               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 );