mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 00:29:35 -05:00
Entry caching. Based on ITS#1545 from Jong Hyuk Choi, jongchoi@us.ibm.com
This commit is contained in:
parent
1226d620e0
commit
713e6beb8d
20 changed files with 1201 additions and 103 deletions
|
|
@ -4,12 +4,12 @@ SRCS = init.c tools.c config.c \
|
|||
add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
|
||||
extended.c passwd.c referral.c attribute.c group.c \
|
||||
attr.c index.c key.c dbcache.c filterindex.c \
|
||||
dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c
|
||||
dn2entry.c dn2id.c error.c id2entry.c idl.c nextid.c cache.c
|
||||
OBJS = init.lo tools.lo config.lo \
|
||||
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
|
||||
extended.lo passwd.lo referral.lo attribute.lo group.lo \
|
||||
attr.lo index.lo key.lo dbcache.lo filterindex.lo \
|
||||
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo
|
||||
dn2entry.lo dn2id.lo error.lo id2entry.lo idl.lo nextid.lo cache.lo
|
||||
|
||||
LDAP_INCDIR= ../../../include
|
||||
LDAP_LIBDIR= ../../../libraries
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ bdb_add(
|
|||
}
|
||||
|
||||
if( 0 ) {
|
||||
/* transaction retry */
|
||||
retry: rc = txn_abort( ltid );
|
||||
retry: /* transaction retry */
|
||||
rc = txn_abort( ltid );
|
||||
ltid = NULL;
|
||||
op->o_private = NULL;
|
||||
if( rc != 0 ) {
|
||||
|
|
@ -130,7 +130,7 @@ retry: rc = txn_abort( ltid );
|
|||
#endif
|
||||
|
||||
/* get parent */
|
||||
rc = bdb_dn2entry( be, ltid, &pdn, &p, &matched, 0 );
|
||||
rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0 );
|
||||
|
||||
switch( rc ) {
|
||||
case 0:
|
||||
|
|
@ -154,7 +154,7 @@ retry: rc = txn_abort( ltid );
|
|||
refs = is_entry_referral( matched )
|
||||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, matched);
|
||||
matched = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -180,8 +180,8 @@ retry: rc = txn_abort( ltid );
|
|||
switch( opinfo.boi_err ) {
|
||||
case DB_LOCK_DEADLOCK:
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
/* free parent and writer lock */
|
||||
bdb_entry_return( be, p );
|
||||
/* free parent and reader lock */
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, p );
|
||||
p = NULL;
|
||||
goto retry;
|
||||
}
|
||||
|
|
@ -214,10 +214,8 @@ retry: rc = txn_abort( ltid );
|
|||
|
||||
if ( is_entry_referral( p ) ) {
|
||||
/* parent is a referral, don't allow add */
|
||||
char *matched_dn = ch_strdup( p->e_dn );
|
||||
BerVarray refs = is_entry_referral( p )
|
||||
? get_entry_referrals( be, conn, op, p )
|
||||
: NULL;
|
||||
char *matched_dn = p->e_dn;
|
||||
BerVarray refs = get_entry_referrals( be, conn, op, p );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is referral\n",
|
||||
0, 0, 0 );
|
||||
|
|
@ -226,7 +224,8 @@ retry: rc = txn_abort( ltid );
|
|||
matched_dn, NULL, refs, NULL );
|
||||
|
||||
ber_bvarray_free( refs );
|
||||
free( matched_dn );
|
||||
bdb_cache_return_entry_r( be, p );
|
||||
p = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -235,8 +234,8 @@ retry: rc = txn_abort( ltid );
|
|||
/* parent must be an administrative point of the required kind */
|
||||
}
|
||||
|
||||
/* free parent and writer lock */
|
||||
bdb_entry_return( be, p );
|
||||
/* free parent and reader lock */
|
||||
bdb_cache_return_entry_r( be, p );
|
||||
p = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -361,6 +360,13 @@ retry: rc = txn_abort( ltid );
|
|||
text = "commit failed";
|
||||
|
||||
} else {
|
||||
/* add the entry to the entry cache */
|
||||
/* we should add to cache only upon free of txn-abort */
|
||||
if (bdb_cache_add_entry_rw(&bdb->bi_cache, e, CACHE_WRITE_LOCK) != 0) {
|
||||
text = "cache add failed";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_add: added id=%08lx dn=\"%s\"\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
|
|
@ -368,6 +374,8 @@ retry: rc = txn_abort( ltid );
|
|||
text = NULL;
|
||||
}
|
||||
|
||||
bdb_cache_entry_commit (e);
|
||||
|
||||
return_results:
|
||||
send_ldap_result( conn, op, rc,
|
||||
NULL, text, NULL, NULL );
|
||||
|
|
@ -379,10 +387,6 @@ return_results:
|
|||
}
|
||||
|
||||
done:
|
||||
if (p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
bdb_entry_return( be, p );
|
||||
}
|
||||
|
||||
if( ltid != NULL ) {
|
||||
txn_abort( ltid );
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ bdb_attribute(
|
|||
AttributeDescription *entry_at,
|
||||
BerVarray *vals )
|
||||
{
|
||||
struct bdbinfo *li = (struct bdbinfo *) be->be_private;
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
struct bdb_op_info *boi = (struct bdb_op_info *) op->o_private;
|
||||
DB_TXN *txn = NULL;
|
||||
Entry *e;
|
||||
|
|
@ -79,7 +79,7 @@ bdb_attribute(
|
|||
|
||||
} else {
|
||||
/* can we find entry */
|
||||
rc = bdb_dn2entry( be, txn, entry_ndn, &e, NULL, 0 );
|
||||
rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0 );
|
||||
switch( rc ) {
|
||||
case DB_NOTFOUND:
|
||||
case 0:
|
||||
|
|
@ -200,7 +200,7 @@ bdb_attribute(
|
|||
return_results:
|
||||
if( target != e ) {
|
||||
/* free entry */
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, e);
|
||||
}
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
|
|
|
|||
|
|
@ -75,6 +75,22 @@ LDAP_BEGIN_DECL
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_CACHE_SIZE 1000
|
||||
|
||||
/* for the in-core cache of entries */
|
||||
typedef struct bdb_cache {
|
||||
int c_maxsize;
|
||||
int c_cursize;
|
||||
Avlnode *c_dntree;
|
||||
Avlnode *c_idtree;
|
||||
Entry *c_lruhead; /* lru - add accessed entries here */
|
||||
Entry *c_lrutail; /* lru - rem lru entries from here */
|
||||
ldap_pvt_thread_mutex_t c_mutex;
|
||||
} Cache;
|
||||
|
||||
#define CACHE_READ_LOCK 0
|
||||
#define CACHE_WRITE_LOCK 1
|
||||
|
||||
#define BDB_INDICES 128
|
||||
|
||||
struct bdb_db_info {
|
||||
|
|
@ -97,6 +113,7 @@ struct bdb_info {
|
|||
int bi_db_opflags; /* db-specific flags */
|
||||
|
||||
slap_mask_t bi_defaultmask;
|
||||
Cache bi_cache;
|
||||
Avlnode *bi_attrs;
|
||||
#ifdef BDB_HIER
|
||||
Avlnode *bi_tree;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ bdb_bind(
|
|||
Debug( LDAP_DEBUG_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val, 0, 0);
|
||||
|
||||
/* get entry */
|
||||
rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
|
||||
rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
|
||||
|
||||
switch(rc) {
|
||||
case DB_NOTFOUND:
|
||||
|
|
@ -67,7 +67,7 @@ bdb_bind(
|
|||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, matched );
|
||||
matched = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -240,7 +240,7 @@ bdb_bind(
|
|||
done:
|
||||
/* free entry and reader lock */
|
||||
if( e != NULL ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, e );
|
||||
}
|
||||
|
||||
/* front end with send result on success (rc==0) */
|
||||
|
|
|
|||
907
servers/slapd/back-bdb/cache.c
Normal file
907
servers/slapd/back-bdb/cache.c
Normal file
|
|
@ -0,0 +1,907 @@
|
|||
/* cache.c - routines to maintain an in-core cache of entries */
|
||||
/* $OpenLDAP$ */
|
||||
/*
|
||||
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
|
||||
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/errno.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
#include "back-bdb.h"
|
||||
|
||||
/* BDB backend specific entry info -- visible only to the cache */
|
||||
typedef struct bdb_entry_info {
|
||||
ldap_pvt_thread_rdwr_t bei_rdwr; /* reader/writer lock */
|
||||
|
||||
/*
|
||||
* remaining fields require backend cache lock to access
|
||||
* These items are specific to the LDBM backend and should
|
||||
* be hidden.
|
||||
*/
|
||||
int bei_state; /* for the cache */
|
||||
#define CACHE_ENTRY_UNDEFINED 0
|
||||
#define CACHE_ENTRY_CREATING 1
|
||||
#define CACHE_ENTRY_READY 2
|
||||
#define CACHE_ENTRY_DELETED 3
|
||||
#define CACHE_ENTRY_COMMITTED 4
|
||||
|
||||
int bei_refcnt; /* # threads ref'ing this entry */
|
||||
Entry *bei_lrunext; /* for cache lru list */
|
||||
Entry *bei_lruprev;
|
||||
} EntryInfo;
|
||||
#undef BEI
|
||||
#define BEI(e) ((EntryInfo *) ((e)->e_private))
|
||||
|
||||
static int bdb_cache_delete_entry_internal(Cache *cache, Entry *e);
|
||||
#ifdef LDAP_DEBUG
|
||||
static void lru_print(Cache *cache);
|
||||
#endif
|
||||
|
||||
static int
|
||||
bdb_cache_entry_rdwr_lock(Entry *e, int rw)
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
|
||||
"bdb_cache_entry_rdwr_lock: %s lock on ID %ld\n",
|
||||
rw ? "w" : "r", e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
|
||||
rw ? "w" : "r", e->e_id, 0);
|
||||
#endif
|
||||
|
||||
if (rw)
|
||||
return ldap_pvt_thread_rdwr_wlock(&BEI(e)->bei_rdwr);
|
||||
else
|
||||
return ldap_pvt_thread_rdwr_rlock(&BEI(e)->bei_rdwr);
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_entry_rdwr_trylock(Entry *e, int rw)
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
|
||||
"bdb_cache_entry_rdwr_trylock: try %s lock on ID: %ld.\n",
|
||||
rw ? "w" : "r", e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n",
|
||||
rw ? "w" : "r", e->e_id, 0);
|
||||
#endif
|
||||
|
||||
|
||||
if (rw)
|
||||
return ldap_pvt_thread_rdwr_wtrylock(&BEI(e)->bei_rdwr);
|
||||
else
|
||||
return ldap_pvt_thread_rdwr_rtrylock(&BEI(e)->bei_rdwr);
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_entry_rdwr_unlock(Entry *e, int rw)
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
|
||||
"bdb_cache_entry_rdwr_unlock: remove %s lock on ID %ld.\n",
|
||||
rw ? "w" : "r", e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n",
|
||||
rw ? "w" : "r", e->e_id, 0);
|
||||
#endif
|
||||
|
||||
|
||||
if (rw)
|
||||
return ldap_pvt_thread_rdwr_wunlock(&BEI(e)->bei_rdwr);
|
||||
else
|
||||
return ldap_pvt_thread_rdwr_runlock(&BEI(e)->bei_rdwr);
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_entry_rdwr_init(Entry *e)
|
||||
{
|
||||
return ldap_pvt_thread_rdwr_init( &BEI(e)->bei_rdwr );
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_entry_rdwr_destroy(Entry *e)
|
||||
{
|
||||
return ldap_pvt_thread_rdwr_destroy( &BEI(e)->bei_rdwr );
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_entry_private_init( Entry *e )
|
||||
{
|
||||
assert( e->e_private == NULL );
|
||||
|
||||
if( e->e_private != NULL ) {
|
||||
/* this should never happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
e->e_private = ch_calloc(1, sizeof(struct bdb_entry_info));
|
||||
|
||||
if( bdb_cache_entry_rdwr_init( e ) != 0 ) {
|
||||
free( BEI(e) );
|
||||
e->e_private = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* marks an entry in CREATING state as committed, so it is really returned
|
||||
* to the cache. Otherwise an entry in CREATING state is removed.
|
||||
* Makes e_private be destroyed at the following cache_return_entry_w,
|
||||
* but lets the entry untouched (owned by someone else)
|
||||
*/
|
||||
void
|
||||
bdb_cache_entry_commit( Entry *e )
|
||||
{
|
||||
assert( e );
|
||||
assert( e->e_private );
|
||||
assert( BEI(e)->bei_state == CACHE_ENTRY_CREATING );
|
||||
/* assert( BEI(e)->bei_refcnt == 1 ); */
|
||||
|
||||
BEI(e)->bei_state = CACHE_ENTRY_COMMITTED;
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_entry_private_destroy( Entry *e )
|
||||
{
|
||||
assert( e->e_private );
|
||||
|
||||
bdb_cache_entry_rdwr_destroy( e );
|
||||
|
||||
free( e->e_private );
|
||||
e->e_private = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
|
||||
{
|
||||
ID id;
|
||||
int refcnt, freeit = 1;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private );
|
||||
|
||||
bdb_cache_entry_rdwr_unlock(e, rw);
|
||||
|
||||
id = e->e_id;
|
||||
refcnt = --BEI(e)->bei_refcnt;
|
||||
|
||||
/*
|
||||
* if the entry is returned when in CREATING state, it is deleted
|
||||
* but not freed because it may belong to someone else (do_add,
|
||||
* for instance)
|
||||
*/
|
||||
if ( BEI(e)->bei_state == CACHE_ENTRY_CREATING ) {
|
||||
bdb_cache_delete_entry_internal( cache, e );
|
||||
freeit = 0;
|
||||
/* now the entry is in DELETED state */
|
||||
}
|
||||
|
||||
if ( BEI(e)->bei_state == CACHE_ENTRY_COMMITTED ) {
|
||||
BEI(e)->bei_state = CACHE_ENTRY_READY;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
|
||||
id, rw ? "w" : "r", refcnt ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_return_entry_%s( %ld ): created (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt );
|
||||
#endif
|
||||
|
||||
|
||||
} else if ( BEI(e)->bei_state == CACHE_ENTRY_DELETED ) {
|
||||
if( refcnt > 0 ) {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_return_entry_rw: %ld, delete pending (%d).\n",
|
||||
id, refcnt ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_return_entry_%s( %ld ): delete pending (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt );
|
||||
#endif
|
||||
|
||||
|
||||
} else {
|
||||
bdb_cache_entry_private_destroy( e );
|
||||
if ( freeit ) {
|
||||
bdb_entry_return( e );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_return_entry_rw: (%ld): deleted (%d)\n",
|
||||
id, refcnt ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_return_entry_%s( %ld ): deleted (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
|
||||
id, rw ? "w": "r", refcnt ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_return_entry_%s( %ld ): returned (%d)\n",
|
||||
rw ? "w" : "r", id, refcnt);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define LRU_DELETE( cache, e ) do { \
|
||||
if ( BEI(e)->bei_lruprev != NULL ) { \
|
||||
BEI(BEI(e)->bei_lruprev)->bei_lrunext = BEI(e)->bei_lrunext; \
|
||||
} else { \
|
||||
(cache)->c_lruhead = BEI(e)->bei_lrunext; \
|
||||
} \
|
||||
if ( BEI(e)->bei_lrunext != NULL ) { \
|
||||
BEI(BEI(e)->bei_lrunext)->bei_lruprev = BEI(e)->bei_lruprev; \
|
||||
} else { \
|
||||
(cache)->c_lrutail = BEI(e)->bei_lruprev; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LRU_ADD( cache, e ) do { \
|
||||
BEI(e)->bei_lrunext = (cache)->c_lruhead; \
|
||||
if ( BEI(e)->bei_lrunext != NULL ) { \
|
||||
BEI(BEI(e)->bei_lrunext)->bei_lruprev = (e); \
|
||||
} \
|
||||
(cache)->c_lruhead = (e); \
|
||||
BEI(e)->bei_lruprev = NULL; \
|
||||
if ( (cache)->c_lrutail == NULL ) { \
|
||||
(cache)->c_lrutail = (e); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* cache_add_entry_rw - create and lock an entry in the cache
|
||||
* returns: 0 entry has been created and locked
|
||||
* 1 entry already existed
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
bdb_cache_add_entry_rw(
|
||||
Cache *cache,
|
||||
Entry *e,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
int i, rc;
|
||||
Entry *ee;
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
|
||||
"bdb_cache_add_entry_rw: add (%s):%s to cache\n",
|
||||
e->e_dn, rw ? "w" : "r" ));
|
||||
#endif
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private == NULL );
|
||||
|
||||
if( bdb_cache_entry_private_init(e) != 0 ) {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ERR,
|
||||
"bdb_cache_add_entry_rw: add (%s):%ld private init failed!\n",
|
||||
e->e_dn, e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> bdb_cache_add_entry( %ld ): \"%s\": private init failed!\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( avl_insert( &cache->c_dntree, (caddr_t) e,
|
||||
(AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_add_entry: (%s):%ld already in cache.\n",
|
||||
e->e_dn, e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_add_entry( %ld ): \"%s\": already in dn cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
bdb_cache_entry_private_destroy(e);
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_insert( &cache->c_idtree, (caddr_t) e,
|
||||
(AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_add_entry: (%s):%ls already in cache.\n",
|
||||
e->e_dn, e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> bdb_cache_add_entry( %ld ): \"%s\": already in id cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* delete from dn tree inserted above */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e,
|
||||
(AVL_CMP) entry_dn_cmp ) == NULL )
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
|
||||
"bdb_cache_add_entry: can't delete (%s) from cache.\n",
|
||||
e->e_dn ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
|
||||
0, 0, 0 );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bdb_cache_entry_private_destroy(e);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
bdb_cache_entry_rdwr_lock( e, rw );
|
||||
|
||||
/* put the entry into 'CREATING' state */
|
||||
/* will be marked after when entry is returned */
|
||||
BEI(e)->bei_state = CACHE_ENTRY_CREATING;
|
||||
BEI(e)->bei_refcnt = 1;
|
||||
|
||||
/* lru */
|
||||
LRU_ADD( cache, e );
|
||||
if ( ++cache->c_cursize > cache->c_maxsize ) {
|
||||
/*
|
||||
* find the lru entry not currently in use and delete it.
|
||||
* in case a lot of entries are in use, only look at the
|
||||
* first 10 on the tail of the list.
|
||||
*/
|
||||
i = 0;
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
BEI(cache->c_lrutail)->bei_refcnt != 0 &&
|
||||
i < 10 )
|
||||
{
|
||||
/* move this in-use entry to the front of the q */
|
||||
ee = cache->c_lrutail;
|
||||
LRU_DELETE( cache, ee );
|
||||
LRU_ADD( cache, ee );
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* found at least one to delete - try to get back under
|
||||
* the max cache size.
|
||||
*/
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
BEI(cache->c_lrutail)->bei_refcnt == 0 &&
|
||||
cache->c_cursize > cache->c_maxsize )
|
||||
{
|
||||
e = cache->c_lrutail;
|
||||
|
||||
/* delete from cache and lru q */
|
||||
/* XXX do we need rc ? */
|
||||
rc = bdb_cache_delete_entry_internal( cache, e );
|
||||
bdb_cache_entry_private_destroy( e );
|
||||
bdb_entry_return( e );
|
||||
}
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_update_entry - update a LOCKED entry which has been deleted.
|
||||
* returns: 0 entry has been created and locked
|
||||
* 1 entry already existed
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
bdb_cache_update_entry(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int i, rc;
|
||||
Entry *ee;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private );
|
||||
|
||||
if ( avl_insert( &cache->c_dntree, (caddr_t) e,
|
||||
(AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_update_entry: (%s):%ld already in dn cache\n",
|
||||
e->e_dn, e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_update_entry( %ld ): \"%s\": already in dn cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_insert( &cache->c_idtree, (caddr_t) e,
|
||||
(AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_update_entry: (%s)%ld already in id cache\n",
|
||||
e->e_dn, e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"====> bdb_cache_update_entry( %ld ): \"%s\": already in id cache\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
/* delete from dn tree inserted above */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e,
|
||||
(AVL_CMP) entry_dn_cmp ) == NULL )
|
||||
{
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
|
||||
"bdb_cache_update_entry: can't delete (%s)%ld from dn cache.\n",
|
||||
e->e_dn, e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
|
||||
0, 0, 0 );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
||||
/* put the entry into 'CREATING' state */
|
||||
/* will be marked after when entry is returned */
|
||||
BEI(e)->bei_state = CACHE_ENTRY_CREATING;
|
||||
|
||||
/* lru */
|
||||
LRU_ADD( cache, e );
|
||||
if ( ++cache->c_cursize > cache->c_maxsize ) {
|
||||
/*
|
||||
* find the lru entry not currently in use and delete it.
|
||||
* in case a lot of entries are in use, only look at the
|
||||
* first 10 on the tail of the list.
|
||||
*/
|
||||
i = 0;
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
BEI(cache->c_lrutail)->bei_refcnt != 0 &&
|
||||
i < 10 )
|
||||
{
|
||||
/* move this in-use entry to the front of the q */
|
||||
ee = cache->c_lrutail;
|
||||
LRU_DELETE( cache, ee );
|
||||
LRU_ADD( cache, ee );
|
||||
i++;
|
||||
}
|
||||
|
||||
/*
|
||||
* found at least one to delete - try to get back under
|
||||
* the max cache size.
|
||||
*/
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
BEI(cache->c_lrutail)->bei_refcnt == 0 &&
|
||||
cache->c_cursize > cache->c_maxsize )
|
||||
{
|
||||
e = cache->c_lrutail;
|
||||
|
||||
/* delete from cache and lru q */
|
||||
/* XXX do we need rc ? */
|
||||
rc = bdb_cache_delete_entry_internal( cache, e );
|
||||
bdb_cache_entry_private_destroy( e );
|
||||
bdb_entry_return( e );
|
||||
}
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
ID
|
||||
bdb_cache_find_entry_ndn2id(
|
||||
Backend *be,
|
||||
Cache *cache,
|
||||
struct berval *ndn
|
||||
)
|
||||
{
|
||||
Entry e, *ep;
|
||||
ID id;
|
||||
int count = 0;
|
||||
|
||||
/* this function is always called with normalized DN */
|
||||
e.e_nname = *ndn;
|
||||
|
||||
try_again:
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e,
|
||||
(AVL_CMP) entry_dn_cmp )) != NULL )
|
||||
{
|
||||
int state;
|
||||
count++;
|
||||
|
||||
/*
|
||||
* ep now points to an unlocked entry
|
||||
* we do not need to lock the entry if we only
|
||||
* check the state, refcnt, LRU, and id.
|
||||
*/
|
||||
|
||||
assert( ep->e_private );
|
||||
|
||||
/* save id */
|
||||
id = ep->e_id;
|
||||
state = BEI(ep)->bei_state;
|
||||
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( state != CACHE_ENTRY_READY ) {
|
||||
assert(state != CACHE_ENTRY_UNDEFINED);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
|
||||
"bdb_cache_find_entry_dn2id: (%s) %ld not ready: %d\n",
|
||||
ndn->bv_val, id, state ));
|
||||
#else
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n",
|
||||
ndn->bv_val, id, state);
|
||||
#endif
|
||||
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_find_entry_dn2id: (%s): %ld %d tries\n",
|
||||
ndn->bv_val, id, count ));
|
||||
#else
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n",
|
||||
ndn->bv_val, id, count);
|
||||
#endif
|
||||
|
||||
|
||||
} else {
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
id = NOID;
|
||||
}
|
||||
|
||||
return( id );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_find_entry_id - find an entry in the cache, given id
|
||||
*/
|
||||
|
||||
Entry *
|
||||
bdb_cache_find_entry_id(
|
||||
Cache *cache,
|
||||
ID id,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
Entry e;
|
||||
Entry *ep;
|
||||
int count = 0;
|
||||
|
||||
e.e_id = id;
|
||||
|
||||
try_again:
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e,
|
||||
(AVL_CMP) entry_id_cmp )) != NULL )
|
||||
{
|
||||
int state;
|
||||
ID ep_id;
|
||||
|
||||
count++;
|
||||
|
||||
assert( ep->e_private );
|
||||
|
||||
ep_id = ep->e_id;
|
||||
state = BEI(ep)->bei_state;
|
||||
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( state != CACHE_ENTRY_READY ) {
|
||||
|
||||
assert(state != CACHE_ENTRY_UNDEFINED);
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
|
||||
"bdb_cache_find_entry_id: (%ld)->%ld not ready (%d).\n",
|
||||
id, ep_id, state ));
|
||||
|
||||
#else
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_find_entry_id( %ld ): %ld (not ready) %d\n",
|
||||
id, ep_id, state);
|
||||
#endif
|
||||
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* acquire reader lock */
|
||||
if ( bdb_cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
|
||||
/* could not acquire entry lock...
|
||||
* owner cannot free as we have the cache locked.
|
||||
* so, unlock the cache, yield, and try again.
|
||||
*/
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
|
||||
"bdb_cache_find_entry_id: %ld -> %ld (busy) %d.\n",
|
||||
id, ep_id, state ));
|
||||
#else
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_find_entry_id( %ld ): %ld (busy) %d\n",
|
||||
id, ep_id, state);
|
||||
#endif
|
||||
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
BEI(ep)->bei_refcnt++;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
|
||||
"bdb_cache_find_entry_id: %ld -> %s found %d tries.\n",
|
||||
ep_id, ep->e_dn, count ));
|
||||
#else
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"====> bdb_cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n",
|
||||
ep_id, ep->e_dn, count);
|
||||
#endif
|
||||
|
||||
|
||||
return( ep );
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_delete_entry - delete the entry e from the cache. the caller
|
||||
* should have obtained e (increasing its ref count) via a call to one
|
||||
* of the cache_find_* routines. the caller should *not* call the
|
||||
* cache_return_entry() routine prior to calling cache_delete_entry().
|
||||
* it performs this function.
|
||||
*
|
||||
* returns: 0 e was deleted ok
|
||||
* 1 e was not in the cache
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
bdb_cache_delete_entry(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
assert( e->e_private );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
|
||||
"bdb_cache_delete_entry: delete %ld.\n", e->e_id ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_delete_entry( %ld )\n",
|
||||
e->e_id, 0, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
rc = bdb_cache_delete_entry_internal( cache, e );
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_cache_delete_entry_internal(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int rc = 0; /* return code */
|
||||
|
||||
/* dn tree */
|
||||
if ( avl_delete( &cache->c_dntree, (caddr_t) e, (AVL_CMP) entry_dn_cmp )
|
||||
== NULL )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
/* id tree */
|
||||
if ( avl_delete( &cache->c_idtree, (caddr_t) e, (AVL_CMP) entry_id_cmp )
|
||||
== NULL )
|
||||
{
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* lru */
|
||||
LRU_DELETE( cache, e );
|
||||
cache->c_cursize--;
|
||||
|
||||
/*
|
||||
* flag entry to be freed later by a call to cache_return_entry()
|
||||
*/
|
||||
BEI(e)->bei_state = CACHE_ENTRY_DELETED;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
void
|
||||
bdb_cache_release_all( Cache *cache )
|
||||
{
|
||||
Entry *e;
|
||||
int rc;
|
||||
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
|
||||
"bdb_cache_release_all: enter\n" ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_release_all\n", 0, 0, 0 );
|
||||
#endif
|
||||
|
||||
|
||||
while ( (e = cache->c_lrutail) != NULL && BEI(e)->bei_refcnt == 0 ) {
|
||||
#ifdef LDAP_RDWR_DEBUG
|
||||
assert(!ldap_pvt_thread_rdwr_active(&BEI(e)->bei_rdwr));
|
||||
#endif
|
||||
|
||||
/* delete from cache and lru q */
|
||||
/* XXX do we need rc ? */
|
||||
rc = bdb_cache_delete_entry_internal( cache, e );
|
||||
bdb_cache_entry_private_destroy( e );
|
||||
bdb_entry_return( e );
|
||||
}
|
||||
|
||||
if ( cache->c_cursize ) {
|
||||
#ifdef NEW_LOGGING
|
||||
LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
|
||||
"bdb_cache_release_all: Entry cache could not be emptied.\n" ));
|
||||
#else
|
||||
Debug( LDAP_DEBUG_TRACE, "Entry-cache could not be emptied\n", 0, 0, 0 );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
}
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
|
||||
static void
|
||||
bdb_lru_print( Cache *cache )
|
||||
{
|
||||
Entry *e;
|
||||
|
||||
fprintf( stderr, "LRU queue (head to tail):\n" );
|
||||
for ( e = cache->c_lruhead; e != NULL; e = BEI(e)->bei_lrunext ) {
|
||||
fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
|
||||
e->e_dn, e->e_id, BEI(e)->bei_refcnt );
|
||||
}
|
||||
fprintf( stderr, "LRU queue (tail to head):\n" );
|
||||
for ( e = cache->c_lrutail; e != NULL; e = BEI(e)->bei_lruprev ) {
|
||||
fprintf( stderr, "\tdn \"%20s\" id %ld refcnt %d\n",
|
||||
e->e_dn, e->e_id, BEI(e)->bei_refcnt );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -32,7 +32,7 @@ bdb_compare(
|
|||
int manageDSAit = get_manageDSAit( op );
|
||||
|
||||
/* get entry */
|
||||
rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
|
||||
rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
|
||||
|
||||
switch( rc ) {
|
||||
case DB_NOTFOUND:
|
||||
|
|
@ -53,7 +53,7 @@ bdb_compare(
|
|||
refs = is_entry_referral( matched )
|
||||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, matched );
|
||||
matched = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -119,7 +119,7 @@ return_results:
|
|||
done:
|
||||
/* free entry */
|
||||
if( e != NULL ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, e );
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,16 @@ bdb_db_config(
|
|||
if( rc != LDAP_SUCCESS ) return 1;
|
||||
#endif
|
||||
|
||||
/* size of the cache in entries */
|
||||
} else if ( strcasecmp( argv[0], "cachesize" ) == 0 ) {
|
||||
if ( argc < 2 ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: missing size in \"cachesize <size>\" line\n",
|
||||
fname, lineno );
|
||||
return( 1 );
|
||||
}
|
||||
bdb->bi_cache.c_maxsize = atoi( argv[1] );
|
||||
|
||||
/* anything else */
|
||||
} else {
|
||||
fprintf( stderr, "%s: line %d: "
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ bdb_delete(
|
|||
|
||||
if( 0 ) {
|
||||
retry: /* transaction retry */
|
||||
if( e != NULL ) {
|
||||
bdb_cache_return_entry_w(&bdb->bi_cache, e);
|
||||
}
|
||||
Debug( LDAP_DEBUG_TRACE, "==> bdb_delete: retrying...\n",
|
||||
0, 0, 0 );
|
||||
rc = txn_abort( ltid );
|
||||
|
|
@ -100,7 +103,7 @@ retry: /* transaction retry */
|
|||
}
|
||||
#endif
|
||||
/* get parent */
|
||||
rc = bdb_dn2entry( be, ltid, &pdn, &p, NULL, 0 );
|
||||
rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0 );
|
||||
|
||||
switch( rc ) {
|
||||
case 0:
|
||||
|
|
@ -128,7 +131,7 @@ retry: /* transaction retry */
|
|||
rc = access_allowed( be, conn, op, p,
|
||||
children, NULL, ACL_WRITE );
|
||||
|
||||
bdb_entry_return( be, p );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, p);
|
||||
p = NULL;
|
||||
|
||||
switch( opinfo.boi_err ) {
|
||||
|
|
@ -191,7 +194,7 @@ retry: /* transaction retry */
|
|||
}
|
||||
|
||||
/* get entry for read/modify/write */
|
||||
rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, DB_RMW );
|
||||
rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW );
|
||||
|
||||
switch( rc ) {
|
||||
case 0:
|
||||
|
|
@ -219,7 +222,7 @@ retry: /* transaction retry */
|
|||
refs = is_entry_referral( matched )
|
||||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, matched );
|
||||
matched = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -297,7 +300,7 @@ retry: /* transaction retry */
|
|||
}
|
||||
|
||||
/* delete from id2entry */
|
||||
rc = bdb_id2entry_delete( be, ltid, e->e_id );
|
||||
rc = bdb_id2entry_delete( be, ltid, e );
|
||||
if ( rc != 0 ) {
|
||||
switch( rc ) {
|
||||
case DB_LOCK_DEADLOCK:
|
||||
|
|
@ -371,7 +374,7 @@ return_results:
|
|||
done:
|
||||
/* free entry */
|
||||
if( e != NULL ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_w(&bdb->bi_cache, e);
|
||||
}
|
||||
|
||||
if( ltid != NULL ) {
|
||||
|
|
|
|||
|
|
@ -18,18 +18,19 @@
|
|||
*/
|
||||
|
||||
int
|
||||
bdb_dn2entry(
|
||||
bdb_dn2entry_rw(
|
||||
BackendDB *be,
|
||||
DB_TXN *tid,
|
||||
struct berval *dn,
|
||||
Entry **e,
|
||||
Entry **matched,
|
||||
int flags )
|
||||
int flags,
|
||||
int rw )
|
||||
{
|
||||
int rc;
|
||||
ID id, id2 = 0;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry(\"%s\")\n",
|
||||
Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry_rw(\"%s\")\n",
|
||||
dn->bv_val, 0, 0 );
|
||||
|
||||
*e = NULL;
|
||||
|
|
@ -46,9 +47,9 @@ bdb_dn2entry(
|
|||
}
|
||||
|
||||
if( id2 == 0 ) {
|
||||
rc = bdb_id2entry( be, tid, id, e );
|
||||
rc = bdb_id2entry_rw( be, tid, id, e, rw );
|
||||
} else {
|
||||
rc = bdb_id2entry( be, tid, id2, matched );
|
||||
rc = bdb_id2entry_r( be, tid, id2, matched);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -223,6 +223,12 @@ bdb_dn2id(
|
|||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id( \"%s\" )\n", dn->bv_val, 0, 0 );
|
||||
|
||||
assert (id);
|
||||
|
||||
if ((*id = bdb_cache_find_entry_ndn2id(be,&bdb->bi_cache,dn)) != NOID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DBTzero( &key );
|
||||
key.size = dn->bv_len + 2;
|
||||
key.data = ch_malloc( key.size );
|
||||
|
|
@ -263,6 +269,7 @@ bdb_dn2id_matched(
|
|||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
DB *db = bdb->bi_dn2id->bdi_db;
|
||||
char *buf, *dn;
|
||||
ID cached_id;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val, 0, 0 );
|
||||
|
||||
|
|
@ -284,8 +291,20 @@ bdb_dn2id_matched(
|
|||
|
||||
*id = NOID;
|
||||
|
||||
/* fetch it */
|
||||
rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
|
||||
/* lookup cache */
|
||||
cached_id = bdb_cache_find_entry_ndn2id(be,&bdb->bi_cache,dn);
|
||||
|
||||
if (cached_id != NOID) {
|
||||
rc = 0;
|
||||
*id = cached_id;
|
||||
if ( dn != buf+1 ) {
|
||||
*id2 = *id;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
/* fetch it */
|
||||
rc = db->get(db, txn, &key, &data, bdb->bi_db_opflags );
|
||||
}
|
||||
|
||||
if( rc == DB_NOTFOUND ) {
|
||||
char *pdn = NULL;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ bdb_group(
|
|||
AttributeDescription *group_at
|
||||
)
|
||||
{
|
||||
struct bdbinfo *li = (struct bdbinfo *) be->be_private;
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
struct bdb_op_info *boi = (struct bdb_op_info *) op->o_private;
|
||||
DB_TXN *txn;
|
||||
Entry *e;
|
||||
|
|
@ -88,7 +88,7 @@ bdb_group(
|
|||
#endif
|
||||
} else {
|
||||
/* can we find group entry */
|
||||
rc = bdb_dn2entry( be, txn, gr_ndn, &e, NULL, 0 );
|
||||
rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0 );
|
||||
if( rc ) {
|
||||
if( txn ) {
|
||||
boi->boi_err = rc;
|
||||
|
|
@ -208,7 +208,7 @@ bdb_group(
|
|||
return_results:
|
||||
if( target != e ) {
|
||||
/* free entry */
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, e );
|
||||
}
|
||||
|
||||
#ifdef NEW_LOGGING
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ int bdb_id2entry_put(
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine adds (or updates) an entry on disk.
|
||||
* The cache should be already be updated.
|
||||
*/
|
||||
|
||||
|
||||
int bdb_id2entry_add(
|
||||
BackendDB *be,
|
||||
DB_TXN *tid,
|
||||
|
|
@ -69,17 +75,18 @@ int bdb_id2entry_update(
|
|||
return bdb_id2entry_put(be, tid, e, 0);
|
||||
}
|
||||
|
||||
int bdb_id2entry(
|
||||
int bdb_id2entry_rw(
|
||||
BackendDB *be,
|
||||
DB_TXN *tid,
|
||||
ID id,
|
||||
Entry **e )
|
||||
Entry **e,
|
||||
int rw )
|
||||
{
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
DB *db = bdb->bi_id2entry->bdi_db;
|
||||
DBT key, data;
|
||||
struct berval bv;
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
*e = NULL;
|
||||
|
||||
|
|
@ -90,6 +97,10 @@ int bdb_id2entry(
|
|||
DBTzero( &data );
|
||||
data.flags = DB_DBT_MALLOC;
|
||||
|
||||
if ((*e = bdb_cache_find_entry_id(&bdb->bi_cache, id, rw)) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fetch it */
|
||||
rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags );
|
||||
|
||||
|
|
@ -109,53 +120,85 @@ int bdb_id2entry(
|
|||
*/
|
||||
ch_free( data.data );
|
||||
}
|
||||
|
||||
if (rc == 0 && bdb_cache_add_entry_rw(&bdb->bi_cache, *e, rw) != 0) {
|
||||
if ((*e)->e_private != NULL)
|
||||
free ((*e)->e_private);
|
||||
(*e)->e_private = NULL;
|
||||
bdb_entry_return (*e);
|
||||
if ((*e=bdb_cache_find_entry_id(&bdb->bi_cache,id,rw)) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BDB_HIER
|
||||
bdb_fix_dn(be, id, *e);
|
||||
#endif
|
||||
|
||||
if (rc == 0)
|
||||
bdb_cache_entry_commit(*e);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bdb_id2entry_delete(
|
||||
BackendDB *be,
|
||||
DB_TXN *tid,
|
||||
ID id )
|
||||
Entry *e )
|
||||
{
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
DB *db = bdb->bi_id2entry->bdi_db;
|
||||
DBT key;
|
||||
int rc;
|
||||
|
||||
bdb_cache_delete_entry(&bdb->bi_cache, e);
|
||||
|
||||
DBTzero( &key );
|
||||
key.data = (char *) &id;
|
||||
key.data = (char *) &e->e_id;
|
||||
key.size = sizeof(ID);
|
||||
|
||||
/* delete from database */
|
||||
rc = db->del( db, tid, &key, 0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bdb_entry_return(
|
||||
BackendDB *be,
|
||||
Entry *e )
|
||||
{
|
||||
/* Our entries are allocated in two blocks; the data comes from
|
||||
* the db itself and the Entry structure and associated pointers
|
||||
* are allocated in entry_decode. The db data pointer is saved
|
||||
* in e_private. Since the Entry structure is allocated as a single
|
||||
* in e_bv. Since the Entry structure is allocated as a single
|
||||
* block, e_attrs is always a fixed offset from e. The exception
|
||||
* is when an entry has been modified, in which case we also need
|
||||
* to free e_attrs.
|
||||
*/
|
||||
if( !e->e_bv.bv_val ) { /* A regular entry, from do_add */
|
||||
entry_free( e );
|
||||
return 0;
|
||||
}
|
||||
if( (void *) e->e_attrs != (void *) (e+1)) {
|
||||
attrs_free( e->e_attrs );
|
||||
}
|
||||
|
||||
/* See if the DNs were changed by modrdn */
|
||||
if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
|
||||
e->e_bv.bv_val + e->e_bv.bv_len ) {
|
||||
ch_free(e->e_name.bv_val);
|
||||
ch_free(e->e_nname.bv_val);
|
||||
e->e_name.bv_val = NULL;
|
||||
e->e_nname.bv_val = NULL;
|
||||
}
|
||||
#ifdef BDB_HIER
|
||||
/* We had to construct the dn and ndn as well, in a single block */
|
||||
free( e->e_dn );
|
||||
if( e->e_name.bv_val ) {
|
||||
free( e->e_name.bv_val );
|
||||
}
|
||||
#endif
|
||||
/* In tool mode the e_private buffer is realloc'd, leave it alone */
|
||||
if( e->e_private && !(slapMode & SLAP_TOOL_MODE) ) {
|
||||
free( e->e_private );
|
||||
/* In tool mode the e_bv buffer is realloc'd, leave it alone */
|
||||
if( !(slapMode & SLAP_TOOL_MODE) ) {
|
||||
free( e->e_bv.bv_val );
|
||||
}
|
||||
|
||||
free( e );
|
||||
|
|
@ -170,12 +213,20 @@ int bdb_entry_release(
|
|||
Entry *e,
|
||||
int rw )
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (o && o->o_tag == LDAP_REQ_ADD)
|
||||
entry_free(e);
|
||||
else
|
||||
retval = bdb_entry_return( be, e );
|
||||
|
||||
return retval;
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
|
||||
/* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
|
||||
SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
|
||||
|
||||
if ( slapMode == SLAP_SERVER_MODE ) {
|
||||
/* free entry and reader or writer lock */
|
||||
bdb_cache_return_entry_rw( &bdb->bi_cache, e, rw );
|
||||
} else {
|
||||
if (e->e_private != NULL)
|
||||
free (e->e_private);
|
||||
e->e_private = NULL;
|
||||
bdb_entry_return ( e );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ bdb_db_init( BackendDB *be )
|
|||
bdb->bi_dbenv_mode = DEFAULT_MODE;
|
||||
bdb->bi_txn = 1; /* default to using transactions */
|
||||
|
||||
bdb->bi_cache.c_maxsize = DEFAULT_CACHE_SIZE;
|
||||
|
||||
#ifndef NO_THREADS
|
||||
#if 0
|
||||
bdb->bi_lock_detect = DB_LOCK_NORUN;
|
||||
|
|
@ -88,6 +90,7 @@ bdb_db_init( BackendDB *be )
|
|||
|
||||
ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
|
||||
ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
|
||||
ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_mutex );
|
||||
#ifdef BDB_HIER
|
||||
ldap_pvt_thread_rdwr_init( &bdb->bi_tree_rdwr );
|
||||
#endif
|
||||
|
|
@ -349,6 +352,8 @@ bdb_db_close( BackendDB *be )
|
|||
free( bdb->bi_databases );
|
||||
bdb_attr_index_destroy( bdb->bi_attrs );
|
||||
|
||||
bdb_cache_release_all (&bdb->bi_cache);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -370,6 +375,8 @@ bdb_db_destroy( BackendDB *be )
|
|||
}
|
||||
}
|
||||
|
||||
bdb_cache_release_all (&bdb->bi_cache);
|
||||
|
||||
rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
|
||||
bdb->bi_dbenv = NULL;
|
||||
if( rc != 0 ) {
|
||||
|
|
|
|||
|
|
@ -198,6 +198,10 @@ bdb_modify(
|
|||
|
||||
if( 0 ) {
|
||||
retry: /* transaction retry */
|
||||
if( e != NULL ) {
|
||||
bdb_cache_delete_entry(&bdb->bi_cache, e);
|
||||
bdb_cache_return_entry_w(&bdb->bi_cache, e);
|
||||
}
|
||||
Debug(LDAP_DEBUG_TRACE,
|
||||
"bdb_modify: retrying...\n", 0, 0, 0);
|
||||
rc = txn_abort( ltid );
|
||||
|
|
@ -232,7 +236,7 @@ retry: /* transaction retry */
|
|||
op->o_private = &opinfo;
|
||||
|
||||
/* get entry */
|
||||
rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 );
|
||||
rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
|
||||
|
||||
if ( rc != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
|
|
@ -261,7 +265,7 @@ retry: /* transaction retry */
|
|||
refs = is_entry_referral( matched )
|
||||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r (&bdb->bi_cache, matched);
|
||||
matched = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -364,8 +368,7 @@ done:
|
|||
}
|
||||
|
||||
if( e != NULL ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_w (&bdb->bi_cache, e);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ bdb_modrdn(
|
|||
LDAPRDN *new_rdn = NULL;
|
||||
LDAPRDN *old_rdn = NULL;
|
||||
|
||||
Entry *np = NULL; /* newSuperior Entry */
|
||||
Entry *np = NULL; /* newSuperior Entry */
|
||||
struct berval *np_dn = NULL; /* newSuperior dn */
|
||||
struct berval *np_ndn = NULL; /* newSuperior ndn */
|
||||
struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
|
||||
|
|
@ -70,6 +70,16 @@ bdb_modrdn(
|
|||
|
||||
if( 0 ) {
|
||||
retry: /* transaction retry */
|
||||
if (e != NULL) {
|
||||
bdb_cache_delete_entry(&bdb->bi_cache, e);
|
||||
bdb_cache_return_entry_w(&bdb->bi_cache, e);
|
||||
}
|
||||
if (p != NULL) {
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, p);
|
||||
}
|
||||
if (np != NULL) {
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, np);
|
||||
}
|
||||
Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
|
||||
rc = txn_abort( ltid );
|
||||
ltid = NULL;
|
||||
|
|
@ -103,7 +113,7 @@ retry: /* transaction retry */
|
|||
op->o_private = &opinfo;
|
||||
|
||||
/* get entry */
|
||||
rc = bdb_dn2entry( be, ltid, ndn, &e, &matched, 0 );
|
||||
rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
|
||||
|
||||
switch( rc ) {
|
||||
case 0:
|
||||
|
|
@ -123,11 +133,11 @@ retry: /* transaction retry */
|
|||
BerVarray refs;
|
||||
|
||||
if( matched != NULL ) {
|
||||
matched_dn = strdup( matched->e_dn );
|
||||
matched_dn = ch_strdup( matched->e_dn );
|
||||
refs = is_entry_referral( matched )
|
||||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, matched );
|
||||
matched = NULL;
|
||||
|
||||
} else {
|
||||
|
|
@ -176,7 +186,7 @@ retry: /* transaction retry */
|
|||
/* Make sure parent entry exist and we can write its
|
||||
* children.
|
||||
*/
|
||||
rc = bdb_dn2entry( be, ltid, &p_ndn, &p, NULL, 0 );
|
||||
rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0 );
|
||||
|
||||
switch( rc ) {
|
||||
case 0:
|
||||
|
|
@ -291,7 +301,7 @@ retry: /* transaction retry */
|
|||
/* newSuperior == entry being moved?, if so ==> ERROR */
|
||||
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
|
||||
|
||||
rc = bdb_dn2entry( be, ltid, nnewSuperior, &np, NULL, 0 );
|
||||
rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0 );
|
||||
|
||||
switch( rc ) {
|
||||
case 0:
|
||||
|
|
@ -571,6 +581,8 @@ retry: /* transaction retry */
|
|||
goto return_results;
|
||||
}
|
||||
|
||||
(void) bdb_cache_delete_entry(&bdb->bi_cache, e);
|
||||
|
||||
/* Binary format uses a single contiguous block, cannot
|
||||
* free individual fields. Leave new_dn/new_ndn set so
|
||||
* they can be individually freed later.
|
||||
|
|
@ -578,6 +590,9 @@ retry: /* transaction retry */
|
|||
e->e_name = new_dn;
|
||||
e->e_nname = new_ndn;
|
||||
|
||||
new_dn.bv_val = NULL;
|
||||
new_ndn.bv_val = NULL;
|
||||
|
||||
/* add new one */
|
||||
rc = bdb_dn2id_add( be, ltid, np_ndn, e );
|
||||
if ( rc != 0 ) {
|
||||
|
|
@ -630,11 +645,13 @@ retry: /* transaction retry */
|
|||
rc = LDAP_OTHER;
|
||||
text = "commit failed";
|
||||
} else {
|
||||
(void) bdb_cache_update_entry(&bdb->bi_cache, e);
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_modrdn: added id=%08lx dn=\"%s\"\n",
|
||||
e->e_id, e->e_dn, 0 );
|
||||
rc = LDAP_SUCCESS;
|
||||
text = NULL;
|
||||
bdb_cache_entry_commit( e );
|
||||
}
|
||||
|
||||
return_results:
|
||||
|
|
@ -664,18 +681,18 @@ done:
|
|||
|
||||
/* LDAP v3 Support */
|
||||
if( np != NULL ) {
|
||||
/* free new parent and writer lock */
|
||||
bdb_entry_return( be, np );
|
||||
/* free new parent and reader lock */
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, np);
|
||||
}
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
bdb_entry_return( be, p );
|
||||
/* free parent and reader lock */
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, p);
|
||||
}
|
||||
|
||||
/* free entry */
|
||||
if( e != NULL ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_w( &bdb->bi_cache, e );
|
||||
}
|
||||
|
||||
if( ltid != NULL ) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ bdb_exop_passwd(
|
|||
|
||||
if( 0 ) {
|
||||
retry: /* transaction retry */
|
||||
if ( e != NULL ) {
|
||||
bdb_cache_delete_entry(&bdb->bi_cache, e);
|
||||
bdb_cache_return_entry_w(&bdb->bi_cache, e);
|
||||
}
|
||||
Debug( LDAP_DEBUG_TRACE, "bdb_exop_passwd: retrying...\n", 0, 0, 0 );
|
||||
rc = txn_abort( ltid );
|
||||
ltid = NULL;
|
||||
|
|
@ -119,7 +123,7 @@ retry: /* transaction retry */
|
|||
op->o_private = &opinfo;
|
||||
|
||||
/* get entry */
|
||||
rc = bdb_dn2entry( be, ltid, dn, &e, NULL, 0 );
|
||||
rc = bdb_dn2entry_w( be, ltid, dn, &e, NULL, 0 );
|
||||
|
||||
switch(rc) {
|
||||
case DB_LOCK_DEADLOCK:
|
||||
|
|
@ -174,8 +178,6 @@ retry: /* transaction retry */
|
|||
case DB_LOCK_DEADLOCK:
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
*text = NULL;
|
||||
bdb_entry_return( be, e );
|
||||
e = NULL;
|
||||
goto retry;
|
||||
case 0:
|
||||
break;
|
||||
|
|
@ -191,8 +193,6 @@ retry: /* transaction retry */
|
|||
switch(rc) {
|
||||
case DB_LOCK_DEADLOCK:
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
bdb_entry_return( be, e );
|
||||
e = NULL;
|
||||
goto retry;
|
||||
}
|
||||
*text = "entry update failed";
|
||||
|
|
@ -212,9 +212,9 @@ retry: /* transaction retry */
|
|||
|
||||
done:
|
||||
if( e != NULL ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_w( &bdb->bi_cache, e );
|
||||
}
|
||||
|
||||
|
||||
if( hash.bv_val != NULL ) {
|
||||
free( hash.bv_val );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,8 +57,10 @@ bdb_db_cache(
|
|||
/*
|
||||
* dn2entry.c
|
||||
*/
|
||||
int bdb_dn2entry LDAP_P(( BackendDB *be, DB_TXN *tid,
|
||||
struct berval *dn, Entry **e, Entry **matched, int flags ));
|
||||
int bdb_dn2entry_rw LDAP_P(( BackendDB *be, DB_TXN *tid,
|
||||
struct berval *dn, Entry **e, Entry **matched, int flags, int rw ));
|
||||
#define bdb_dn2entry_r(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0)
|
||||
#define bdb_dn2entry_w(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1)
|
||||
|
||||
/*
|
||||
* dn2id.c
|
||||
|
|
@ -103,7 +105,7 @@ bdb_dn2idl(
|
|||
/*
|
||||
* entry.c
|
||||
*/
|
||||
int bdb_entry_return( BackendDB *be, Entry *e );
|
||||
int bdb_entry_return( Entry *e );
|
||||
BI_entry_release_rw bdb_entry_release;
|
||||
|
||||
/*
|
||||
|
|
@ -127,7 +129,7 @@ int bdb_filter_candidates(
|
|||
BI_acl_group bdb_group;
|
||||
|
||||
/*
|
||||
* id2entry
|
||||
* id2entry.c
|
||||
*/
|
||||
int bdb_id2entry_add(
|
||||
BackendDB *be,
|
||||
|
|
@ -142,13 +144,18 @@ int bdb_id2entry_update(
|
|||
int bdb_id2entry_delete(
|
||||
BackendDB *be,
|
||||
DB_TXN *tid,
|
||||
ID id );
|
||||
Entry *e);
|
||||
|
||||
int bdb_id2entry(
|
||||
int bdb_id2entry_rw(
|
||||
BackendDB *be,
|
||||
DB_TXN *tid,
|
||||
ID id,
|
||||
Entry **e );
|
||||
Entry **e,
|
||||
int rw );
|
||||
#define bdb_id2entry_r(be, tid, id, e) bdb_id2entry_rw((be), (tid), (id), (e), 0)
|
||||
#define bdb_id2entry_w(be, tid, id, e) bdb_id2entry_rw((be), (tid), (id), (e), 1)
|
||||
|
||||
void bdb_entry_free ( Entry *e );
|
||||
|
||||
/*
|
||||
* idl.c
|
||||
|
|
@ -282,6 +289,40 @@ int bdb_modify_internal(
|
|||
*/
|
||||
BI_op_extended bdb_exop_passwd;
|
||||
|
||||
|
||||
/*
|
||||
* cache.c
|
||||
*/
|
||||
|
||||
void bdb_cache_entry_commit( Entry *e );
|
||||
void bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
|
||||
#define bdb_cache_return_entry_r(c, e) bdb_cache_return_entry_rw((c), (e), 0)
|
||||
#define bdb_cache_return_entry_w(c, e) bdb_cache_return_entry_rw((c), (e), 1)
|
||||
int bdb_cache_add_entry_rw(
|
||||
Cache *cache,
|
||||
Entry *e,
|
||||
int rw
|
||||
);
|
||||
int bdb_cache_update_entry(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
);
|
||||
ID bdb_cache_find_entry_ndn2id(
|
||||
Backend *be,
|
||||
Cache *cache,
|
||||
struct berval *ndn
|
||||
);
|
||||
Entry* bdb_cache_find_entry_id(
|
||||
Cache *cache,
|
||||
ID id,
|
||||
int rw
|
||||
);
|
||||
int bdb_cache_delete_entry(
|
||||
Cache *cache,
|
||||
Entry *e
|
||||
);
|
||||
void bdb_cache_release_all( Cache *cache );
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* _PROTO_BDB_H */
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ bdb_referrals(
|
|||
}
|
||||
|
||||
/* get entry */
|
||||
rc = bdb_dn2entry( be, NULL, ndn, &e, &matched, 0 );
|
||||
rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
|
||||
|
||||
switch(rc) {
|
||||
case DB_NOTFOUND:
|
||||
|
|
@ -47,6 +47,12 @@ bdb_referrals(
|
|||
Debug( LDAP_DEBUG_TRACE,
|
||||
"bdb_referrals: dn2entry failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
if (e != NULL) {
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, e);
|
||||
}
|
||||
if (matched != NULL) {
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, matched);
|
||||
}
|
||||
send_ldap_result( conn, op, rc=LDAP_OTHER,
|
||||
NULL, "internal error", NULL, NULL );
|
||||
return rc;
|
||||
|
|
@ -68,7 +74,7 @@ bdb_referrals(
|
|||
refs = get_entry_referrals( be, conn, op, matched );
|
||||
}
|
||||
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r (&bdb->bi_cache, matched);
|
||||
matched = NULL;
|
||||
} else if ( default_referral != NULL ) {
|
||||
rc = LDAP_OTHER;
|
||||
|
|
@ -113,6 +119,6 @@ bdb_referrals(
|
|||
ber_bvarray_free( refs );
|
||||
}
|
||||
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, e);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ bdb_search(
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
rc = bdb_dn2entry( be, NULL, nbase, &e, &matched, 0 );
|
||||
rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0 );
|
||||
}
|
||||
|
||||
switch(rc) {
|
||||
|
|
@ -86,6 +86,12 @@ bdb_search(
|
|||
case 0:
|
||||
break;
|
||||
default:
|
||||
if (e != NULL) {
|
||||
bdb_cache_return_entry_w(&bdb->bi_cache, e);
|
||||
}
|
||||
if (matched != NULL) {
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, matched);
|
||||
}
|
||||
send_ldap_result( conn, op, rc=LDAP_OTHER,
|
||||
NULL, "internal error", NULL, NULL );
|
||||
return rc;
|
||||
|
|
@ -104,7 +110,7 @@ bdb_search(
|
|||
? get_entry_referrals( be, conn, op, matched )
|
||||
: NULL;
|
||||
|
||||
bdb_entry_return( be, matched );
|
||||
bdb_cache_return_entry_r (&bdb->bi_cache, matched);
|
||||
matched = NULL;
|
||||
|
||||
if( erefs ) {
|
||||
|
|
@ -135,7 +141,7 @@ bdb_search(
|
|||
erefs = get_entry_referrals( be, conn, op, e );
|
||||
refs = NULL;
|
||||
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r( &bdb->bi_cache, e );
|
||||
e = NULL;
|
||||
|
||||
if( erefs ) {
|
||||
|
|
@ -245,7 +251,7 @@ bdb_search(
|
|||
cursor = e->e_id == NOID ? 1 : e->e_id;
|
||||
|
||||
if ( e != &slap_entry_root ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, e);
|
||||
}
|
||||
e = NULL;
|
||||
|
||||
|
|
@ -296,7 +302,7 @@ bdb_search(
|
|||
}
|
||||
|
||||
/* get the entry with reader lock */
|
||||
rc = bdb_id2entry( be, NULL, id, &e );
|
||||
rc = bdb_id2entry_r( be, NULL, id, &e );
|
||||
|
||||
if ( e == NULL ) {
|
||||
if( !BDB_IDL_IS_RANGE(candidates) ) {
|
||||
|
|
@ -418,7 +424,7 @@ bdb_search(
|
|||
if ( scopeok ) {
|
||||
/* check size limit */
|
||||
if ( --slimit == -1 ) {
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r (&bdb->bi_cache, e);
|
||||
e = NULL;
|
||||
send_search_result( conn, op,
|
||||
rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
|
||||
|
|
@ -437,7 +443,7 @@ bdb_search(
|
|||
case 1: /* entry not sent */
|
||||
break;
|
||||
case -1: /* connection closed */
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r(&bdb->bi_cache, e);
|
||||
e = NULL;
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
|
|
@ -457,7 +463,8 @@ bdb_search(
|
|||
loop_continue:
|
||||
if( e != NULL ) {
|
||||
/* free reader lock */
|
||||
bdb_entry_return( be, e );
|
||||
bdb_cache_return_entry_r ( &bdb->bi_cache, e );
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
|
|
@ -469,6 +476,11 @@ loop_continue:
|
|||
rc = 0;
|
||||
|
||||
done:
|
||||
if( e != NULL ) {
|
||||
/* free reader lock */
|
||||
bdb_cache_return_entry_r ( &bdb->bi_cache, e );
|
||||
}
|
||||
|
||||
if( v2refs ) ber_bvarray_free( v2refs );
|
||||
if( realbase.bv_val ) ch_free( realbase.bv_val );
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue