/*
* Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (c) 1993 The Regents of the University of Michigan.
* All rights reserved.
*
* cache.c - local caching support for LDAP
*/
#ifndef NO_CACHE
#ifndef lint
static char copyright[] = "@(#) Copyright (c) 1993 The Regents of the University of Michigan.\nAll rights reserved.\n";
#endif
#include <stdio.h>
#include <string.h>
#ifdef MACOS
#include <stdlib.h>
#include <time.h>
#include "macos.h"
#else /* MACOS */
#include <malloc.h>
#include "msdos.h"
#ifdef NCSA
#include "externs.h"
#endif /* NCSA */
#ifdef WINSOCK
#include <time.h>
#endif /* WINSOCK */
#else /* DOS */
#endif /* DOS */
#endif /* MACOS */
#include "lber.h"
#include "ldap.h"
#include "ldap-private.h"
#include "ldap-int.h"
#ifdef NEEDPROTOS
#else /* NEEDPROTOS */
static int cache_hash();
static LDAPMessage *msg_dup();
static int request_cmp();
static int chain_contains_dn();
static void check_cache_memused();
static void uncache_entry_or_req();
#endif /* NEEDPROTOS */
int
{
#if defined( SUN ) && defined( _REENTRANT )
#endif
== NULLLDCACHE ) {
#if defined( SUN ) && defined( _REENTRANT )
#endif
return( -1 );
}
}
#if defined( SUN ) && defined( _REENTRANT )
#endif
return( 0 );
}
void
{
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
void
{
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
void
{
#if defined( SUN ) && defined( _REENTRANT )
#endif
ldap_flush_cache( ld );
}
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
void
{
int i;
#if defined( SUN ) && defined( _REENTRANT )
#endif
/* delete all requests in the queue */
ldap_msgfree( m );
}
/* delete all messages in the cache */
for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
ldap_msgfree( m );
}
}
}
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
void
{
#if defined( SUN ) && defined( _REENTRANT )
#endif
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
void
{
#if defined( SUN ) && defined( _REENTRANT )
#endif
#if defined( SUN ) && defined( _REENTRANT )
#endif
}
static void
char *dn, /* if non-NULL, uncache entry */
int msgid ) /* request to uncache (if dn == NULL) */
{
int i;
return;
}
/* first check the request queue */
} else {
}
ldap_msgfree( m );
} else {
prev = m;
}
}
/* now check the rest of the cache */
for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
m = next ) {
} else {
}
ldap_msgfree( m );
} else {
prev = m;
}
}
}
}
void
{
return;
}
!= NULL ) {
return;
}
== NULL ) {
return;
}
} else {
}
}
void
{
return;
}
/*
* only cache search and compare operations
*/
return;
}
/*
* if corresponding request is in the lc_requests list, add this
* result to it. if this result completes the results for the
*/
break;
}
prev = m;
}
if ( m != NULLMSG ) { /* found request; add to end of chain */
req = m;
;
0, 0, 0 );
}
/*
* this result completes the chain of results
* add to cache proper if appropriate
*/
keep = 0; /* pessimistic */
if ( err == LDAP_SUCCESS ||
( err == LDAP_COMPARE_FALSE ||
err == LDAP_COMPARE_TRUE ||
err == LDAP_NO_SUCH_ATTRIBUTE ))) {
keep = 1;
}
if ( err == LDAP_SIZELIMIT_EXCEEDED ) {
keep = 1;
}
LDAP_CACHE_OPT_CACHEALLERRS ) != 0 ) {
keep = 1;
}
} else {
}
if ( !keep ) {
err, 0, 0 );
ldap_msgfree( req );
} else {
err, 0, 0 );
}
}
} else {
0, 0, 0 );
}
}
/*
* look in the cache for this request
* return 0 if found, -1 if not
* if found, the corresponding result messages are added to the incoming
* queue with the correct (new) msgid so that subsequent ldap_result calls
* will find them.
*/
int
{
unsigned long validtime;
return( -1 );
}
m->lm_msgid, m->lm_msgtype, 0 );
/* delete expired message */
} else {
}
m->lm_msgid, 0, 0 );
ldap_msgfree( m );
} else {
if ( m->lm_msgtype == msgtype &&
break;
}
prev = m;
}
}
if ( m == NULLMSG ) {
return( -1 );
}
/*
* add duplicates of responses to incoming queue
*/
first = 1;
#if defined( SUN ) && defined( _REENTRANT )
#endif
#if defined( SUN ) && defined( _REENTRANT )
#endif
return( -1 );
}
if ( first ) {
first = 0;
} else {
}
new->lm_msgtype, 0, 0 );
}
#if defined( SUN ) && defined( _REENTRANT )
#endif
return( 0 );
}
static int
{
unsigned int len;
/*
* just take the length of the packet and mod with # of buckets
*/
len = 0; /* punt: just return zero */
} else {
}
return ( len % LDAP_CACHE_BUCKETS );
}
static LDAPMessage *
{
return( NULLMSG );
}
return( NULLMSG );
}
}
return( new );
}
static int
{
unsigned int len;
/*
* skip the enclosing tags (sequence markers) and the msg ids
*/
== LBER_ERROR ) {
return( -1 );
}
== LBER_ERROR ) {
return( -1 );
}
/*
* check remaining length and bytes if necessary
*/
return( -1 ); /* different lengths */
}
}
static int
{
LDAPMessage *m;
int msgid;
char *s;
int rc;
/*
* first check the base or dn of the request
*/
free( s );
if ( rc != 0 ) {
return( rc );
}
}
return( 0 );
}
/*
* now check the dn of each search result
*/
rc = 0;
if ( m->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
continue;
}
free( s );
}
}
return( rc );
}
static ssize_t
{
LDAPMessage *m;
size = 0;
}
return( size );
}
static void
{
/*
* this routine is called to check if the cache is too big (lc_maxmem >
* minimum cache size and lc_memused > lc_maxmem). If too big, it reduces
* the cache size to < SIZE_FACTOR * lc_maxmem. The algorithm is as follows:
* remove_threshold = lc_timeout seconds;
* do {
* remove everything older than remove_threshold seconds;
* remove_threshold = remove_threshold * THRESHOLD_FACTOR;
* } while ( cache size is > SIZE_FACTOR * lc_maxmem )
*/
int i;
Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 108, "check_cache_memused: %1$ld bytes in use (%2$ld max)\n"),
return;
}
for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
m = next ) {
} else {
}
m->lm_msgid, 0, 0 );
ldap_msgfree( m );
} else {
prev = m;
}
}
}
}
lc->lc_memused, 0, 0 );
}
#endif /* !NO_CACHE */