Move LDBM-backend specific fields of Entry struct into a private struct.

The new e_private field can be used for any backend purpose.  In LDBM,
it's used to point th the private entry info struct.  The LDBM entry
info struct is only visible to the LDBM cache.
WARNING: This change has not be ported to other backends!  Breakage is likely.
This commit is contained in:
Kurt Zeilenga 1999-02-10 18:28:25 +00:00
parent 529caeddd0
commit 88c43a1e6e
12 changed files with 323 additions and 207 deletions

View File

@ -54,11 +54,11 @@ do_add( Connection *conn, Operation *op )
} }
e = (Entry *) ch_calloc( 1, sizeof(Entry) ); e = (Entry *) ch_calloc( 1, sizeof(Entry) );
/* initialize reader/writer lock */
entry_rdwr_init(e);
e->e_dn = dn; e->e_dn = dn;
e->e_ndn = dn_normalize_case( ch_strdup( dn ) ); e->e_ndn = dn_normalize_case( ch_strdup( dn ) );
e->e_private = NULL;
dn = NULL; dn = NULL;
Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 ); Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 );

View File

@ -23,7 +23,7 @@ ldbm_back_add(
char *pdn; char *pdn;
Entry *p = NULL; Entry *p = NULL;
int rootlock = 0; int rootlock = 0;
int rc = -1; int rc;
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0); Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
@ -121,39 +121,19 @@ ldbm_back_add(
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
} }
/* acquire required reader/writer lock */
if (entry_rdwr_lock(e, 1)) {
if( p != NULL) {
/* free parent and writer lock */
cache_return_entry_w( &li->li_cache, p );
}
if ( rootlock ) {
/* release root lock */
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
}
Debug( LDAP_DEBUG_ANY, "add: could not lock entry\n",
0, 0, 0 );
entry_free(e);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
return( -1 );
}
e->e_id = next_id( be ); e->e_id = next_id( be );
/* /*
* Try to add the entry to the cache, assign it a new dnid. * Try to add the entry to the cache, assign it a new dnid.
* This should only fail if the entry already exists.
*/ */
rc = cache_add_entry_rw(&li->li_cache, e, ENTRY_STATE_CREATING, 1);
if ( cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING ) != 0 ) { if ( rc != 0 ) {
if( p != NULL) { if( p != NULL) {
/* free parent and writer lock */ /* free parent and writer lock */
cache_return_entry_w( &li->li_cache, p ); cache_return_entry_w( &li->li_cache, p );
} }
if ( rootlock ) { if ( rootlock ) {
/* release root lock */ /* release root lock */
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex); ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
@ -161,15 +141,24 @@ ldbm_back_add(
Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0, Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
0 ); 0 );
/* return the id */
next_id_return( be, e->e_id ); next_id_return( be, e->e_id );
entry_rdwr_unlock(e, 1); /* free the entry */
entry_free( e ); entry_free( e );
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" ); if(rc > 0) {
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
} else {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
}
return( -1 ); return( -1 );
} }
rc = -1;
/* /*
* add it to the id2children index for the parent * add it to the id2children index for the parent
*/ */

View File

@ -79,6 +79,9 @@ struct cache {
ldap_pvt_thread_mutex_t c_mutex; ldap_pvt_thread_mutex_t c_mutex;
}; };
#define ENTRY_STATE_DELETED 1
#define ENTRY_STATE_CREATING 2
/* for the cache of open index files */ /* for the cache of open index files */
struct dbcache { struct dbcache {
int dbc_refcnt; int dbc_refcnt;

View File

@ -12,6 +12,23 @@
#include "back-ldbm.h" #include "back-ldbm.h"
/* LDBM backend specific entry info -- visible only to the cache */
struct ldbm_entry_info {
ldap_pvt_thread_rdwr_t lei_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 lei_state; /* for the cache */
int lei_refcnt; /* # threads ref'ing this entry */
struct entry *lei_lrunext; /* for cache lru list */
struct entry *lei_lruprev;
};
#define LEI(e) ((struct ldbm_entry_info *) ((e)->e_private))
static int cache_delete_entry_internal(struct cache *cache, Entry *e); static int cache_delete_entry_internal(struct cache *cache, Entry *e);
#ifdef LDAP_DEBUG #ifdef LDAP_DEBUG
static void lru_print(struct cache *cache); static void lru_print(struct cache *cache);
@ -53,27 +70,94 @@ cache_set_state( struct cache *cache, Entry *e, int state )
/* set cache mutex */ /* set cache mutex */
ldap_pvt_thread_mutex_lock( &cache->c_mutex ); ldap_pvt_thread_mutex_lock( &cache->c_mutex );
e->e_state = state; LEI(e)->lei_state = state;
/* free cache mutex */ /* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
} }
#ifdef not_used static int
static void cache_entry_rdwr_lock(Entry *e, int rw)
cache_return_entry( struct cache *cache, Entry *e )
{ {
/* set cache mutex */ Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
ldap_pvt_thread_mutex_lock( &cache->c_mutex ); rw ? "w" : "r", e->e_id, 0);
if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) { if (rw)
entry_free( e ); return ldap_pvt_thread_rdwr_wlock(&LEI(e)->lei_rdwr);
else
return ldap_pvt_thread_rdwr_rlock(&LEI(e)->lei_rdwr);
}
static int
cache_entry_rdwr_trylock(Entry *e, int rw)
{
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n",
rw ? "w" : "r", e->e_id, 0);
if (rw)
return ldap_pvt_thread_rdwr_wtrylock(&LEI(e)->lei_rdwr);
else
return ldap_pvt_thread_rdwr_rtrylock(&LEI(e)->lei_rdwr);
}
static int
cache_entry_rdwr_unlock(Entry *e, int rw)
{
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n",
rw ? "w" : "r", e->e_id, 0);
if (rw)
return ldap_pvt_thread_rdwr_wunlock(&LEI(e)->lei_rdwr);
else
return ldap_pvt_thread_rdwr_runlock(&LEI(e)->lei_rdwr);
}
static int
cache_entry_rdwr_init(Entry *e)
{
return ldap_pvt_thread_rdwr_init( &LEI(e)->lei_rdwr );
}
static int
cache_entry_rdwr_destroy(Entry *e)
{
return ldap_pvt_thread_rdwr_destroy( &LEI(e)->lei_rdwr );
}
static int
cache_entry_private_init( Entry*e )
{
struct ldbm_entry_info *lei;
if( e->e_private != NULL ) {
return 1;
} }
/* free cache mutex */ e->e_private = ch_calloc(1, sizeof(struct ldbm_entry_info));
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
if( cache_entry_rdwr_init( e ) != 0 ) {
free( LEI(e) );
return 1;
}
return 0;
}
static int
cache_entry_private_destroy( Entry*e )
{
struct ldbm_entry_info *lei;
if( e->e_private == NULL ) {
return 1;
}
cache_entry_rdwr_destroy( e );
free( e->e_private );
e->e_private = NULL;
return 0;
} }
#endif
static void static void
cache_return_entry_rw( struct cache *cache, Entry *e, int rw ) cache_return_entry_rw( struct cache *cache, Entry *e, int rw )
@ -84,9 +168,12 @@ cache_return_entry_rw( struct cache *cache, Entry *e, int rw )
/* set cache mutex */ /* set cache mutex */
ldap_pvt_thread_mutex_lock( &cache->c_mutex ); ldap_pvt_thread_mutex_lock( &cache->c_mutex );
entry_rdwr_unlock(e, rw); cache_entry_rdwr_unlock(e, rw);
if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) { if ( --LEI(e)->lei_refcnt == 0 &&
LEI(e)->lei_state == ENTRY_STATE_DELETED )
{
cache_entry_private_destroy( e );
entry_free( e ); entry_free( e );
} }
@ -108,41 +195,42 @@ cache_return_entry_w( struct cache *cache, Entry *e )
#define LRU_DELETE( cache, e ) { \ #define LRU_DELETE( cache, e ) { \
if ( e->e_lruprev != NULL ) { \ if ( LEI(e)->lei_lruprev != NULL ) { \
e->e_lruprev->e_lrunext = e->e_lrunext; \ LEI(LEI(e)->lei_lruprev)->lei_lrunext = LEI(e)->lei_lrunext; \
} else { \ } else { \
cache->c_lruhead = e->e_lrunext; \ cache->c_lruhead = LEI(e)->lei_lrunext; \
} \ } \
if ( e->e_lrunext != NULL ) { \ if ( LEI(e)->lei_lrunext != NULL ) { \
e->e_lrunext->e_lruprev = e->e_lruprev; \ LEI(LEI(e)->lei_lrunext)->lei_lruprev = LEI(e)->lei_lruprev; \
} else { \ } else { \
cache->c_lrutail = e->e_lruprev; \ cache->c_lrutail = LEI(e)->lei_lruprev; \
} \ } \
} }
#define LRU_ADD( cache, e ) { \ #define LRU_ADD( cache, e ) { \
e->e_lrunext = cache->c_lruhead; \ LEI(e)->lei_lrunext = cache->c_lruhead; \
if ( e->e_lrunext != NULL ) { \ if ( LEI(e)->lei_lrunext != NULL ) { \
e->e_lrunext->e_lruprev = e; \ LEI(LEI(e)->lei_lrunext)->lei_lruprev = e; \
} \ } \
cache->c_lruhead = e; \ cache->c_lruhead = e; \
e->e_lruprev = NULL; \ LEI(e)->lei_lruprev = NULL; \
if ( cache->c_lrutail == NULL ) { \ if ( cache->c_lrutail == NULL ) { \
cache->c_lrutail = e; \ cache->c_lrutail = e; \
} \ } \
} }
/* /*
* cache_create_entry_lock - create an entry in the cache, and lock it. * cache_add_entry_rw - create and lock an entry in the cache
* returns: 0 entry has been created and locked * returns: 0 entry has been created and locked
* 1 entry already existed * 1 entry already existed
* -1 something bad happened * -1 something bad happened
*/ */
int int
cache_add_entry_lock( cache_add_entry_rw(
struct cache *cache, struct cache *cache,
Entry *e, Entry *e,
int state int state,
int rw
) )
{ {
int i, rc; int i, rc;
@ -151,11 +239,134 @@ cache_add_entry_lock(
/* set cache mutex */ /* set cache mutex */
ldap_pvt_thread_mutex_lock( &cache->c_mutex ); ldap_pvt_thread_mutex_lock( &cache->c_mutex );
if ( e->e_private != NULL ) {
Debug( LDAP_DEBUG_ANY,
"====> cache_add_entry: entry %20s id %lu already cached.\n",
e->e_dn, e->e_id, 0 );
return( -1 );
}
if( cache_entry_private_init(e) != 0 ) {
Debug( LDAP_DEBUG_ANY,
"====> cache_add_entry: entry %20s id %lu: private init failed!\n",
e->e_dn, e->e_id, 0 );
return( -1 );
}
if ( avl_insert( &cache->c_dntree, (caddr_t) e, if ( avl_insert( &cache->c_dntree, (caddr_t) e,
cache_entrydn_cmp, avl_dup_error ) != 0 ) cache_entrydn_cmp, avl_dup_error ) != 0 )
{ {
Debug( LDAP_DEBUG_TRACE, Debug( LDAP_DEBUG_TRACE,
"====> cache_add_entry lock: entry %20s id %lu already in dn cache\n", "====> cache_add_entry: entry %20s id %lu already in dn cache\n",
e->e_dn, e->e_id, 0 );
cache_entry_private_destroy(e);
/* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
return( 1 );
}
/* id tree */
if ( avl_insert( &cache->c_idtree, (caddr_t) e,
cache_entryid_cmp, avl_dup_error ) != 0 )
{
Debug( LDAP_DEBUG_ANY,
"====> entry %20s id %lu already in id cache\n",
e->e_dn, e->e_id, 0 );
/* delete from dn tree inserted above */
if ( avl_delete( &cache->c_dntree, (caddr_t) e,
cache_entrydn_cmp ) == NULL )
{
Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
0, 0, 0 );
}
cache_entry_private_destroy(e);
/* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
return( -1 );
}
cache_entry_rdwr_lock( e, rw );
LEI(e)->lei_state = state;
LEI(e)->lei_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 &&
LEI(cache->c_lrutail)->lei_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 &&
LEI(cache->c_lrutail)->lei_refcnt == 0 &&
cache->c_cursize > cache->c_maxsize )
{
e = cache->c_lrutail;
/* delete from cache and lru q */
rc = cache_delete_entry_internal( cache, e );
entry_free( 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
cache_update_entry(
struct cache *cache,
Entry *e
)
{
int i, rc;
Entry *ee;
/* set cache mutex */
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
if ( e->e_private == NULL ) {
Debug( LDAP_DEBUG_ANY,
"====> cache_update_entry: entry %20s id %lu no private data.\n",
e->e_dn, e->e_id, 0 );
return( -1 );
}
if ( avl_insert( &cache->c_dntree, (caddr_t) e,
cache_entrydn_cmp, avl_dup_error ) != 0 )
{
Debug( LDAP_DEBUG_TRACE,
"====> cache_add_entry: entry %20s id %lu already in dn cache\n",
e->e_dn, e->e_id, 0 ); e->e_dn, e->e_id, 0 );
/* free cache mutex */ /* free cache mutex */
@ -184,9 +395,6 @@ cache_add_entry_lock(
return( -1 ); return( -1 );
} }
e->e_state = state;
e->e_refcnt = 1;
/* lru */ /* lru */
LRU_ADD( cache, e ); LRU_ADD( cache, e );
if ( ++cache->c_cursize > cache->c_maxsize ) { if ( ++cache->c_cursize > cache->c_maxsize ) {
@ -196,8 +404,10 @@ cache_add_entry_lock(
* first 10 on the tail of the list. * first 10 on the tail of the list.
*/ */
i = 0; i = 0;
while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt while ( cache->c_lrutail != NULL &&
!= 0 && i < 10 ) { LEI(cache->c_lrutail)->lei_refcnt != 0 &&
i < 10 )
{
/* move this in-use entry to the front of the q */ /* move this in-use entry to the front of the q */
ee = cache->c_lrutail; ee = cache->c_lrutail;
LRU_DELETE( cache, ee ); LRU_DELETE( cache, ee );
@ -209,15 +419,12 @@ cache_add_entry_lock(
* found at least one to delete - try to get back under * found at least one to delete - try to get back under
* the max cache size. * the max cache size.
*/ */
while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt while ( cache->c_lrutail != NULL &&
== 0 && cache->c_cursize > cache->c_maxsize ) { LEI(cache->c_lrutail)->lei_refcnt == 0 &&
cache->c_cursize > cache->c_maxsize )
{
e = cache->c_lrutail; e = cache->c_lrutail;
/* check for active readers/writer lock */
#ifdef LDAP_DEBUG
assert(!ldap_pvt_thread_rdwr_active( &e->e_rdwr ));
#endif
/* delete from cache and lru q */ /* delete from cache and lru q */
rc = cache_delete_entry_internal( cache, e ); rc = cache_delete_entry_internal( cache, e );
@ -267,8 +474,8 @@ cache_find_entry_dn2id(
/* /*
* entry is deleted or not fully created yet * entry is deleted or not fully created yet
*/ */
if ( ep->e_state == ENTRY_STATE_DELETED || if ( LEI(ep)->lei_state == ENTRY_STATE_DELETED ||
ep->e_state == ENTRY_STATE_CREATING ) LEI(ep)->lei_state == ENTRY_STATE_CREATING )
{ {
/* free cache mutex */ /* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
@ -326,8 +533,8 @@ try_again:
/* /*
* entry is deleted or not fully created yet * entry is deleted or not fully created yet
*/ */
if ( ep->e_state == ENTRY_STATE_DELETED || if ( LEI(ep)->lei_state == ENTRY_STATE_DELETED ||
ep->e_state == ENTRY_STATE_CREATING ) LEI(ep)->lei_state == ENTRY_STATE_CREATING )
{ {
/* free cache mutex */ /* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
@ -335,7 +542,7 @@ try_again:
} }
/* acquire reader lock */ /* acquire reader lock */
if ( entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) { if ( cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
/* could not acquire entry lock... /* could not acquire entry lock...
* owner cannot free as we have the cache locked. * owner cannot free as we have the cache locked.
* so, unlock the cache, yield, and try again. * so, unlock the cache, yield, and try again.
@ -351,7 +558,7 @@ try_again:
LRU_DELETE( cache, ep ); LRU_DELETE( cache, ep );
LRU_ADD( cache, ep ); LRU_ADD( cache, ep );
ep->e_refcnt++; LEI(ep)->lei_refcnt++;
/* free cache mutex */ /* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
@ -389,11 +596,6 @@ cache_delete_entry(
/* set cache mutex */ /* set cache mutex */
ldap_pvt_thread_mutex_lock( &cache->c_mutex ); ldap_pvt_thread_mutex_lock( &cache->c_mutex );
/* XXX check for writer lock - should also check no readers pending */
#ifdef LDAP_DEBUG
assert(ldap_pvt_thread_rdwr_writers( &e->e_rdwr ) == 1);
#endif
rc = cache_delete_entry_internal( cache, e ); rc = cache_delete_entry_internal( cache, e );
/* free cache mutex */ /* free cache mutex */
@ -434,7 +636,7 @@ cache_delete_entry_internal(
/* /*
* flag entry to be freed later by a call to cache_return_entry() * flag entry to be freed later by a call to cache_return_entry()
*/ */
e->e_state = ENTRY_STATE_DELETED; LEI(e)->lei_state = ENTRY_STATE_DELETED;
return( 0 ); return( 0 );
} }
@ -447,14 +649,14 @@ lru_print( struct cache *cache )
Entry *e; Entry *e;
fprintf( stderr, "LRU queue (head to tail):\n" ); fprintf( stderr, "LRU queue (head to tail):\n" );
for ( e = cache->c_lruhead; e != NULL; e = e->e_lrunext ) { for ( e = cache->c_lruhead; e != NULL; e = LEI(e)->lei_lrunext ) {
fprintf( stderr, "\tdn %20s id %lu refcnt %d\n", e->e_dn, fprintf( stderr, "\tdn %20s id %lu refcnt %d\n", e->e_dn,
e->e_id, e->e_refcnt ); e->e_id, LEI(e)->lei_refcnt );
} }
fprintf( stderr, "LRU queue (tail to head):\n" ); fprintf( stderr, "LRU queue (tail to head):\n" );
for ( e = cache->c_lrutail; e != NULL; e = e->e_lruprev ) { for ( e = cache->c_lrutail; e != NULL; e = LEI(e)->lei_lruprev ) {
fprintf( stderr, "\tdn %20s id %lu refcnt %d\n", e->e_dn, fprintf( stderr, "\tdn %20s id %lu refcnt %d\n", e->e_dn,
e->e_id, e->e_refcnt ); e->e_id, LEI(e)->lei_refcnt );
} }
} }

View File

@ -154,7 +154,7 @@ dn2id_delete(
*/ */
static Entry * static Entry *
dn2entry( dn2entry_rw(
Backend *be, Backend *be,
char *dn, char *dn,
char **matched, char **matched,
@ -172,7 +172,7 @@ dn2entry(
*matched = NULL; *matched = NULL;
if ( (id = dn2id( be, dn )) != NOID && if ( (id = dn2id( be, dn )) != NOID &&
(e = id2entry( be, id, rw )) != NULL ) (e = id2entry_rw( be, id, rw )) != NULL )
{ {
return( e ); return( e );
} }
@ -215,7 +215,7 @@ dn2entry_r(
char **matched char **matched
) )
{ {
return( dn2entry( be, dn, matched, 0 ) ); return( dn2entry_rw( be, dn, matched, 0 ) );
} }
Entry * Entry *
@ -225,7 +225,7 @@ dn2entry_w(
char **matched char **matched
) )
{ {
return( dn2entry( be, dn, matched, 1 ) ); return( dn2entry_rw( be, dn, matched, 1 ) );
} }

View File

@ -9,6 +9,11 @@
#include "slap.h" #include "slap.h"
#include "back-ldbm.h" #include "back-ldbm.h"
/*
* This routine adds (or updates) an entry on disk.
* The cache should already be updated.
*/
int int
id2entry_add( Backend *be, Entry *e ) id2entry_add( Backend *be, Entry *e )
{ {
@ -45,11 +50,12 @@ id2entry_add( Backend *be, Entry *e )
ldap_pvt_thread_mutex_unlock( &entry2str_mutex ); ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
ldbm_cache_close( be, db ); ldbm_cache_close( be, db );
(void) cache_add_entry_lock( &li->li_cache, e, 0 );
/* XXX entry should have already been added to the cache */
/* (void) cache_add_entry_rw( &li->li_cache, e, 0 ); */
Debug( LDAP_DEBUG_TRACE, "<= id2entry_add %d\n", rc, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "<= id2entry_add %d\n", rc, 0, 0 );
/* XXX should entries be born locked, i.e. apply writer lock here? */
return( rc ); return( rc );
} }
@ -64,9 +70,11 @@ id2entry_delete( Backend *be, Entry *e )
Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %lu, \"%s\" )\n", e->e_id, Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %lu, \"%s\" )\n", e->e_id,
e->e_dn, 0 ); e->e_dn, 0 );
#ifdef notdef
#ifdef LDAP_DEBUG #ifdef LDAP_DEBUG
/* check for writer lock */ /* check for writer lock */
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1); assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
#endif
#endif #endif
ldbm_datum_init( key ); ldbm_datum_init( key );
@ -96,7 +104,7 @@ id2entry_delete( Backend *be, Entry *e )
/* XXX returns entry with reader/writer lock */ /* XXX returns entry with reader/writer lock */
Entry * Entry *
id2entry( Backend *be, ID id, int rw ) id2entry_rw( Backend *be, ID id, int rw )
{ {
struct ldbminfo *li = (struct ldbminfo *) be->be_private; struct ldbminfo *li = (struct ldbminfo *) be->be_private;
struct dbcache *db; struct dbcache *db;
@ -145,15 +153,12 @@ id2entry( Backend *be, ID id, int rw )
return( NULL ); return( NULL );
} }
/* acquire required reader/writer lock */
if (entry_rdwr_lock(e, rw)) {
/* XXX set DELETE flag?? */
entry_free(e);
return(NULL);
}
e->e_id = id; e->e_id = id;
(void) cache_add_entry_lock( &li->li_cache, e, 0 );
if( cache_add_entry_rw( &li->li_cache, e, 0, rw ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (cache add failed)\n",
rw ? "w" : "r", id, 0 );
}
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (disk)\n", Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (disk)\n",
rw ? "w" : "r", id, 0 ); rw ? "w" : "r", id, 0 );
@ -163,12 +168,12 @@ id2entry( Backend *be, ID id, int rw )
Entry * Entry *
id2entry_r( Backend *be, ID id ) id2entry_r( Backend *be, ID id )
{ {
return( id2entry( be, id, 0 ) ); return( id2entry_rw( be, id, 0 ) );
} }
Entry * Entry *
id2entry_w( Backend *be, ID id ) id2entry_w( Backend *be, ID id )
{ {
return( id2entry( be, id, 1 ) ); return( id2entry_rw( be, id, 1 ) );
} }

View File

@ -146,7 +146,9 @@ ldbm_back_modrdn(
e->e_dn = new_dn; e->e_dn = new_dn;
e->e_ndn = new_ndn; e->e_ndn = new_ndn;
/* XXX (void) cache_update_entry( &li->li_cache, e );
/*
* At some point here we need to update the attribute values in * At some point here we need to update the attribute values in
* the entry itself that were effected by this RDN change * the entry itself that were effected by this RDN change
* (respecting the value of the deleteoldrdn parameter). * (respecting the value of the deleteoldrdn parameter).

View File

@ -37,7 +37,9 @@ void attr_index_config LDAP_P(( struct ldbminfo *li, char *fname, int lineno,
void cache_set_state LDAP_P(( struct cache *cache, Entry *e, int state )); void cache_set_state LDAP_P(( struct cache *cache, Entry *e, int state ));
void cache_return_entry_r LDAP_P(( struct cache *cache, Entry *e )); void cache_return_entry_r LDAP_P(( struct cache *cache, Entry *e ));
void cache_return_entry_w LDAP_P(( struct cache *cache, Entry *e )); void cache_return_entry_w LDAP_P(( struct cache *cache, Entry *e ));
int cache_add_entry_lock LDAP_P(( struct cache *cache, Entry *e, int state )); int cache_add_entry_rw LDAP_P(( struct cache *cache, Entry *e,
int state, int rw ));
int cache_update_entry LDAP_P(( struct cache *cache, Entry *e ));
ID cache_find_entry_dn2id LDAP_P(( Backend *be, struct cache *cache, char *dn )); ID cache_find_entry_dn2id LDAP_P(( Backend *be, struct cache *cache, char *dn ));
Entry * cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw )); Entry * cache_find_entry_id LDAP_P(( struct cache *cache, ID id, int rw ));
int cache_delete_entry LDAP_P(( struct cache *cache, Entry *e )); int cache_delete_entry LDAP_P(( struct cache *cache, Entry *e ));
@ -85,7 +87,7 @@ int has_children LDAP_P(( Backend *be, Entry *p ));
int id2entry_add LDAP_P(( Backend *be, Entry *e )); int id2entry_add LDAP_P(( Backend *be, Entry *e ));
int id2entry_delete LDAP_P(( Backend *be, Entry *e )); int id2entry_delete LDAP_P(( Backend *be, Entry *e ));
Entry * id2entry LDAP_P(( Backend *be, ID id, int rw )); Entry * id2entry_rw LDAP_P(( Backend *be, ID id, int rw ));
Entry * id2entry_r LDAP_P(( Backend *be, ID id )); Entry * id2entry_r LDAP_P(( Backend *be, ID id ));
Entry * id2entry_w LDAP_P(( Backend *be, ID id )); Entry * id2entry_w LDAP_P(( Backend *be, ID id ));

View File

@ -39,11 +39,10 @@ config_info( Connection *conn, Operation *op )
vals[1] = NULL; vals[1] = NULL;
e = (Entry *) ch_calloc( 1, sizeof(Entry) ); e = (Entry *) ch_calloc( 1, sizeof(Entry) );
/* initialize reader/writer lock */
entry_rdwr_init(e);
e->e_attrs = NULL; e->e_attrs = NULL;
e->e_dn = ch_strdup( SLAPD_CONFIG_DN ); e->e_dn = ch_strdup( SLAPD_CONFIG_DN );
e->e_private = NULL;
for ( i = 0; i < nbackends; i++ ) { for ( i = 0; i < nbackends; i++ ) {
strcpy( buf, backends[i].be_type ); strcpy( buf, backends[i].be_type );

View File

@ -68,9 +68,9 @@ str2entry( char *s )
0, 0, 0 ); 0, 0, 0 );
return( NULL ); return( NULL );
} }
e->e_id = id;
entry_rdwr_init(e); e->e_id = id;
e->e_private = NULL;
/* dn + attributes */ /* dn + attributes */
e->e_attrs = NULL; e->e_attrs = NULL;
@ -142,7 +142,8 @@ str2entry( char *s )
return( NULL ); return( NULL );
} }
Debug(LDAP_DEBUG_TRACE, "<= str2entry 0x%lx\n", (unsigned long)e, 0,0); Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> %lu (0x%lx)\n",
e->e_dn, e->e_id, (unsigned long)e );
return( e ); return( e );
} }
@ -219,93 +220,20 @@ entry_free( Entry *e )
int i; int i;
Attribute *a, *next; Attribute *a, *next;
/* check that no reader/writer locks exist */
if ( ldap_pvt_thread_rdwr_wtrylock( &e->e_rdwr ) ==
LDAP_PVT_THREAD_EBUSY )
{
Debug( LDAP_DEBUG_ANY, "entry_free(%ld): active (%d, %d)\n",
e->e_id,
ldap_pvt_thread_rdwr_readers( &e->e_rdwr ),
ldap_pvt_thread_rdwr_writers( &e->e_rdwr ));
#ifdef LDAP_DEBUG
assert(!ldap_pvt_thread_rdwr_active( &e->e_rdwr ));
#endif
}
if ( e->e_dn != NULL ) { if ( e->e_dn != NULL ) {
free( e->e_dn ); free( e->e_dn );
e->e_dn = NULL;
} }
if ( e->e_ndn != NULL ) { if ( e->e_ndn != NULL ) {
free( e->e_ndn ); free( e->e_ndn );
e->e_ndn = NULL;
} }
for ( a = e->e_attrs; a != NULL; a = next ) { for ( a = e->e_attrs; a != NULL; a = next ) {
next = a->a_next; next = a->a_next;
attr_free( a ); attr_free( a );
} }
e->e_attrs = NULL;
e->e_private = NULL;
free( e ); free( e );
} }
int
entry_rdwr_lock(Entry *e, int rw)
{
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
rw ? "w" : "r", e->e_id, 0);
if (rw)
return ldap_pvt_thread_rdwr_wlock(&e->e_rdwr);
else
return ldap_pvt_thread_rdwr_rlock(&e->e_rdwr);
}
int
entry_rdwr_rlock(Entry *e)
{
return entry_rdwr_lock( e, 0 );
}
int
entry_rdwr_wlock(Entry *e)
{
return entry_rdwr_lock( e, 1 );
}
int
entry_rdwr_trylock(Entry *e, int rw)
{
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n",
rw ? "w" : "r", e->e_id, 0);
if (rw)
return ldap_pvt_thread_rdwr_wtrylock(&e->e_rdwr);
else
return ldap_pvt_thread_rdwr_rtrylock(&e->e_rdwr);
}
int
entry_rdwr_unlock(Entry *e, int rw)
{
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n",
rw ? "w" : "r", e->e_id, 0);
if (rw)
return ldap_pvt_thread_rdwr_wunlock(&e->e_rdwr);
else
return ldap_pvt_thread_rdwr_runlock(&e->e_rdwr);
}
int
entry_rdwr_runlock(Entry *e)
{
return entry_rdwr_unlock( e, 0 );
}
int
entry_rdwr_wunlock(Entry *e)
{
return entry_rdwr_unlock( e, 1 );
}
int
entry_rdwr_init(Entry *e)
{
return ldap_pvt_thread_rdwr_init( &e->e_rdwr );
}

View File

@ -46,10 +46,10 @@ monitor_info( Connection *conn, Operation *op )
e = (Entry *) ch_calloc( 1, sizeof(Entry) ); e = (Entry *) ch_calloc( 1, sizeof(Entry) );
/* initialize reader/writer lock */ /* initialize reader/writer lock */
entry_rdwr_init(e);
e->e_attrs = NULL; e->e_attrs = NULL;
e->e_dn = ch_strdup( SLAPD_MONITOR_DN ); e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
e->e_ndn = dn_normalize_case( ch_strdup(SLAPD_MONITOR_DN) ); e->e_ndn = dn_normalize_case( ch_strdup(SLAPD_MONITOR_DN) );
e->e_private = NULL;
val.bv_val = Versionstr; val.bv_val = Versionstr;
if (( p = strchr( Versionstr, '\n' )) == NULL ) { if (( p = strchr( Versionstr, '\n' )) == NULL ) {

View File

@ -138,33 +138,19 @@ typedef unsigned long ID;
* represents an entry in core * represents an entry in core
*/ */
typedef struct entry { typedef struct entry {
ldap_pvt_thread_rdwr_t e_rdwr; /* reader/writer lock */
char *e_dn; /* DN of this entry */
char *e_ndn; /* normalized DN of this entry */
Attribute *e_attrs; /* list of attributes + values */
/* /*
* The ID field should only be changed before entry is * The ID field should only be changed before entry is
* inserted into a cache. The ID value is backend * inserted into a cache. The ID value is backend
* specific. * specific.
*/ */
ID e_id; /* id of this entry - this should */ ID e_id;
/* really be private to back-ldbm */
/* char *e_dn; /* DN of this entry */
* remaining fields require backend cache lock to access char *e_ndn; /* normalized DN of this entry */
* These items are specific to the LDBM backend and should Attribute *e_attrs; /* list of attributes + values */
* be hidden.
*/
char e_state; /* for the cache */
#define ENTRY_STATE_DELETED 1
#define ENTRY_STATE_CREATING 2
int e_refcnt; /* # threads ref'ing this entry */ /* for use by the backend for any purpose */
struct entry *e_lrunext; /* for cache lru list */ void* e_private;
struct entry *e_lruprev;
} Entry; } Entry;
/* /*