1/* $NetBSD: operational.c,v 1.1.1.3 2010/12/12 15:22:59 adam Exp $ */ 2 3/* operational.c - bdb backend operational attributes function */ 4/* OpenLDAP: pkg/ldap/servers/slapd/back-bdb/operational.c,v 1.29.2.7 2010/06/10 17:25:02 quanah Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2000-2010 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19#include "portable.h" 20 21#include <stdio.h> 22 23#include <ac/string.h> 24#include <ac/socket.h> 25 26#include "slap.h" 27#include "back-bdb.h" 28 29/* 30 * sets *hasSubordinates to LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE 31 * if the entry has children or not. 32 */ 33int 34bdb_hasSubordinates( 35 Operation *op, 36 Entry *e, 37 int *hasSubordinates ) 38{ 39 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; 40 struct bdb_op_info *opinfo; 41 OpExtra *oex; 42 DB_TXN *rtxn; 43 int rc; 44 int release = 0; 45 46 assert( e != NULL ); 47 48 /* NOTE: this should never happen, but it actually happens 49 * when using back-relay; until we find a better way to 50 * preserve entry's private information while rewriting it, 51 * let's disable the hasSubordinate feature for back-relay. 52 */ 53 if ( BEI( e ) == NULL ) { 54 Entry *ee = NULL; 55 rc = be_entry_get_rw( op, &e->e_nname, NULL, NULL, 0, &ee ); 56 if ( rc != LDAP_SUCCESS || ee == NULL ) { 57 rc = LDAP_OTHER; 58 goto done; 59 } 60 e = ee; 61 release = 1; 62 if ( BEI( ee ) == NULL ) { 63 rc = LDAP_OTHER; 64 goto done; 65 } 66 } 67 68 /* Check for a txn in a parent op, otherwise use reader txn */ 69 LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) { 70 if ( oex->oe_key == bdb ) 71 break; 72 } 73 opinfo = (struct bdb_op_info *) oex; 74 if ( opinfo && opinfo->boi_txn ) { 75 rtxn = opinfo->boi_txn; 76 } else { 77 rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn); 78 if ( rc ) { 79 rc = LDAP_OTHER; 80 goto done; 81 } 82 } 83 84retry: 85 /* FIXME: we can no longer assume the entry's e_private 86 * field is correctly populated; so we need to reacquire 87 * it with reader lock */ 88 rc = bdb_cache_children( op, rtxn, e ); 89 90 switch( rc ) { 91 case DB_LOCK_DEADLOCK: 92 case DB_LOCK_NOTGRANTED: 93 goto retry; 94 95 case 0: 96 *hasSubordinates = LDAP_COMPARE_TRUE; 97 break; 98 99 case DB_NOTFOUND: 100 *hasSubordinates = LDAP_COMPARE_FALSE; 101 rc = LDAP_SUCCESS; 102 break; 103 104 default: 105 Debug(LDAP_DEBUG_ARGS, 106 "<=- " LDAP_XSTRING(bdb_hasSubordinates) 107 ": has_children failed: %s (%d)\n", 108 db_strerror(rc), rc, 0 ); 109 rc = LDAP_OTHER; 110 } 111 112done:; 113 if ( release && e != NULL ) be_entry_release_r( op, e ); 114 return rc; 115} 116 117/* 118 * sets the supported operational attributes (if required) 119 */ 120int 121bdb_operational( 122 Operation *op, 123 SlapReply *rs ) 124{ 125 Attribute **ap; 126 127 assert( rs->sr_entry != NULL ); 128 129 for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) 130 /* just count */ ; 131 132 if ( SLAP_OPATTRS( rs->sr_attr_flags ) || 133 ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) 134 { 135 int hasSubordinates, rc; 136 137 rc = bdb_hasSubordinates( op, rs->sr_entry, &hasSubordinates ); 138 if ( rc == LDAP_SUCCESS ) { 139 *ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE ); 140 assert( *ap != NULL ); 141 142 ap = &(*ap)->a_next; 143 } 144 } 145 146 return LDAP_SUCCESS; 147} 148 149