mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-15 03:01:09 +08:00
e46877f89f
id2entry: when an error occurs attempting to insert fetched entry into cache, check to see if entry was added by another thread. If so, return the entry added by the other thread. The concurrency tests now run without the dreaded "no such object" error messages!
180 lines
4.1 KiB
C
180 lines
4.1 KiB
C
/* id2entry.c - routines to deal with the id2entry index */
|
|
|
|
#include "portable.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ac/socket.h>
|
|
|
|
#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 )
|
|
{
|
|
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
|
struct dbcache *db;
|
|
Datum key, data;
|
|
int len, rc, flags;
|
|
|
|
ldbm_datum_init( key );
|
|
ldbm_datum_init( data );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "=> id2entry_add( %ld, \"%s\" )\n", e->e_id,
|
|
e->e_dn, 0 );
|
|
|
|
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
|
== NULL ) {
|
|
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
|
LDBM_SUFFIX, 0, 0 );
|
|
return( -1 );
|
|
}
|
|
|
|
key.dptr = (char *) &e->e_id;
|
|
key.dsize = sizeof(ID);
|
|
|
|
ldap_pvt_thread_mutex_lock( &entry2str_mutex );
|
|
data.dptr = entry2str( e, &len, 1 );
|
|
data.dsize = len + 1;
|
|
|
|
/* store it */
|
|
flags = LDBM_REPLACE;
|
|
if ( li->li_dbcachewsync ) flags |= LDBM_SYNC;
|
|
rc = ldbm_cache_store( db, key, data, flags );
|
|
|
|
ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
|
|
|
|
ldbm_cache_close( be, db );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_add %d\n", rc, 0, 0 );
|
|
|
|
return( rc );
|
|
}
|
|
|
|
int
|
|
id2entry_delete( Backend *be, Entry *e )
|
|
{
|
|
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
|
struct dbcache *db;
|
|
Datum key;
|
|
int rc;
|
|
|
|
Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %ld, \"%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 );
|
|
|
|
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
|
== NULL ) {
|
|
Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
|
|
LDBM_SUFFIX, 0, 0 );
|
|
return( -1 );
|
|
}
|
|
|
|
if ( cache_delete_entry( &li->li_cache, e ) != 0 ) {
|
|
Debug(LDAP_DEBUG_ANY, "could not delete %ld (%s) from cache\n",
|
|
e->e_id, e->e_dn, 0 );
|
|
}
|
|
|
|
key.dptr = (char *) &e->e_id;
|
|
key.dsize = sizeof(ID);
|
|
|
|
rc = ldbm_cache_delete( db, key );
|
|
|
|
ldbm_cache_close( be, db );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_delete %d\n", rc, 0, 0 );
|
|
return( rc );
|
|
}
|
|
|
|
/* returns entry with reader/writer lock */
|
|
Entry *
|
|
id2entry_rw( Backend *be, ID id, int rw )
|
|
{
|
|
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
|
struct dbcache *db;
|
|
Datum key, data;
|
|
Entry *e;
|
|
|
|
ldbm_datum_init( key );
|
|
ldbm_datum_init( data );
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "=> id2entry_%s( %ld )\n",
|
|
rw ? "w" : "r", id, 0 );
|
|
|
|
if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
|
|
rw ? "w" : "r", id, (unsigned long) e );
|
|
return( e );
|
|
}
|
|
|
|
if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
|
|
== NULL ) {
|
|
Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
|
|
LDBM_SUFFIX, 0, 0 );
|
|
return( NULL );
|
|
}
|
|
|
|
key.dptr = (char *) &id;
|
|
key.dsize = sizeof(ID);
|
|
|
|
data = ldbm_cache_fetch( db, key );
|
|
|
|
if ( data.dptr == NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) not found\n",
|
|
rw ? "w" : "r", id, 0 );
|
|
ldbm_cache_close( be, db );
|
|
return( NULL );
|
|
}
|
|
|
|
e = str2entry( data.dptr );
|
|
|
|
ldbm_datum_free( db->dbc_db, data );
|
|
ldbm_cache_close( be, db );
|
|
|
|
if ( e == NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (failed)\n",
|
|
rw ? "w" : "r", id, 0 );
|
|
return( NULL );
|
|
}
|
|
|
|
if ( e->e_id != id ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (wrong id %ld on disk)\n",
|
|
rw ? "w" : "r", id, e->e_id );
|
|
entry_free( e );
|
|
return( NULL );
|
|
}
|
|
|
|
if( cache_add_entry_rw( &li->li_cache, e, rw ) != 0 ) {
|
|
entry_free( e );
|
|
|
|
/* maybe the entry got added underneath us */
|
|
if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
|
|
rw ? "w" : "r", id, (unsigned long) e );
|
|
return( e );
|
|
}
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (cache add failed)\n",
|
|
rw ? "w" : "r", id, 0 );
|
|
return NULL;
|
|
}
|
|
|
|
Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (disk)\n",
|
|
rw ? "w" : "r", id, (unsigned long) e );
|
|
|
|
return( e );
|
|
}
|