Back to index

openldap  2.4.31
operational.c
Go to the documentation of this file.
00001 /* operational.c - bdb backend operational attributes function */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2000-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 
00021 #include <ac/string.h>
00022 #include <ac/socket.h>
00023 
00024 #include "slap.h"
00025 #include "back-bdb.h"
00026 
00027 /*
00028  * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE
00029  * if the entry has children or not.
00030  */
00031 int
00032 bdb_hasSubordinates(
00033        Operation     *op,
00034        Entry         *e,
00035        int           *hasSubordinates )
00036 {
00037        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
00038        struct bdb_op_info   *opinfo;
00039        OpExtra *oex;
00040        DB_TXN        *rtxn;
00041        int           rc;
00042        int           release = 0;
00043        
00044        assert( e != NULL );
00045 
00046        /* NOTE: this should never happen, but it actually happens
00047         * when using back-relay; until we find a better way to
00048         * preserve entry's private information while rewriting it,
00049         * let's disable the hasSubordinate feature for back-relay.
00050         */
00051        if ( BEI( e ) == NULL ) {
00052               Entry *ee = NULL;
00053               rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee );
00054               if ( rc != LDAP_SUCCESS || ee == NULL ) {
00055                      rc = LDAP_OTHER;
00056                      goto done;
00057               }
00058               e = ee;
00059               release = 1;
00060               if ( BEI( ee ) == NULL ) {
00061                      rc = LDAP_OTHER;
00062                      goto done;
00063               }
00064        }
00065 
00066        /* Check for a txn in a parent op, otherwise use reader txn */
00067        LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
00068               if ( oex->oe_key == bdb )
00069                      break;
00070        }
00071        opinfo = (struct bdb_op_info *) oex;
00072        if ( opinfo && opinfo->boi_txn ) {
00073               rtxn = opinfo->boi_txn;
00074        } else {
00075               rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
00076               if ( rc ) {
00077                      rc = LDAP_OTHER;
00078                      goto done;
00079               }
00080        }
00081 
00082 retry:
00083        /* FIXME: we can no longer assume the entry's e_private
00084         * field is correctly populated; so we need to reacquire
00085         * it with reader lock */
00086        rc = bdb_cache_children( op, rtxn, e );
00087 
00088        switch( rc ) {
00089        case DB_LOCK_DEADLOCK:
00090        case DB_LOCK_NOTGRANTED:
00091               goto retry;
00092 
00093        case 0:
00094               *hasSubordinates = LDAP_COMPARE_TRUE;
00095               break;
00096 
00097        case DB_NOTFOUND:
00098               *hasSubordinates = LDAP_COMPARE_FALSE;
00099               rc = LDAP_SUCCESS;
00100               break;
00101 
00102        default:
00103               Debug(LDAP_DEBUG_ARGS, 
00104                      "<=- " LDAP_XSTRING(bdb_hasSubordinates)
00105                      ": has_children failed: %s (%d)\n", 
00106                      db_strerror(rc), rc, 0 );
00107               rc = LDAP_OTHER;
00108        }
00109 
00110 done:;
00111        if ( release && e != NULL ) be_entry_release_r( op, e );
00112        return rc;
00113 }
00114 
00115 /*
00116  * sets the supported operational attributes (if required)
00117  */
00118 int
00119 bdb_operational(
00120        Operation     *op,
00121        SlapReply     *rs )
00122 {
00123        Attribute     **ap;
00124 
00125        assert( rs->sr_entry != NULL );
00126 
00127        for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
00128               if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
00129                      break;
00130               }
00131        }
00132 
00133        if ( *ap == NULL &&
00134               attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
00135               ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
00136                      ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
00137        {
00138               int    hasSubordinates, rc;
00139 
00140               rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates );
00141               if ( rc == LDAP_SUCCESS ) {
00142                      *ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
00143                      assert( *ap != NULL );
00144 
00145                      ap = &(*ap)->a_next;
00146               }
00147        }
00148 
00149        return LDAP_SUCCESS;
00150 }
00151