| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* resourcelimit.c - binder-based resource limits implementation */
- /*
- * Implementation notes:
- *
- * At present this code only provides support for integer-based
- * resource limits.
- *
- * When a successful bind occurs (i.e., when bind_credentials_set() is
- * called), reslimit_update_from_dn() or reslimit_update_from_entry()
- * must be called. These functions look in the binder entry and pull
- * out attribute values that correspond to resource limits. Typically
- * operational attributes are used, e.g., nsSizeLimit to hold a
- * binder-specific search size limit. The attributes should be single
- * valued; if not, this code ignores all but the first value it finds.
- * The virtual attribute interface is used to retrieve the binder entry
- * values, so they can be based on COS, etc.
- *
- * Any resource limits found in the binder entry are cached in the
- * connection structure. A connection object extension is used for this
- * purpose. This means that if the attributes that correspond to binder
- * entry are changed the resource limit won't be affected until the next
- * bind occurs as that entry. The data in the connection extension is
- * protected using a single writer/multiple reader locking scheme.
- *
- * A plugin or server subsystem that wants to use the resource limit
- * subsystem should call slapi_reslimit_register() once for each limit it
- * wants tracked. Note that slapi_reslimit_register() should be called
- * early, i.e., before any client connections are accepted.
- * slapi_reslimit_register() gives back an integer handle that is used
- * later to refer to the limit in question. Here's a sample call:
- */
- #if SLAPI_RESLIMIT_SAMPLE_CODE
- static int sizelimit_reslimit_handle = -1;
- if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT, "nsSizeLimit",
- &sizelimit_reslimit_handle ) != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
- /* limit could not be registered -- fatal error? */
- }
- ...
- #endif
- /*
- * A successful call to slapi_reslimit_register() results in a new
- * entry in the reslimit_map, which is private to this source file.
- * The map data structure is protected using a single writer/multiple
- * reader locking scheme.
- *
- * To retrieve a binder-based limit, simple call
- * slapi_reslimit_get_integer_limit(). If a value was present in the
- * binder entry, it will be given back to the caller and
- * SLAPI_RESLIMIT_STATUS_SUCCESS will be returned. If no value was
- * present or the connection is NULL, SLAPI_RESLIMIT_STATUS_NOVALUE is
- * returned. Other errors may be returned also. Here's a sample call:
- */
- #if SLAPI_RESLIMIT_SAMPLE_CODE
- int rc, sizelimit;
- rc = slapi_reslimit_get_integer_limit( conn, sizelimit_reslimit_handle,
- &sizelimit );
- switch( rc ) {
- case SLAPI_RESLIMIT_STATUS_SUCCESS: /* got a value */
- break;
- case SLAPI_RESLIMIT_STATUS_NOVALUE: /* no limit value available */
- sizelimit = 500; /* use a default value */
- break;
- default: /* some other error occurred */
- sizelimit = 500; /* use a default value */
- }
- #endif
- /*
- * The function reslimit_cleanup() is called from main() to dispose of
- * memory, locks, etc. so tools like Purify() don't report leaks at exit.
- */
- /* End of implementation notes */
- #include "slap.h"
- /*
- * Macros.
- */
- #define SLAPI_RESLIMIT_MODULE "binder-based resource limits"
- /* #define SLAPI_RESLIMIT_DEBUG */ /* define this to enable extra logging */
- /* also forces trace log messages to */
- /* always be logged */
- #ifdef SLAPI_RESLIMIT_DEBUG
- #define SLAPI_RESLIMIT_TRACELEVEL LDAP_DEBUG_ANY
- #else /* SLAPI_RESLIMIT_DEBUG */
- #define SLAPI_RESLIMIT_TRACELEVEL LDAP_DEBUG_TRACE
- #endif /* SLAPI_RESLIMIT_DEBUG */
- /*
- * Structures and types.
- */
- /* Per-connection resource limits data */
- typedef struct slapi_reslimit_conndata {
- PRRWLock *rlcd_rwlock; /* to serialize access to the rest */
- int rlcd_integer_count; /* size of rlcd_integer_limit array */
- PRBool *rlcd_integer_available; /* array that says whether each */
- /* value is available */
- int *rlcd_integer_value; /* array that holds limit values */
- } SLAPIResLimitConnData;
- /* Mapping between attribute and limit */
- typedef struct slapi_reslimit_map {
- int rlmap_type; /* always SLAPI_RESLIMIT_TYPE_INT for now */
- char *rlmap_at; /* attribute type name */
- } SLAPIResLimitMap;
- /*
- * Static variables (module globals).
- */
- static int reslimit_inited = 0;
- static int reslimit_connext_objtype = 0;
- static int reslimit_connext_handle = 0;
- static struct slapi_reslimit_map *reslimit_map = NULL;
- static int reslimit_map_count = 0;
- static struct slapi_componentid *reslimit_componentid=NULL;
- /*
- * reslimit_map_rwlock is used to serialize access to
- * reslimit_map and reslimit_map_count
- */
- static PRRWLock *reslimit_map_rwlock = NULL;
- /*
- * Static functions.
- */
- static int reslimit_init( void );
- static void *reslimit_connext_constructor( void *object, void *parent );
- static void reslimit_connext_destructor( void *extension, void *object,
- void *parent );
- static int reslimit_get_ext( Slapi_Connection *conn, const char *logname,
- SLAPIResLimitConnData **rlcdpp );
- static int reslimit_bv2int( const struct berval *bvp );
- static char ** reslimit_get_registered_attributes();
- /*
- * reslimit_init() must be called before any resource related work
- * is done. It is safe to call this more than once, but reslimit_inited
- * can be tested to avoid a call.
- *
- * Returns zero if all goes well and non-zero if not.
- */
- static int
- reslimit_init( void )
- {
- if ( reslimit_inited == 0 ) {
- if ( slapi_register_object_extension( SLAPI_RESLIMIT_MODULE,
- SLAPI_EXT_CONNECTION, reslimit_connext_constructor,
- reslimit_connext_destructor,
- &reslimit_connext_objtype, &reslimit_connext_handle )
- != 0 ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "reslimit_init: slapi_register_object_extension()"
- " failed\n" );
- return( -1 );
- }
- if (( reslimit_map_rwlock = PR_NewRWLock( PR_RWLOCK_RANK_NONE,
- "resourcelimit map rwlock" )) == NULL ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "reslimit_init: PR_NewRWLock() failed\n" );
- return( -1 );
- }
- reslimit_inited = 1;
- }
- reslimit_componentid=generate_componentid(NULL,COMPONENT_RESLIMIT);
- return( 0 );
- }
- /*
- * Dispose of any allocated memory, locks, other resources. Called when
- * server is shutting down.
- */
- void
- reslimit_cleanup( void )
- {
- int i;
- if ( reslimit_map != NULL ) {
- for ( i = 0; i < reslimit_map_count; ++i ) {
- if ( reslimit_map[ i ].rlmap_at != NULL ) {
- slapi_ch_free( (void **)&reslimit_map[ i ].rlmap_at );
- }
- }
- slapi_ch_free( (void **)&reslimit_map );
- }
- if ( reslimit_map_rwlock != NULL ) {
- PR_DestroyRWLock( reslimit_map_rwlock );
- }
- if ( reslimit_componentid != NULL ) {
- release_componentid( reslimit_componentid );
- }
- }
- /*
- * constructor for the connection object extension.
- */
- static void *
- reslimit_connext_constructor( void *object, void *parent )
- {
- SLAPIResLimitConnData *rlcdp;
- PRRWLock *rwlock;
- if (( rwlock = PR_NewRWLock( PR_RWLOCK_RANK_NONE,
- "resource limit connection data rwlock" )) == NULL ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "reslimit_connext_constructor: PR_NewRWLock() failed\n" );
- return( NULL );
- }
- rlcdp = (SLAPIResLimitConnData *)slapi_ch_calloc( 1,
- sizeof( SLAPIResLimitConnData ));
- rlcdp->rlcd_rwlock = rwlock;
- return( rlcdp );
- }
- /*
- * destructor for the connection object extension.
- */
- static void
- reslimit_connext_destructor( void *extension, void *object, void *parent )
- {
- SLAPIResLimitConnData *rlcdp = (SLAPIResLimitConnData *)extension;
- if ( rlcdp->rlcd_integer_available != NULL ) {
- slapi_ch_free( (void **)&rlcdp->rlcd_integer_available );
- }
- if ( rlcdp->rlcd_integer_value != NULL ) {
- slapi_ch_free( (void **)&rlcdp->rlcd_integer_value );
- }
- PR_DestroyRWLock( rlcdp->rlcd_rwlock );
- slapi_ch_free( (void **)&rlcdp );
- }
- /*
- * utility function to retrieve the connection object extension.
- *
- * if logname is non-NULL, errors are logged.
- */
- static int
- reslimit_get_ext( Slapi_Connection *conn, const char *logname,
- SLAPIResLimitConnData **rlcdpp )
- {
- if ( !reslimit_inited && reslimit_init() != 0 ) {
- if ( NULL != logname ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: reslimit_init() failed\n", logname );
- }
- return( SLAPI_RESLIMIT_STATUS_INIT_FAILURE );
- }
- if (( *rlcdpp = (SLAPIResLimitConnData *)slapi_get_object_extension(
- reslimit_connext_objtype, conn,
- reslimit_connext_handle )) == NULL ) {
- if ( NULL != logname ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: slapi_get_object_extension() returned NULL\n", logname );
- }
- return( SLAPI_RESLIMIT_STATUS_INTERNAL_ERROR );
- }
- return( SLAPI_RESLIMIT_STATUS_SUCCESS );
- }
- /*
- * utility function to convert a string-represented integer to an int.
- *
- * XXXmcs: wouldn't need this if slapi_value_get_int() returned a signed int!
- */
- static int
- reslimit_bv2int( const struct berval *bvp )
- {
- int rc = 0;
- char smallbuf[ 25 ], *buf;
- if ( bvp != NULL ) {
- /* make a copy to ensure it is zero-terminated */
- if ( bvp->bv_len < sizeof( smallbuf )) {
- buf = smallbuf;
- } else {
- buf = slapi_ch_malloc( bvp->bv_len + 1 );
- }
- memcpy( buf, bvp->bv_val, bvp->bv_len);
- buf[ bvp->bv_len ] = '\0';
- rc = atoi( buf );
- if ( buf != smallbuf ) {
- slapi_ch_free( (void **)&smallbuf );
- }
- }
- return( rc );
- }
- /**** Semi-public functions start here ***********************************/
- /*
- * These functions are exposed to other parts of the server only, i.e.,
- * they are NOT part of the official SLAPI API.
- */
- /*
- * Set the resource limits associated with connection `conn' based on the
- * entry named by `dn'. If `dn' is NULL, limits are returned to their
- * default state.
- *
- * A SLAPI_RESLIMIT_STATUS_... code is returned.
- */
- int
- reslimit_update_from_dn( Slapi_Connection *conn, Slapi_DN *dn )
- {
- Slapi_Entry *e;
- int rc;
- e = NULL;
- if ( dn != NULL ) {
- char ** attrs = reslimit_get_registered_attributes();
- (void) slapi_search_internal_get_entry( dn, attrs, &e , reslimit_componentid);
- charray_free(attrs);
- }
- rc = reslimit_update_from_entry( conn, e );
- if ( NULL != e ) {
- slapi_entry_free( e );
- }
- return( rc );
- }
- /*
- * Set the resource limits associated with connection `conn' based on the
- * entry `e'. If `e' is NULL, limits are returned to their default state.
- * If `conn' is NULL, nothing is done.
- *
- * A SLAPI_RESLIMIT_STATUS_... code is returned.
- */
- int
- reslimit_update_from_entry( Slapi_Connection *conn, Slapi_Entry *e )
- {
- char *fnname = "reslimit_update_from_entry()";
- char *actual_type_name, *get_ext_logname;
- int i, rc, type_name_disposition, free_flags;
- SLAPIResLimitConnData *rlcdp;
- Slapi_ValueSet *vs;
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL, "=> %s conn=0x%x, entry=0x%x\n",
- fnname, conn, e );
- rc = SLAPI_RESLIMIT_STATUS_SUCCESS; /* optimistic */
- /* if conn is NULL, there is nothing to be done */
- if ( conn == NULL ) {
- goto log_and_return;
- }
-
- if ( NULL == e ) {
- get_ext_logname = NULL; /* do not log errors if resetting limits */
- } else {
- get_ext_logname = fnname;
- }
- if (( rc = reslimit_get_ext( conn, get_ext_logname, &rlcdp )) !=
- SLAPI_RESLIMIT_STATUS_SUCCESS ) {
- goto log_and_return;
- }
- /* LOCK FOR READ -- map lock */
- PR_RWLock_Rlock( reslimit_map_rwlock );
- /* LOCK FOR WRITE -- conn. data lock */
- PR_RWLock_Wlock( rlcdp->rlcd_rwlock );
- if ( rlcdp->rlcd_integer_value == NULL ) {
- rlcdp->rlcd_integer_count = reslimit_map_count;
- if ( rlcdp->rlcd_integer_count > 0 ) {
- rlcdp->rlcd_integer_available = (PRBool *)slapi_ch_calloc(
- rlcdp->rlcd_integer_count, sizeof( PRBool ));
- rlcdp->rlcd_integer_value = (int *)slapi_ch_calloc(
- rlcdp->rlcd_integer_count, sizeof( int ));
- }
- }
- for ( i = 0; i < rlcdp->rlcd_integer_count; ++i ) {
- if ( reslimit_map[ i ].rlmap_type != SLAPI_RESLIMIT_TYPE_INT ) {
- continue;
- }
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL,
- "%s: setting limit for handle %d (based on %s)\n",
- fnname, i, reslimit_map[ i ].rlmap_at );
- rlcdp->rlcd_integer_available[ i ] = PR_FALSE;
- if ( NULL != e && 0 == slapi_vattr_values_get( e,
- reslimit_map[ i ].rlmap_at, &vs, &type_name_disposition,
- &actual_type_name, 0, &free_flags )) {
- Slapi_Value *v;
- int index;
- const struct berval *bvp;
- if (( index = slapi_valueset_first_value( vs, &v )) != -1 &&
- ( bvp = slapi_value_get_berval( v )) != NULL ) {
- rlcdp->rlcd_integer_value[ i ] = reslimit_bv2int( bvp );
- rlcdp->rlcd_integer_available[ i ] = PR_TRUE;
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL,
- "%s: set limit based on %s to %d\n",
- fnname, reslimit_map[ i ].rlmap_at,
- rlcdp->rlcd_integer_value[ i ] );
- if ( slapi_valueset_next_value( vs, index, &v ) != -1 ) {
- char ebuf[ BUFSIZ ];
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: ignoring multiple values for %s in entry %s\n",
- fnname, reslimit_map[ i ].rlmap_at,
- escape_string( slapi_entry_get_dn_const( e ),
- ebuf ));
- }
- }
- slapi_vattr_values_free( &vs, &actual_type_name, free_flags);
- }
- }
- PR_RWLock_Unlock( rlcdp->rlcd_rwlock );
- /* UNLOCKED -- conn. data lock */
- PR_RWLock_Unlock( reslimit_map_rwlock );
- /* UNLOCKED -- map lock */
- log_and_return:
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL, "<= %s returning status %d\n",
- fnname, rc, 0 );
- return( rc );
- }
- /* return the list of registered attributes */
- static char ** reslimit_get_registered_attributes()
- {
- int i;
- char **attrs=NULL;
- /* LOCK FOR READ -- map lock */
- PR_RWLock_Rlock( reslimit_map_rwlock );
- for ( i = 0; i < reslimit_map_count; ++i ) {
- if ( reslimit_map[ i ].rlmap_at != NULL ) {
- charray_add(&attrs, slapi_ch_strdup(reslimit_map[ i ].rlmap_at));
- }
- }
-
- PR_RWLock_Unlock( reslimit_map_rwlock );
- return attrs;
- }
- /**** Public functions can be found below this point *********************/
- /*
- * These functions are exposed to plugins, i.e., they are part of the
- * official SLAPI API.
- */
- /*
- * Register a new resource to be tracked. `type' must be
- * SLAPI_RESLIMIT_TYPE_INT and `attrname' is an LDAP attribute type that
- * is consulted in the bound entry to determine the limit's value.
- *
- * A SLAPI_RESLIMIT_STATUS_... code is returned. If it is ...SUCCESS, then
- * `*handlep' is set to an opaque integer value that should be used in
- * subsequent calls to slapi_reslimit_get_integer_limit().
- */
- int
- slapi_reslimit_register( int type, const char *attrname, int *handlep )
- {
- char *fnname = "slapi_reslimit_register()";
- int i, rc;
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL, "=> %s attrname=%s\n",
- fnname, attrname, 0 );
- rc = SLAPI_RESLIMIT_STATUS_SUCCESS; /* optimistic */
- /* initialize if necessary */
- if ( !reslimit_inited && reslimit_init() != 0 ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: reslimit_init() failed\n", fnname );
- rc = SLAPI_RESLIMIT_STATUS_INIT_FAILURE;
- goto log_and_return;
- }
- /* sanity check parameters */
- if ( type != SLAPI_RESLIMIT_TYPE_INT || attrname == NULL
- || handlep == NULL ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: parameter error\n", fnname );
- rc = SLAPI_RESLIMIT_STATUS_PARAM_ERROR;
- goto log_and_return;
- }
- /* LOCK FOR WRITE -- map lock */
- PR_RWLock_Wlock( reslimit_map_rwlock );
- /*
- * check that attrname is not already registered
- */
- for ( i = 0; i < reslimit_map_count; ++i ) {
- if ( 0 == slapi_attr_type_cmp( reslimit_map[ i ].rlmap_at,
- attrname, SLAPI_TYPE_CMP_EXACT )) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: parameter error (%s already registered)\n",
- attrname, fnname );
- rc = SLAPI_RESLIMIT_STATUS_PARAM_ERROR;
- goto unlock_and_return;
- }
- }
- /*
- * expand the map array and add the new element
- */
- reslimit_map = (SLAPIResLimitMap *)slapi_ch_realloc(
- (char *)reslimit_map,
- (1 + reslimit_map_count) * sizeof( SLAPIResLimitMap ));
- reslimit_map[ reslimit_map_count ].rlmap_type = type;
- reslimit_map[ reslimit_map_count ].rlmap_at
- = slapi_ch_strdup( attrname );
- *handlep = reslimit_map_count;
- ++reslimit_map_count;
- unlock_and_return:
- PR_RWLock_Unlock( reslimit_map_rwlock );
- /* UNLOCKED -- map lock */
- log_and_return:
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL,
- "<= %s returning status=%d, handle=%d\n", fnname, rc,
- (handlep == NULL) ? -1 : *handlep );
- return( rc );
- }
- /*
- * Retrieve the integer limit associated with connection `conn' for
- * the resource identified by `handle'.
- *
- * A SLAPI_RESLIMIT_STATUS_... code is returned:
- *
- * SLAPI_RESLIMIT_STATUS_SUCCESS -- `*limitp' is set to the limit value.
- * SLAPI_RESLIMIT_STATUS_NOVALUE -- no limit value is available (use default).
- * Another SLAPI_RESLIMIT_STATUS_... code -- some more fatal error occurred.
- *
- * If `conn' is NULL, SLAPI_RESLIMIT_STATUS_NOVALUE is returned.
- */
- int
- slapi_reslimit_get_integer_limit( Slapi_Connection *conn, int handle,
- int *limitp )
- {
- char *fnname = "slapi_reslimit_get_integer_limit()";
- int rc;
- SLAPIResLimitConnData *rlcdp;
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL, "=> %s conn=0x%x, handle=%d\n",
- fnname, conn, handle );
- rc = SLAPI_RESLIMIT_STATUS_SUCCESS; /* optimistic */
- /* sanity check parameters */
- if ( limitp == NULL ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: parameter error\n", fnname );
- rc = SLAPI_RESLIMIT_STATUS_PARAM_ERROR;
- goto log_and_return;
- }
- if ( conn == NULL ) {
- rc = SLAPI_RESLIMIT_STATUS_NOVALUE;
- goto log_and_return;
- }
- if (( rc = reslimit_get_ext( conn, fnname, &rlcdp )) !=
- SLAPI_RESLIMIT_STATUS_SUCCESS ) {
- goto log_and_return;
- }
- if(rlcdp->rlcd_integer_count==0) { /* peek at it to avoid lock */
- rc = SLAPI_RESLIMIT_STATUS_NOVALUE;
- } else {
- PR_RWLock_Rlock( rlcdp->rlcd_rwlock );
- if(rlcdp->rlcd_integer_count==0) {
- rc = SLAPI_RESLIMIT_STATUS_NOVALUE;
- } else if ( handle < 0 || handle >= rlcdp->rlcd_integer_count ) {
- slapi_log_error( SLAPI_LOG_FATAL, SLAPI_RESLIMIT_MODULE,
- "%s: unknown handle %d\n", fnname, handle );
- rc = SLAPI_RESLIMIT_STATUS_UNKNOWN_HANDLE;
- } else if ( rlcdp->rlcd_integer_available[ handle ] ) {
- *limitp = rlcdp->rlcd_integer_value[ handle ];
- } else {
- rc = SLAPI_RESLIMIT_STATUS_NOVALUE;
- }
- PR_RWLock_Unlock( rlcdp->rlcd_rwlock );
- }
- log_and_return:
- if ( LDAPDebugLevelIsSet( LDAP_DEBUG_TRACE )) {
- if ( rc == SLAPI_RESLIMIT_STATUS_SUCCESS ) {
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL,
- "<= %s returning SUCCESS, value=%d\n", fnname, *limitp, 0 );
- } else if ( rc == SLAPI_RESLIMIT_STATUS_NOVALUE ) {
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL, "<= %s returning NO VALUE\n",
- fnname, 0, 0 );
- } else {
- LDAPDebug( SLAPI_RESLIMIT_TRACELEVEL, "<= %s returning ERROR %d\n",
- fnname, rc, 0 );
- }
- }
- return( rc );
- }
- /**** Public functions END ***********************************************/
|