mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-09 02:52:04 +08:00
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:
parent
529caeddd0
commit
88c43a1e6e
@ -54,11 +54,11 @@ do_add( Connection *conn, Operation *op )
|
||||
}
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
/* initialize reader/writer lock */
|
||||
entry_rdwr_init(e);
|
||||
|
||||
e->e_dn = dn;
|
||||
e->e_ndn = dn_normalize_case( ch_strdup( dn ) );
|
||||
e->e_private = NULL;
|
||||
|
||||
dn = NULL;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 );
|
||||
|
@ -23,7 +23,7 @@ ldbm_back_add(
|
||||
char *pdn;
|
||||
Entry *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
int rc;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
/* 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);
|
||||
@ -161,15 +141,24 @@ ldbm_back_add(
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
|
||||
0 );
|
||||
|
||||
/* return the id */
|
||||
next_id_return( be, e->e_id );
|
||||
|
||||
entry_rdwr_unlock(e, 1);
|
||||
|
||||
/* free the entry */
|
||||
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 );
|
||||
}
|
||||
|
||||
rc = -1;
|
||||
|
||||
/*
|
||||
* add it to the id2children index for the parent
|
||||
*/
|
||||
|
@ -79,6 +79,9 @@ struct cache {
|
||||
ldap_pvt_thread_mutex_t c_mutex;
|
||||
};
|
||||
|
||||
#define ENTRY_STATE_DELETED 1
|
||||
#define ENTRY_STATE_CREATING 2
|
||||
|
||||
/* for the cache of open index files */
|
||||
struct dbcache {
|
||||
int dbc_refcnt;
|
||||
|
@ -12,6 +12,23 @@
|
||||
|
||||
#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);
|
||||
#ifdef LDAP_DEBUG
|
||||
static void lru_print(struct cache *cache);
|
||||
@ -53,27 +70,94 @@ cache_set_state( struct cache *cache, Entry *e, int state )
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
|
||||
e->e_state = state;
|
||||
LEI(e)->lei_state = state;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
}
|
||||
|
||||
#ifdef not_used
|
||||
static void
|
||||
cache_return_entry( struct cache *cache, Entry *e )
|
||||
static int
|
||||
cache_entry_rdwr_lock(Entry *e, int rw)
|
||||
{
|
||||
/* set cache mutex */
|
||||
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
|
||||
Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
|
||||
rw ? "w" : "r", e->e_id, 0);
|
||||
|
||||
if ( --e->e_refcnt == 0 && e->e_state == ENTRY_STATE_DELETED ) {
|
||||
entry_free( e );
|
||||
if (rw)
|
||||
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 */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
e->e_private = ch_calloc(1, sizeof(struct ldbm_entry_info));
|
||||
|
||||
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
|
||||
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 */
|
||||
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 );
|
||||
}
|
||||
|
||||
@ -108,41 +195,42 @@ cache_return_entry_w( struct cache *cache, Entry *e )
|
||||
|
||||
|
||||
#define LRU_DELETE( cache, e ) { \
|
||||
if ( e->e_lruprev != NULL ) { \
|
||||
e->e_lruprev->e_lrunext = e->e_lrunext; \
|
||||
if ( LEI(e)->lei_lruprev != NULL ) { \
|
||||
LEI(LEI(e)->lei_lruprev)->lei_lrunext = LEI(e)->lei_lrunext; \
|
||||
} else { \
|
||||
cache->c_lruhead = e->e_lrunext; \
|
||||
cache->c_lruhead = LEI(e)->lei_lrunext; \
|
||||
} \
|
||||
if ( e->e_lrunext != NULL ) { \
|
||||
e->e_lrunext->e_lruprev = e->e_lruprev; \
|
||||
if ( LEI(e)->lei_lrunext != NULL ) { \
|
||||
LEI(LEI(e)->lei_lrunext)->lei_lruprev = LEI(e)->lei_lruprev; \
|
||||
} else { \
|
||||
cache->c_lrutail = e->e_lruprev; \
|
||||
cache->c_lrutail = LEI(e)->lei_lruprev; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LRU_ADD( cache, e ) { \
|
||||
e->e_lrunext = cache->c_lruhead; \
|
||||
if ( e->e_lrunext != NULL ) { \
|
||||
e->e_lrunext->e_lruprev = e; \
|
||||
LEI(e)->lei_lrunext = cache->c_lruhead; \
|
||||
if ( LEI(e)->lei_lrunext != NULL ) { \
|
||||
LEI(LEI(e)->lei_lrunext)->lei_lruprev = e; \
|
||||
} \
|
||||
cache->c_lruhead = e; \
|
||||
e->e_lruprev = NULL; \
|
||||
LEI(e)->lei_lruprev = NULL; \
|
||||
if ( cache->c_lrutail == NULL ) { \
|
||||
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
|
||||
* 1 entry already existed
|
||||
* -1 something bad happened
|
||||
*/
|
||||
int
|
||||
cache_add_entry_lock(
|
||||
cache_add_entry_rw(
|
||||
struct cache *cache,
|
||||
Entry *e,
|
||||
int state
|
||||
int state,
|
||||
int rw
|
||||
)
|
||||
{
|
||||
int i, rc;
|
||||
@ -151,11 +239,134 @@ cache_add_entry_lock(
|
||||
/* set cache 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,
|
||||
cache_entrydn_cmp, avl_dup_error ) != 0 )
|
||||
{
|
||||
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 );
|
||||
|
||||
/* free cache mutex */
|
||||
@ -184,9 +395,6 @@ cache_add_entry_lock(
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
e->e_state = state;
|
||||
e->e_refcnt = 1;
|
||||
|
||||
/* lru */
|
||||
LRU_ADD( cache, e );
|
||||
if ( ++cache->c_cursize > cache->c_maxsize ) {
|
||||
@ -196,8 +404,10 @@ cache_add_entry_lock(
|
||||
* first 10 on the tail of the list.
|
||||
*/
|
||||
i = 0;
|
||||
while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
|
||||
!= 0 && i < 10 ) {
|
||||
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 );
|
||||
@ -209,15 +419,12 @@ cache_add_entry_lock(
|
||||
* found at least one to delete - try to get back under
|
||||
* the max cache size.
|
||||
*/
|
||||
while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
|
||||
== 0 && cache->c_cursize > cache->c_maxsize ) {
|
||||
while ( cache->c_lrutail != NULL &&
|
||||
LEI(cache->c_lrutail)->lei_refcnt == 0 &&
|
||||
cache->c_cursize > cache->c_maxsize )
|
||||
{
|
||||
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 */
|
||||
rc = cache_delete_entry_internal( cache, e );
|
||||
|
||||
@ -267,8 +474,8 @@ cache_find_entry_dn2id(
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( ep->e_state == ENTRY_STATE_DELETED ||
|
||||
ep->e_state == ENTRY_STATE_CREATING )
|
||||
if ( LEI(ep)->lei_state == ENTRY_STATE_DELETED ||
|
||||
LEI(ep)->lei_state == ENTRY_STATE_CREATING )
|
||||
{
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
@ -326,8 +533,8 @@ try_again:
|
||||
/*
|
||||
* entry is deleted or not fully created yet
|
||||
*/
|
||||
if ( ep->e_state == ENTRY_STATE_DELETED ||
|
||||
ep->e_state == ENTRY_STATE_CREATING )
|
||||
if ( LEI(ep)->lei_state == ENTRY_STATE_DELETED ||
|
||||
LEI(ep)->lei_state == ENTRY_STATE_CREATING )
|
||||
{
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
@ -335,7 +542,7 @@ try_again:
|
||||
}
|
||||
|
||||
/* 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...
|
||||
* owner cannot free as we have the cache locked.
|
||||
* so, unlock the cache, yield, and try again.
|
||||
@ -351,7 +558,7 @@ try_again:
|
||||
LRU_DELETE( cache, ep );
|
||||
LRU_ADD( cache, ep );
|
||||
|
||||
ep->e_refcnt++;
|
||||
LEI(ep)->lei_refcnt++;
|
||||
|
||||
/* free cache mutex */
|
||||
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
|
||||
@ -389,11 +596,6 @@ cache_delete_entry(
|
||||
/* set cache 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 );
|
||||
|
||||
/* free cache mutex */
|
||||
@ -434,7 +636,7 @@ cache_delete_entry_internal(
|
||||
/*
|
||||
* 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 );
|
||||
}
|
||||
@ -447,14 +649,14 @@ lru_print( struct cache *cache )
|
||||
Entry *e;
|
||||
|
||||
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,
|
||||
e->e_id, e->e_refcnt );
|
||||
e->e_id, LEI(e)->lei_refcnt );
|
||||
}
|
||||
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,
|
||||
e->e_id, e->e_refcnt );
|
||||
e->e_id, LEI(e)->lei_refcnt );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ dn2id_delete(
|
||||
*/
|
||||
|
||||
static Entry *
|
||||
dn2entry(
|
||||
dn2entry_rw(
|
||||
Backend *be,
|
||||
char *dn,
|
||||
char **matched,
|
||||
@ -172,7 +172,7 @@ dn2entry(
|
||||
*matched = NULL;
|
||||
|
||||
if ( (id = dn2id( be, dn )) != NOID &&
|
||||
(e = id2entry( be, id, rw )) != NULL )
|
||||
(e = id2entry_rw( be, id, rw )) != NULL )
|
||||
{
|
||||
return( e );
|
||||
}
|
||||
@ -215,7 +215,7 @@ dn2entry_r(
|
||||
char **matched
|
||||
)
|
||||
{
|
||||
return( dn2entry( be, dn, matched, 0 ) );
|
||||
return( dn2entry_rw( be, dn, matched, 0 ) );
|
||||
}
|
||||
|
||||
Entry *
|
||||
@ -225,7 +225,7 @@ dn2entry_w(
|
||||
char **matched
|
||||
)
|
||||
{
|
||||
return( dn2entry( be, dn, matched, 1 ) );
|
||||
return( dn2entry_rw( be, dn, matched, 1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,11 @@
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
/*
|
||||
* This routine adds (or updates) an entry on disk.
|
||||
* The cache should already be updated.
|
||||
*/
|
||||
|
||||
int
|
||||
id2entry_add( Backend *be, Entry *e )
|
||||
{
|
||||
@ -45,11 +50,12 @@ id2entry_add( Backend *be, Entry *e )
|
||||
ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
|
||||
|
||||
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 );
|
||||
|
||||
/* XXX should entries be born locked, i.e. apply writer lock here? */
|
||||
return( rc );
|
||||
}
|
||||
|
||||
@ -64,9 +70,11 @@ id2entry_delete( Backend *be, Entry *e )
|
||||
Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %lu, \"%s\" )\n", e->e_id,
|
||||
e->e_dn, 0 );
|
||||
|
||||
#ifdef notdef
|
||||
#ifdef LDAP_DEBUG
|
||||
/* check for writer lock */
|
||||
assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ldbm_datum_init( key );
|
||||
@ -96,7 +104,7 @@ id2entry_delete( Backend *be, Entry *e )
|
||||
|
||||
/* XXX returns entry with reader/writer lock */
|
||||
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 dbcache *db;
|
||||
@ -145,15 +153,12 @@ id2entry( Backend *be, ID id, int rw )
|
||||
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;
|
||||
(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",
|
||||
rw ? "w" : "r", id, 0 );
|
||||
@ -163,12 +168,12 @@ id2entry( Backend *be, ID id, int rw )
|
||||
Entry *
|
||||
id2entry_r( Backend *be, ID id )
|
||||
{
|
||||
return( id2entry( be, id, 0 ) );
|
||||
return( id2entry_rw( be, id, 0 ) );
|
||||
}
|
||||
|
||||
Entry *
|
||||
id2entry_w( Backend *be, ID id )
|
||||
{
|
||||
return( id2entry( be, id, 1 ) );
|
||||
return( id2entry_rw( be, id, 1 ) );
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,9 @@ ldbm_back_modrdn(
|
||||
e->e_dn = new_dn;
|
||||
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
|
||||
* the entry itself that were effected by this RDN change
|
||||
* (respecting the value of the deleteoldrdn parameter).
|
||||
|
@ -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_return_entry_r 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 ));
|
||||
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 ));
|
||||
@ -85,7 +87,7 @@ int has_children LDAP_P(( Backend *be, Entry *p ));
|
||||
|
||||
int id2entry_add 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_w LDAP_P(( Backend *be, ID id ));
|
||||
|
||||
|
@ -39,11 +39,10 @@ config_info( Connection *conn, Operation *op )
|
||||
vals[1] = NULL;
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
/* initialize reader/writer lock */
|
||||
entry_rdwr_init(e);
|
||||
|
||||
e->e_attrs = NULL;
|
||||
e->e_dn = ch_strdup( SLAPD_CONFIG_DN );
|
||||
e->e_private = NULL;
|
||||
|
||||
for ( i = 0; i < nbackends; i++ ) {
|
||||
strcpy( buf, backends[i].be_type );
|
||||
|
@ -68,9 +68,9 @@ str2entry( char *s )
|
||||
0, 0, 0 );
|
||||
return( NULL );
|
||||
}
|
||||
e->e_id = id;
|
||||
|
||||
entry_rdwr_init(e);
|
||||
e->e_id = id;
|
||||
e->e_private = NULL;
|
||||
|
||||
/* dn + attributes */
|
||||
e->e_attrs = NULL;
|
||||
@ -142,7 +142,8 @@ str2entry( char *s )
|
||||
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 );
|
||||
}
|
||||
@ -219,93 +220,20 @@ entry_free( Entry *e )
|
||||
int i;
|
||||
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 ) {
|
||||
free( e->e_dn );
|
||||
e->e_dn = NULL;
|
||||
}
|
||||
if ( e->e_ndn != NULL ) {
|
||||
free( e->e_ndn );
|
||||
e->e_ndn = NULL;
|
||||
}
|
||||
for ( a = e->e_attrs; a != NULL; a = next ) {
|
||||
next = a->a_next;
|
||||
attr_free( a );
|
||||
}
|
||||
e->e_attrs = NULL;
|
||||
e->e_private = NULL;
|
||||
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 );
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ monitor_info( Connection *conn, Operation *op )
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
/* initialize reader/writer lock */
|
||||
entry_rdwr_init(e);
|
||||
e->e_attrs = NULL;
|
||||
e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
|
||||
e->e_ndn = dn_normalize_case( ch_strdup(SLAPD_MONITOR_DN) );
|
||||
e->e_private = NULL;
|
||||
|
||||
val.bv_val = Versionstr;
|
||||
if (( p = strchr( Versionstr, '\n' )) == NULL ) {
|
||||
|
@ -138,33 +138,19 @@ typedef unsigned long ID;
|
||||
* represents an entry in core
|
||||
*/
|
||||
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
|
||||
* inserted into a cache. The ID value is backend
|
||||
* specific.
|
||||
*/
|
||||
ID e_id; /* id of this entry - this should */
|
||||
/* really be private to back-ldbm */
|
||||
ID e_id;
|
||||
|
||||
/*
|
||||
* remaining fields require backend cache lock to access
|
||||
* These items are specific to the LDBM backend and should
|
||||
* be hidden.
|
||||
*/
|
||||
char e_state; /* for the cache */
|
||||
#define ENTRY_STATE_DELETED 1
|
||||
#define ENTRY_STATE_CREATING 2
|
||||
char *e_dn; /* DN of this entry */
|
||||
char *e_ndn; /* normalized DN of this entry */
|
||||
Attribute *e_attrs; /* list of attributes + values */
|
||||
|
||||
int e_refcnt; /* # threads ref'ing this entry */
|
||||
struct entry *e_lrunext; /* for cache lru list */
|
||||
struct entry *e_lruprev;
|
||||
/* for use by the backend for any purpose */
|
||||
void* e_private;
|
||||
} Entry;
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user