send_ldap_result( conn, op, LDAP_SUCCESS,
NULL, NULL, NULL, NULL );
+
+ /* marks the entry as committed, so it is added to the cache;
+ * otherwise it is removed from the cache, but not destroyed;
+ * it will be destroyed by the caller */
rc = 0;
+ cache_entry_commit( e );
return_results:;
if (p != NULL) {
}
if ( rc ) {
- /* FIXME: remove from cache? */
- cache_entry_private_destroy_mark( e );
-
- /* free entry and writer lock */
+ /* in case of error, writer lock is freed
+ * and entry's private data is destroyed */
cache_return_entry_w( &li->li_cache, e );
}
int lei_state; /* for the cache */
#define CACHE_ENTRY_UNDEFINED 0
#define CACHE_ENTRY_CREATING 1
-#define CACHE_ENTRY_READY 2
-#define CACHE_ENTRY_DELETED 3
-#define CACHE_ENTRY_DESTROY_PRIVATE 4
+#define CACHE_ENTRY_READY 2
+#define CACHE_ENTRY_DELETED 3
+#define CACHE_ENTRY_COMMITTED 4
int lei_refcnt; /* # threads ref'ing this entry */
Entry *lei_lrunext; /* for cache lru list */
}
/*
- * 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,
+ * marks an entry in CREATING state as committed, so it is really returned
+ * to the cache. Otherwise an entry in CREATING state is removed.
+ * 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 )
+cache_entry_commit( Entry *e )
{
assert( e );
assert( e->e_private );
+ assert( LEI(e)->lei_state == CACHE_ENTRY_CREATING );
+ /* assert( LEI(e)->lei_refcnt == 1 ); */
- LEI(e)->lei_state = CACHE_ENTRY_DESTROY_PRIVATE;
+ LEI(e)->lei_state = CACHE_ENTRY_COMMITTED;
}
static int
cache_return_entry_rw( Cache *cache, Entry *e, int rw )
{
ID id;
- int refcnt;
+ int refcnt, freeit = 1;
/* set cache mutex */
ldap_pvt_thread_mutex_lock( &cache->c_mutex );
id = e->e_id;
refcnt = --LEI(e)->lei_refcnt;
- if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) {
+ /*
+ * if the entry is returned when in CREATING state, it is deleted
+ * but not freed because it may belong to someone else (do_add,
+ * for instance)
+ */
+ if ( LEI(e)->lei_state == CACHE_ENTRY_CREATING ) {
+ cache_delete_entry_internal( cache, e );
+ freeit = 0;
+ /* now the entry is in DELETED state */
+ }
+
+ if ( LEI(e)->lei_state == CACHE_ENTRY_COMMITTED ) {
LEI(e)->lei_state = CACHE_ENTRY_READY;
/* free cache mutex */
#endif
- } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED
- || LEI(e)->lei_state == CACHE_ENTRY_DESTROY_PRIVATE ) {
+ } else if ( LEI(e)->lei_state == CACHE_ENTRY_DELETED ) {
if( refcnt > 0 ) {
/* free cache mutex */
ldap_pvt_thread_mutex_unlock( &cache->c_mutex );
} else {
- int state = LEI(e)->lei_state;
-
cache_entry_private_destroy( e );
- if ( state == CACHE_ENTRY_DELETED ) {
+ if ( freeit ) {
entry_free( e );
}
rw ? "w" : "r", id, (unsigned long) e );
#endif
+ /* marks the entry as committed, so it will get added to the cache
+ * when the lock is released */
+ cache_entry_commit( e );
return( e );
}
goto return_results;
}
+ rc = -1;
(void) cache_update_entry( &li->li_cache, e );
/* id2entry index */
if ( id2entry_add( be, e ) != 0 ) {
- entry_free( e );
send_ldap_result( conn, op, LDAP_OTHER,
NULL, "entry update failed", NULL, NULL );
goto return_results;
send_ldap_result( conn, op, LDAP_SUCCESS,
NULL, NULL, NULL, NULL );
rc = 0;
+ cache_entry_commit( e );
return_results:
if( new_dn != NULL ) free( new_dn );
/* free entry and writer lock */
cache_return_entry_w( &li->li_cache, e );
+ if ( rc ) {
+ /* if rc != 0 the entry is uncached and its private data
+ * is destroyed; the entry must be freed */
+ entry_free( e );
+ }
return( rc );
}
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 ));
+void cache_entry_commit 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 ));