/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2000-2009 The OpenLDAP Foundation.
+ * Copyright 2000-2011 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
cache->c_eifree = ei;
ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex );
#else
+ ldap_pvt_thread_mutex_destroy( &ei->bei_kids_mutex );
ch_free( ei );
#endif
}
#define LRU_DEL( c, e ) do { \
- if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \
- if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \
- e->bei_lrunext->bei_lruprev = e->bei_lruprev; \
- e->bei_lruprev->bei_lrunext = e->bei_lrunext; \
+ if ( e == e->bei_lruprev ) { \
+ (c)->c_lruhead = (c)->c_lrutail = NULL; \
+ } else { \
+ if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \
+ if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \
+ e->bei_lrunext->bei_lruprev = e->bei_lruprev; \
+ e->bei_lruprev->bei_lrunext = e->bei_lrunext; \
+ } \
e->bei_lruprev = NULL; \
} while ( 0 )
if ( !lock ) return 0;
+ DBTzero( &lockobj );
lockobj.data = &ei->bei_id;
lockobj.size = sizeof(ei->bei_id) + 1;
else
db_rw = DB_LOCK_READ;
+ DBTzero( &lockobj );
lockobj.data = &ei->bei_id;
lockobj.size = sizeof(ei->bei_id) + 1;
int free = 0;
ei = e->e_private;
- if ( ei &&
- ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) &&
- ( bdb_cache_entryinfo_trylock( ei ) == 0 )) {
+ if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) {
+ bdb_cache_entryinfo_lock( ei );
if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) {
/* Releasing the entry can only be done when
* we know that nobody else is using it, i.e we
ei.bei_parent = eip;
ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
if ( !ei2 ) {
- DB_LOCK lock;
+ DBC *cursor;
int len = ei.bei_nrdn.bv_len;
if ( BER_BVISEMPTY( ndn )) {
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s",
ei.bei_nrdn.bv_val );
- lock.mode = DB_LOCK_NG;
- rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &lock );
+ cursor = NULL;
+ rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor );
if (rc) {
bdb_cache_entryinfo_lock( eip );
eip->bei_finders--;
- bdb_cache_entry_db_unlock( bdb, &lock );
+ if ( cursor ) cursor->c_close( cursor );
*res = eip;
return rc;
}
/* add_internal left eip and c_rwlock locked */
eip->bei_finders--;
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
- bdb_cache_entry_db_unlock( bdb, &lock );
+ if ( cursor ) cursor->c_close( cursor );
if ( rc ) {
*res = eip;
return rc;
}
- } else if ( ei2->bei_state & CACHE_ENTRY_DELETED ) {
+ }
+ bdb_cache_entryinfo_lock( ei2 );
+ if ( ei2->bei_state & CACHE_ENTRY_DELETED ) {
/* In the midst of deleting? Give it a chance to
* complete.
*/
+ bdb_cache_entryinfo_unlock( ei2 );
bdb_cache_entryinfo_unlock( eip );
ldap_pvt_thread_yield();
bdb_cache_entryinfo_lock( eip );
*res = eip;
return DB_NOTFOUND;
}
- bdb_cache_entryinfo_lock( ei2 );
bdb_cache_entryinfo_unlock( eip );
eip = ei2;
if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) {
load = 1;
(*eip)->bei_state |= CACHE_ENTRY_LOADING;
+ flag |= ID_CHKPURGE;
}
if ( !load ) {
* another thread is currently loading it.
*/
if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) {
- (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED;
+ (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED;
+ flag |= ID_CHKPURGE;
}
- flag &= ~ID_NOCACHE;
}
if ( flag & ID_LOCKED ) {
ldap_pvt_thread_yield();
bdb_fix_dn( ep, 0 );
#endif
+ bdb_cache_entryinfo_lock( *eip );
+
(*eip)->bei_e = ep;
#ifdef SLAP_ZONE_ALLOC
(*eip)->bei_zseq = *((ber_len_t *)ep - 2);
#endif
ep = NULL;
- bdb_cache_lru_link( bdb, *eip );
- if (( flag & ID_NOCACHE ) &&
- ( bdb_cache_entryinfo_trylock( *eip ) == 0 )) {
+ if ( flag & ID_NOCACHE ) {
/* Set the cached state only if no other thread
* found the info while we were loading the entry.
*/
- if ( (*eip)->bei_finders == 1 )
+ if ( (*eip)->bei_finders == 1 ) {
(*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
- bdb_cache_entryinfo_unlock( *eip );
+ flag ^= ID_CHKPURGE;
+ }
}
+ bdb_cache_entryinfo_unlock( *eip );
+ bdb_cache_lru_link( bdb, *eip );
}
if ( rc == 0 ) {
/* If we succeeded, downgrade back to a readlock. */
if ( rc == 0 ) {
int purge = 0;
- if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ||
- ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax )) {
+ if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) {
ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
- if ( !bdb->bi_cache.c_purging ) {
- if ( load && !( flag & ID_NOCACHE )) {
- bdb->bi_cache.c_cursize++;
- if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
- purge = 1;
- bdb->bi_cache.c_purging = 1;
- }
- } else if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
+ if ( flag & ID_CHKPURGE ) {
+ bdb->bi_cache.c_cursize++;
+ if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) {
purge = 1;
bdb->bi_cache.c_purging = 1;
}
+ } else if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
+ purge = 1;
+ bdb->bi_cache.c_purging = 1;
}
ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
}
ei.bei_nrdn = *nrdn;
ei.bei_lockpad = 0;
+#if 0
/* Lock this entry so that bdb_add can run to completion.
* It can only fail if BDB has run out of lock resources.
*/
bdb_cache_entryinfo_unlock( eip );
return rc;
}
+#endif
#ifdef BDB_HIER
if ( nrdn->bv_len != e->e_nname.bv_len ) {
}
ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
+ new->bei_finders = 1;
bdb_cache_lru_link( bdb, new );
if ( purge )
return rc;
}
+void bdb_cache_deref(
+ EntryInfo *ei
+ )
+{
+ bdb_cache_entryinfo_lock( ei );
+ ei->bei_finders--;
+ bdb_cache_entryinfo_unlock( ei );
+}
+
int
bdb_cache_modify(
struct bdb_info *bdb,
}
#ifdef LDAP_DEBUG
+static void
+bdb_lru_count( Cache *cache )
+{
+ EntryInfo *e;
+ int ei = 0, ent = 0, nc = 0;
+
+ for ( e = cache->c_lrutail; ; ) {
+ ei++;
+ if ( e->bei_e ) {
+ ent++;
+ if ( e->bei_state & CACHE_ENTRY_NOT_CACHED )
+ nc++;
+ fprintf( stderr, "ei %d entry %p dn %s\n", ei, (void *) e->bei_e, e->bei_e->e_name.bv_val );
+ }
+ e = e->bei_lrunext;
+ if ( e == cache->c_lrutail )
+ break;
+ }
+ fprintf( stderr, "counted %d entryInfos and %d entries, %d notcached\n",
+ ei, ent, nc );
+ ei = 0;
+ for ( e = cache->c_lrutail; ; ) {
+ ei++;
+ e = e->bei_lruprev;
+ if ( e == cache->c_lrutail )
+ break;
+ }
+ fprintf( stderr, "counted %d entryInfos (on lruprev)\n", ei );
+}
+
#ifdef SLAPD_UNUSED
static void
bdb_lru_print( Cache *cache )