X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fback-bdb%2Foperational.c;h=5a479858b279a4a82958f3eb6812236c46967b8a;hb=8f02c3f57578f6e35e89fcf73574c34108b41195;hp=3ff7aa2bc97bfb2cee412057afb6ab0c9f1ca2fe;hpb=9f6f5491fe55d31cc5eceab59be6bcdc47ea4282;p=openldap diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c index 3ff7aa2bc9..5a479858b2 100644 --- a/servers/slapd/back-bdb/operational.c +++ b/servers/slapd/back-bdb/operational.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2004 The OpenLDAP Foundation. + * Copyright 2000-2011 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +23,6 @@ #include "slap.h" #include "back-bdb.h" -#include "external.h" /* * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE @@ -35,9 +34,14 @@ 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 ); + assert( e != NULL ); /* NOTE: this should never happen, but it actually happens * when using back-relay; until we find a better way to @@ -45,19 +49,45 @@ 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: - ldap_pvt_thread_yield(); goto retry; case 0: @@ -70,18 +100,15 @@ retry: break; default: -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, - "=> bdb_hasSubordinates: has_children failed: %s (%d)\n", - db_strerror(rc), rc, 0 ); -#else Debug(LDAP_DEBUG_ARGS, - "<=- bdb_hasSubordinates: has_children failed: %s (%d)\n", + "<=- " LDAP_XSTRING(bdb_hasSubordinates) + ": has_children failed: %s (%d)\n", db_strerror(rc), rc, 0 ); -#endif rc = LDAP_OTHER; } +done:; + if ( release && e != NULL ) be_entry_release_r( op, e ); return rc; } @@ -95,25 +122,30 @@ bdb_operational( { Attribute **ap; - assert( rs->sr_entry ); + 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; + int hasSubordinates, rc; - rs->sr_err = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates ); - if ( rs->sr_err == LDAP_SUCCESS ) { + rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates ); + if ( rc == LDAP_SUCCESS ) { *ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE ); - assert( *ap ); + assert( *ap != NULL ); ap = &(*ap)->a_next; } } - return rs->sr_err; + return LDAP_SUCCESS; }