diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index 5ff80d36b1..bd9d796952 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -240,9 +240,7 @@ ldbm_back_add( ldap_pvt_thread_mutex_unlock(&li->li_add_mutex); } - e->e_id = next_id( be ); - - if( e->e_id == NOID ) { + if ( next_id( be, &e->e_id ) ) { if( p != NULL) { /* free parent and writer lock */ cache_return_entry_w( &li->li_cache, p ); @@ -311,7 +309,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "index_entry_add failed\n", 0, 0, 0 ); #endif - + send_ldap_result( conn, op, LDAP_OTHER, NULL, "index generation failed", NULL, NULL ); @@ -327,6 +325,7 @@ ldbm_back_add( Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0, 0, 0 ); #endif + /* FIXME: delete attr indices? */ send_ldap_result( conn, op, LDAP_OTHER, NULL, "DN index generation failed", NULL, NULL ); @@ -344,7 +343,9 @@ ldbm_back_add( 0, 0 ); #endif + /* FIXME: delete attr indices? */ (void) dn2id_delete( be, e->e_ndn, e->e_id ); + send_ldap_result( conn, op, LDAP_OTHER, NULL, "entry store failed", NULL, NULL ); @@ -367,6 +368,9 @@ return_results:; } if ( rc ) { + /* FIXME: remove from cache? */ + cache_entry_private_destroy_mark( e ); + /* free entry and writer lock */ cache_return_entry_w( &li->li_cache, e ); } diff --git a/servers/slapd/back-ldbm/cache.c b/servers/slapd/back-ldbm/cache.c index f87bb405f1..65c1e4fec2 100644 --- a/servers/slapd/back-ldbm/cache.c +++ b/servers/slapd/back-ldbm/cache.c @@ -31,7 +31,8 @@ typedef struct ldbm_entry_info { #define CACHE_ENTRY_CREATING 1 #define CACHE_ENTRY_READY 2 #define CACHE_ENTRY_DELETED 3 - +#define CACHE_ENTRY_DESTROY_PRIVATE 4 + int lei_refcnt; /* # threads ref'ing this entry */ Entry *lei_lrunext; /* for cache lru list */ Entry *lei_lruprev; @@ -134,6 +135,20 @@ cache_entry_private_init( Entry*e ) return 0; } +/* + * assumes that the entry is write-locked;marks it i a manner that + * makes e_private be destroyed at the following cache_return_entry_w, + * but lets the entry untouched (owned by someone else) + */ +void +cache_entry_private_destroy_mark( Entry *e ) +{ + assert( e ); + assert( e->e_private ); + + LEI(e)->lei_state = CACHE_ENTRY_DESTROY_PRIVATE; +} + static int cache_entry_private_destroy( Entry*e ) { @@ -179,7 +194,8 @@ cache_return_entry_rw( Cache *cache, Entry *e, int rw ) #endif - } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED ) { + } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED + || LEI(e)->lei_state == CACHE_ENTRY_DESTROY_PRIVATE ) { if( refcnt > 0 ) { /* free cache mutex */ ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); @@ -196,8 +212,12 @@ cache_return_entry_rw( Cache *cache, Entry *e, int rw ) } else { + int state = LEI(e)->lei_state; + cache_entry_private_destroy( e ); - entry_free( e ); + if ( state == CACHE_ENTRY_DELETED ) { + entry_free( e ); + } /* free cache mutex */ ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); diff --git a/servers/slapd/back-ldbm/idl.c b/servers/slapd/back-ldbm/idl.c index a0491cbca7..93c26ed8de 100644 --- a/servers/slapd/back-ldbm/idl.c +++ b/servers/slapd/back-ldbm/idl.c @@ -65,10 +65,14 @@ ID_BLOCK * idl_allids( Backend *be ) { ID_BLOCK *idl; + ID id; idl = idl_alloc( 0 ); ID_BLOCK_NMAX(idl) = ID_BLOCK_ALLIDS_VALUE; - ID_BLOCK_NIDS(idl) = next_id_get( be ); + if ( next_id_get( be, &id ) ) { + return NULL; + } + ID_BLOCK_NIDS(idl) = id; return( idl ); } diff --git a/servers/slapd/back-ldbm/nextid.c b/servers/slapd/back-ldbm/nextid.c index 8ac43d944a..97772bfcc8 100644 --- a/servers/slapd/back-ldbm/nextid.c +++ b/servers/slapd/back-ldbm/nextid.c @@ -19,13 +19,14 @@ #include "slap.h" #include "back-ldbm.h" -static ID -next_id_read( Backend *be ) +static int +next_id_read( Backend *be, ID *idp ) { - ID id = NOID; Datum key, data; DBCache *db; + *idp = NOID; + if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT )) == NULL ) { #ifdef NEW_LOGGING @@ -36,35 +37,34 @@ next_id_read( Backend *be ) 0, 0, 0 ); #endif - return( NOID ); + return( -1 ); } ldbm_datum_init( key ); - key.dptr = (char *) &id; + key.dptr = (char *) idp; key.dsize = sizeof(ID); data = ldbm_cache_fetch( db, key ); if( data.dptr != NULL ) { - AC_MEMCPY( &id, data.dptr, sizeof( ID ) ); + AC_MEMCPY( idp, data.dptr, sizeof( ID ) ); ldbm_datum_free( db->dbc_db, data ); } else { - id = 1; + *idp = 1; } ldbm_cache_close( be, db ); - return id; + return( 0 ); } -ID +int next_id_write( Backend *be, ID id ) { - struct ldbminfo *li = (struct ldbminfo *) be->be_private; Datum key, data; DBCache *db; ID noid = NOID; - int flags; + int flags, rc = 0; if ( (db = ldbm_cache_open( be, "nextid", LDBM_SUFFIX, LDBM_WRCREAT )) == NULL ) { @@ -76,7 +76,7 @@ next_id_write( Backend *be, ID id ) 0, 0, 0 ); #endif - return( NOID ); + return( -1 ); } ldbm_datum_init( key ); @@ -90,49 +90,58 @@ next_id_write( Backend *be, ID id ) flags = LDBM_REPLACE; if ( ldbm_cache_store( db, key, data, flags ) != 0 ) { - id = NOID; + rc = -1; } ldbm_cache_close( be, db ); - return id; + return( rc ); } -ID -next_id_get( Backend *be ) +int +next_id_get( Backend *be, ID *idp ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id = NOID; + int rc = 0; + + *idp = NOID; ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex ); if ( li->li_nextid == NOID ) { - li->li_nextid = next_id_read( be ); + if ( ( rc = next_id_read( be, idp ) ) ) { + ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); + return( rc ); + } + li->li_nextid = *idp; } - id = li->li_nextid; + *idp = li->li_nextid; ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); - return id; + return( rc ); } -ID -next_id( Backend *be ) +int +next_id( Backend *be, ID *idp ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; - ID id = NOID; + int rc = 0; ldap_pvt_thread_mutex_lock( &li->li_nextid_mutex ); if ( li->li_nextid == NOID ) { - li->li_nextid = next_id_read( be ); + if ( ( rc = next_id_read( be, idp ) ) ) { + ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); + return( rc ); + } + li->li_nextid = *idp; } - if ( li->li_nextid != NOID ) { - id = li->li_nextid++; - - (void) next_id_write( be, li->li_nextid ); + *idp = li->li_nextid++; + if ( next_id_write( be, li->li_nextid ) ) { + rc = -1; } ldap_pvt_thread_mutex_unlock( &li->li_nextid_mutex ); - return id; + return( rc ); } diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index c6aecfdb95..7d798fe55a 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -51,6 +51,7 @@ int cache_update_entry LDAP_P(( Cache *cache, Entry *e )); void cache_return_entry_rw LDAP_P(( Cache *cache, Entry *e, int rw )); #define cache_return_entry_r(c, e) cache_return_entry_rw((c), (e), 0) #define cache_return_entry_w(c, e) cache_return_entry_rw((c), (e), 1) +void cache_entry_private_destroy_mark LDAP_P(( Entry *e )); ID cache_find_entry_dn2id LDAP_P(( Backend *be, Cache *cache, const char *dn )); ID cache_find_entry_ndn2id LDAP_P(( Backend *be, Cache *cache, const char *ndn )); @@ -213,9 +214,9 @@ int ldbm_modify_internal LDAP_P((Backend *be, * nextid.c */ -ID next_id LDAP_P(( Backend *be )); -ID next_id_get LDAP_P(( Backend *be )); -ID next_id_write LDAP_P(( Backend *be, ID id )); +int next_id LDAP_P(( Backend *be, ID *idp )); +int next_id_get LDAP_P(( Backend *be, ID *idp )); +int next_id_write LDAP_P(( Backend *be, ID id )); LDAP_END_DECL #endif diff --git a/servers/slapd/back-ldbm/tools.c b/servers/slapd/back-ldbm/tools.c index 94d0dc6387..226db043a6 100644 --- a/servers/slapd/back-ldbm/tools.c +++ b/servers/slapd/back-ldbm/tools.c @@ -162,7 +162,7 @@ ID ldbm_tool_entry_put( assert( slapMode & SLAP_TOOL_MODE ); assert( id2entry != NULL ); - if( next_id_get( be ) == NOID ) { + if ( next_id_get( be, &id ) || id == NOID ) { return NOID; } @@ -286,7 +286,9 @@ int ldbm_tool_sync( BackendDB *be ) assert( slapMode & SLAP_TOOL_MODE ); if ( li->li_nextid != NOID ) { - next_id_write( be, li->li_nextid ); + if ( next_id_write( be, li->li_nextid ) ) { + return( -1 ); + } } return 0;