]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/operational.c
Merge remote branch 'origin/mdb.master'
[openldap] / servers / slapd / back-bdb / operational.c
index 0272e00923a700508b7f3fc60f50bdb6760136cc..f30fb001c87029919c38f5f5600a84fd665e8259 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2008 The OpenLDAP Foundation.
+ * Copyright 2000-2012 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,12 @@ bdb_hasSubordinates(
        Entry           *e,
        int             *hasSubordinates )
 {
+       struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
+       struct bdb_op_info      *opinfo;
+       OpExtra *oex;
+       DB_TXN          *rtxn;
        int             rc;
+       int             release = 0;
        
        assert( e != NULL );
 
@@ -44,15 +49,42 @@ bdb_hasSubordinates(
         * let's disable the hasSubordinate feature for back-relay.
         */
        if ( BEI( e ) == NULL ) {
-               return LDAP_OTHER;
+               Entry *ee = NULL;
+               rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee );
+               if ( rc != LDAP_SUCCESS || ee == NULL ) {
+                       rc = LDAP_OTHER;
+                       goto done;
+               }
+               e = ee;
+               release = 1;
+               if ( BEI( ee ) == NULL ) {
+                       rc = LDAP_OTHER;
+                       goto done;
+               }
+       }
+
+       /* Check for a txn in a parent op, otherwise use reader txn */
+       LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
+               if ( oex->oe_key == bdb )
+                       break;
+       }
+       opinfo = (struct bdb_op_info *) oex;
+       if ( opinfo && opinfo->boi_txn ) {
+               rtxn = opinfo->boi_txn;
+       } else {
+               rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
+               if ( rc ) {
+                       rc = LDAP_OTHER;
+                       goto done;
+               }
        }
 
 retry:
        /* FIXME: we can no longer assume the entry's e_private
         * field is correctly populated; so we need to reacquire
         * it with reader lock */
-       rc = bdb_cache_children( op, NULL, e );
-       
+       rc = bdb_cache_children( op, rtxn, e );
+
        switch( rc ) {
        case DB_LOCK_DEADLOCK:
        case DB_LOCK_NOTGRANTED:
@@ -75,6 +107,8 @@ retry:
                rc = LDAP_OTHER;
        }
 
+done:;
+       if ( release && e != NULL ) be_entry_release_r( op, e );
        return rc;
 }
 
@@ -90,11 +124,16 @@ bdb_operational(
 
        assert( rs->sr_entry != NULL );
 
-       for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
-               /* just count */ ;
+       for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
+               if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
+                       break;
+               }
+       }
 
-       if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
-                       ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
+       if ( *ap == NULL &&
+               attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
+               ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
+                       ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
        {
                int     hasSubordinates, rc;