]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-mdb/search.c
Happy new year (belated)
[openldap] / servers / slapd / back-mdb / search.c
index 09bdf60c96111c61ecd065599841595e625ac4ea..4cac2b30df00597abc44d48429c2593120cd9172 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2013 The OpenLDAP Foundation.
+ * Copyright 2000-2014 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -218,6 +218,7 @@ static int search_aliases(
                                 */
                                mdb_entry_return( op, matched );
                                rs->sr_text = NULL;
+                               rs->sr_err = 0;
                        }
                }
                /* If this is a OneLevel search, we're done; oldsubs only had one
@@ -316,9 +317,10 @@ int
 mdb_search( Operation *op, SlapReply *rs )
 {
        struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
-       ID              id, cursor, nsubs, ncand;
+       ID              id, cursor, nsubs, ncand, cscope;
        ID              lastid = NOID;
        ID              candidates[MDB_IDL_UM_SIZE];
+       ID              iscopes[MDB_IDL_DB_SIZE];
        ID2             *scopes;
        Entry           *e = NULL, *base = NULL;
        Entry           *matched = NULL;
@@ -366,6 +368,7 @@ mdb_search( Operation *op, SlapReply *rs )
        isc.mt = ltid;
        isc.mc = mcd;
        isc.scopes = scopes;
+       isc.oscope = op->ors_scope;
 
        if ( op->ors_deref & LDAP_DEREF_FINDING ) {
                MDB_IDL_ZERO(candidates);
@@ -535,6 +538,7 @@ dn2entry_retry:
        /* select candidates */
        if ( op->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
                rs->sr_err = base_candidate( op->o_bd, base, candidates );
+               scopes[0].mid = 0;
                ncand = 1;
        } else {
                if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) {
@@ -636,6 +640,21 @@ dn2entry_retry:
        if ( nsubs < ncand ) {
                int rc;
                /* Do scope-based search */
+
+               /* if any alias scopes were set, save them */
+               if (scopes[0].mid > 1) {
+                       cursor = 1;
+                       for (cscope = 1; cscope <= scopes[0].mid; cscope++) {
+                               /* Ignore the original base */
+                               if (scopes[cscope].mid == base->e_id)
+                                       continue;
+                               iscopes[cursor++] = scopes[cscope].mid;
+                       }
+                       iscopes[0] = scopes[0].mid - 1;
+               } else {
+                       iscopes[0] = 0;
+               }
+
                isc.id = base->e_id;
                isc.numrdns = 0;
                rc = mdb_dn2id_walk( op, &isc );
@@ -643,6 +662,7 @@ dn2entry_retry:
                        id = NOID;
                else
                        id = isc.id;
+               cscope = 0;
        } else {
                id = mdb_idl_first( candidates, &cursor );
        }
@@ -839,7 +859,7 @@ notfound:
                        int i;
 
                        /* child of base, just append RDNs to base->e_name */
-                       if ( nsubs < ncand || isc.nscope == 1 ) {
+                       if ( nsubs < ncand || isc.scopes[isc.nscope].mid == base->e_id ) {
                                pdn = base->e_name;
                                pndn = base->e_nname;
                        } else {
@@ -957,6 +977,9 @@ notfound:
                                        break;
                                default:                /* entry not sent */
                                        break;
+                               case LDAP_BUSY:
+                                       send_ldap_result( op, rs );
+                                       goto done;
                                case LDAP_UNAVAILABLE:
                                case LDAP_SIZELIMIT_EXCEEDED:
                                        if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
@@ -989,9 +1012,30 @@ loop_continue:
 
                if ( nsubs < ncand ) {
                        int rc = mdb_dn2id_walk( op, &isc );
-                       if (rc)
+                       if (rc) {
                                id = NOID;
-                       else
+                               /* We got to the end of a subtree. If there are any
+                                * alias scopes left, search them too.
+                                */
+                               while (iscopes[0] && cscope < iscopes[0]) {
+                                       cscope++;
+                                       isc.id = iscopes[cscope];
+                                       if ( base )
+                                               mdb_entry_return( op, base );
+                                       rs->sr_err = mdb_id2entry(op, mci, isc.id, &base);
+                                       if ( !rs->sr_err ) {
+                                               mdb_id2name( op, ltid, &isc.mc, isc.id, &base->e_name, &base->e_nname );
+                                               isc.numrdns = 0;
+                                               if (isc.oscope == LDAP_SCOPE_ONELEVEL)
+                                                       isc.oscope = LDAP_SCOPE_BASE;
+                                               rc = mdb_dn2id_walk( op, &isc );
+                                               if ( !rc ) {
+                                                       id = isc.id;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       } else
                                id = isc.id;
                } else {
                        id = mdb_idl_next( candidates, &cursor );
@@ -1017,6 +1061,8 @@ done:
        if ( moi == &opinfo ) {
                mdb_txn_reset( moi->moi_txn );
                LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
+       } else {
+               moi->moi_ref--;
        }
        if( rs->sr_v2ref ) {
                ber_bvarray_free( rs->sr_v2ref );