Bug hunting -- various problems with opening caches.

This commit is contained in:
Mark Valence 2000-06-14 18:23:43 +00:00
parent 0ebf86f2d3
commit 89da861b89
2 changed files with 78 additions and 48 deletions

View File

@ -92,6 +92,7 @@ typedef struct ldbm_dbcache {
int dbc_maxids; int dbc_maxids;
int dbc_maxindirect; int dbc_maxindirect;
int dbc_dirty; int dbc_dirty;
int dbc_flags;
time_t dbc_lastref; time_t dbc_lastref;
long dbc_blksize; long dbc_blksize;
char *dbc_name; char *dbc_name;

View File

@ -27,7 +27,7 @@ ldbm_cache_open(
) )
{ {
struct ldbminfo *li = (struct ldbminfo *) be->be_private; struct ldbminfo *li = (struct ldbminfo *) be->be_private;
int i, lru; int i, lru, empty;
time_t oldtime, curtime; time_t oldtime, curtime;
char buf[MAXPATHLEN]; char buf[MAXPATHLEN];
#ifdef HAVE_ST_BLKSIZE #ifdef HAVE_ST_BLKSIZE
@ -52,58 +52,84 @@ ldbm_cache_open(
Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf, Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf,
flags, li->li_mode ); flags, li->li_mode );
lru = 0;
curtime = slap_get_time(); curtime = slap_get_time();
oldtime = curtime; empty = MAXDBCACHE;
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex ); ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
for ( i = 0; i < MAXDBCACHE && li->li_dbcache[i].dbc_name != NULL; do {
i++ ) { lru = 0;
/* already open - return it */ oldtime = curtime;
if ( strcmp( li->li_dbcache[i].dbc_name, buf ) == 0 ) { for ( i = 0; i < MAXDBCACHE; i++ ) {
li->li_dbcache[i].dbc_refcnt++; /* see if this slot is free */
Debug( LDAP_DEBUG_TRACE, if ( li->li_dbcache[i].dbc_name == NULL) {
"<= ldbm_cache_open (cache %d)\n", i, 0, 0 ); empty = i;
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex ); continue;
return( &li->li_dbcache[i] ); }
}
if ( strcmp( li->li_dbcache[i].dbc_name, buf ) == 0 ) {
/* keep track of lru db */ /* already open - return it */
if ( li->li_dbcache[i].dbc_lastref < oldtime && if (li->li_dbcache[i].dbc_flags != flags
li->li_dbcache[i].dbc_refcnt == 0 ) { && li->li_dbcache[i].dbc_refcnt == 0)
lru = i; {
oldtime = li->li_dbcache[i].dbc_lastref; /* we don't want to use an open cache with different
} * permissions (esp. if we need write but the open
} * cache is read-only). So close this one if
* possible, and re-open below.
/* no empty slots, not already open - close lru and use that slot */ *
if ( i == MAXDBCACHE ) { * FIXME: what about the case where the refcount
i = lru; * is > 0? right now, we're using it anyway and
if ( li->li_dbcache[i].dbc_refcnt != 0 ) { * just praying. Can there be more than one open
Debug( LDAP_DEBUG_ANY, * cache to the same db?
"ldbm_cache_open no unused db to close - waiting\n", *
0, 0, 0 ); * Also, it's really only necessary to compare the
lru = -1; * read-only flag, instead of all of the flags,
while ( lru == -1 ) { * but for now I'm checking all of them.
ldap_pvt_thread_cond_wait( &li->li_dbcache_cv, */
&li->li_dbcache_mutex ); lru = i;
for ( i = 0; i < MAXDBCACHE; i++ ) { empty = MAXDBCACHE;
if ( li->li_dbcache[i].dbc_refcnt break;
== 0 ) { }
lru = i; li->li_dbcache[i].dbc_refcnt++;
break; Debug( LDAP_DEBUG_TRACE,
} "<= ldbm_cache_open (cache %d)\n", i, 0, 0 );
} ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
return( &li->li_dbcache[i] );
}
/* keep track of lru db */
if ( li->li_dbcache[i].dbc_lastref < oldtime
&& li->li_dbcache[i].dbc_refcnt == 0 )
{
lru = i;
oldtime = li->li_dbcache[i].dbc_lastref;
} }
i = lru;
} }
ldbm_close( li->li_dbcache[i].dbc_db );
free( li->li_dbcache[i].dbc_name ); i = empty;
li->li_dbcache[i].dbc_name = NULL; if ( i == MAXDBCACHE ) {
} /* no empty slots, not already open - close lru and use that slot */
if ( li->li_dbcache[lru].dbc_refcnt == 0 ) {
i = lru;
ldbm_close( li->li_dbcache[i].dbc_db );
free( li->li_dbcache[i].dbc_name );
li->li_dbcache[i].dbc_name = NULL;
} else {
Debug( LDAP_DEBUG_ANY,
"ldbm_cache_open no unused db to close - waiting\n",
0, 0, 0 );
ldap_pvt_thread_cond_wait( &li->li_dbcache_cv,
&li->li_dbcache_mutex );
/* after waiting for a free slot, go back to square
* one: look for an open cache for this db, or an
* empty slot, or an unref'ed cache, or wait again.
*/
}
}
} while (i == MAXDBCACHE);
if ( (li->li_dbcache[i].dbc_db = ldbm_open( buf, flags, li->li_mode, if ( (li->li_dbcache[i].dbc_db = ldbm_open( buf, flags, li->li_mode,
li->li_dbcachesize )) == NULL ) { li->li_dbcachesize )) == NULL )
{
int err = errno; int err = errno;
Debug( LDAP_DEBUG_TRACE, Debug( LDAP_DEBUG_TRACE,
"<= ldbm_cache_open NULL \"%s\" errno=%d reason=\"%s\")\n", "<= ldbm_cache_open NULL \"%s\" errno=%d reason=\"%s\")\n",
@ -115,6 +141,7 @@ ldbm_cache_open(
li->li_dbcache[i].dbc_name = ch_strdup( buf ); li->li_dbcache[i].dbc_name = ch_strdup( buf );
li->li_dbcache[i].dbc_refcnt = 1; li->li_dbcache[i].dbc_refcnt = 1;
li->li_dbcache[i].dbc_lastref = curtime; li->li_dbcache[i].dbc_lastref = curtime;
li->li_dbcache[i].dbc_flags = flags;
li->li_dbcache[i].dbc_dirty = 0; li->li_dbcache[i].dbc_dirty = 0;
#ifdef HAVE_ST_BLKSIZE #ifdef HAVE_ST_BLKSIZE
if ( stat( buf, &st ) == 0 ) { if ( stat( buf, &st ) == 0 ) {
@ -151,7 +178,8 @@ ldbm_cache_close( Backend *be, DBCache *db )
} }
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex ); ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
if ( --db->dbc_refcnt == 0 ) { if ( --db->dbc_refcnt <= 0 ) {
db->dbc_refcnt = 0;
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv ); ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
} }
ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex ); ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
@ -163,7 +191,8 @@ ldbm_cache_really_close( Backend *be, DBCache *db )
struct ldbminfo *li = (struct ldbminfo *) be->be_private; struct ldbminfo *li = (struct ldbminfo *) be->be_private;
ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex ); ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
if ( --db->dbc_refcnt == 0 ) { if ( --db->dbc_refcnt <= 0 ) {
db->dbc_refcnt = 0;
ldap_pvt_thread_cond_signal( &li->li_dbcache_cv ); ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
ldbm_close( db->dbc_db ); ldbm_close( db->dbc_db );
free( db->dbc_name ); free( db->dbc_name );