diff --git a/servers/slapd/add.c b/servers/slapd/add.c index e128d81af7..0e8330d762 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -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 ); diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index 052b23c6a9..b99ade9cf5 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -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 */ diff --git a/servers/slapd/back-ldbm/back-ldbm.h b/servers/slapd/back-ldbm/back-ldbm.h index e0816acd48..9b98c02cb0 100644 --- a/servers/slapd/back-ldbm/back-ldbm.h +++ b/servers/slapd/back-ldbm/back-ldbm.h @@ -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; diff --git a/servers/slapd/back-ldbm/cache.c b/servers/slapd/back-ldbm/cache.c index 46d8c655b6..0a2b3c97b1 100644 --- a/servers/slapd/back-ldbm/cache.c +++ b/servers/slapd/back-ldbm/cache.c @@ -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 ); } } diff --git a/servers/slapd/back-ldbm/dn2id.c b/servers/slapd/back-ldbm/dn2id.c index 683d30a2e5..3772b90281 100644 --- a/servers/slapd/back-ldbm/dn2id.c +++ b/servers/slapd/back-ldbm/dn2id.c @@ -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 ) ); } diff --git a/servers/slapd/back-ldbm/id2entry.c b/servers/slapd/back-ldbm/id2entry.c index ae5e18868e..dad31af444 100644 --- a/servers/slapd/back-ldbm/id2entry.c +++ b/servers/slapd/back-ldbm/id2entry.c @@ -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 ) ); } diff --git a/servers/slapd/back-ldbm/modrdn.c b/servers/slapd/back-ldbm/modrdn.c index dc93fd8461..3c8c2f8511 100644 --- a/servers/slapd/back-ldbm/modrdn.c +++ b/servers/slapd/back-ldbm/modrdn.c @@ -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). diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index ae7ec7f957..a0abc0d867 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -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 )); diff --git a/servers/slapd/configinfo.c b/servers/slapd/configinfo.c index c25a76dc28..df64293da4 100644 --- a/servers/slapd/configinfo.c +++ b/servers/slapd/configinfo.c @@ -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 ); diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index 1e7a7c6b55..3755272d1f 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -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 ); -} diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c index 88ea15b9ec..4c21dfb273 100644 --- a/servers/slapd/monitor.c +++ b/servers/slapd/monitor.c @@ -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 ) { diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 3cfaa66783..786702b2e4 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -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; /*