X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Foperational.c;h=4614825cda5fb7676142b33a263f704a6e5aa894;hb=24bebf36943afff95e77ca92ffe4964470d452bc;hp=5278c23ba3baa83ca6ed59a29f9a81223b903eab;hpb=976fb2265f8b68b89c2e520d528843ce585d468c;p=openldap diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c index 5278c23ba3..4614825cda 100644 --- a/servers/slapd/back-bdb/operational.c +++ b/servers/slapd/back-bdb/operational.c @@ -1,7 +1,17 @@ /* operational.c - bdb backend operational attributes function */ -/* - * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2000-2013 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ #include "portable.h" @@ -13,120 +23,129 @@ #include "slap.h" #include "back-bdb.h" -#include "proto-bdb.h" /* - * sets the supported operational attributes (if required) + * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE + * if the entry has children or not. */ - int -bdb_operational( - BackendDB *be, - Connection *conn, +bdb_hasSubordinates( Operation *op, Entry *e, - AttributeName *attrs, - int opattrs, - Attribute **a ) + int *hasSubordinates ) { - struct bdb_info *bdb = (struct bdb_info *) be->be_private; - Attribute **aa = a; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; + struct bdb_op_info *opinfo; + OpExtra *oex; + DB_TXN *rtxn; int rc; - DB_TXN *ltid = NULL; - struct bdb_op_info opinfo; + int release = 0; - assert( e ); - - if ( !opattrs && !ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) { - return 0; - } - - - if( 0 ) { -retry: /* transaction retry */ -#if 0 - if( e != NULL ) { - bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e); + assert( e != NULL ); + + /* NOTE: this should never happen, but it actually happens + * when using back-relay; until we find a better way to + * preserve entry's private information while rewriting it, + * let's disable the hasSubordinate feature for back-relay. + */ + if ( BEI( e ) == NULL ) { + 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; } -#endif -#ifdef NEW_LOGGING - LDAP_LOG (( "operational", LDAP_LEVEL_DETAIL1, - "=> bdb_operational: retrying...\n" )); -#else - Debug( LDAP_DEBUG_TRACE, "==> bdb_operational: retrying...\n", - 0, 0, 0 ); -#endif - rc = TXN_ABORT( ltid ); - ltid = NULL; - op->o_private = NULL; - if( rc != 0 ) { + e = ee; + release = 1; + if ( BEI( ee ) == NULL ) { rc = LDAP_OTHER; - goto return_results; + goto done; } - ldap_pvt_thread_yield(); } - /* begin transaction */ - rc = TXN_BEGIN( bdb->bi_dbenv, NULL, <id, bdb->bi_db_opflags ); - if ( rc != 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG (( "operational", LDAP_LEVEL_ERR, - "=> bdb_operational: txn_begin failed: %s (%d)\n", - db_strerror(rc), rc )); -#else - Debug( LDAP_DEBUG_TRACE, - "bdb_operational: txn_begin failed: %s (%d)\n", - db_strerror( rc ), rc, 0 ); -#endif - rc = LDAP_OTHER; - return rc; + /* 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; + } } - opinfo.boi_bdb = be; - opinfo.boi_txn = ltid; - opinfo.boi_err = 0; - op->o_private = &opinfo; +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, rtxn, e ); - rc = bdb_dn2id_children( be, ltid, &e->e_nname ); - switch( rc ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; case 0: + *hasSubordinates = LDAP_COMPARE_TRUE; + break; + case DB_NOTFOUND: - *aa = slap_operational_hasSubordinate( rc == 0 ); - if ( *aa != NULL ) { - aa = &(*aa)->a_next; - } + *hasSubordinates = LDAP_COMPARE_FALSE; + rc = LDAP_SUCCESS; break; default: -#ifdef NEW_LOGGING - LDAP_LOG (( "operational", LDAP_LEVEL_ERR, - "=> bdb_operational: has_children failed: %s (%d)\n", - db_strerror(rc), rc )); -#else Debug(LDAP_DEBUG_ARGS, - "<=- bdb_operational: 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; } -return_results: - if ( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) { - ldap_pvt_thread_yield(); - TXN_CHECKPOINT( bdb->bi_dbenv, - bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); +done:; + if ( release && e != NULL ) be_entry_release_r( op, e ); + return rc; +} + +/* + * sets the supported operational attributes (if required) + */ +int +bdb_operational( + Operation *op, + SlapReply *rs ) +{ + Attribute **ap; + + assert( rs->sr_entry != NULL ); + + for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) { + if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) { + break; + } } - if ( ltid != NULL ) { - TXN_ABORT( ltid ); - op->o_private = NULL; + 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; + + rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates ); + if ( rc == LDAP_SUCCESS ) { + *ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE ); + assert( *ap != NULL ); + + ap = &(*ap)->a_next; + } } - return rc; + return LDAP_SUCCESS; }