Skip to content
Snippets Groups Projects
Commit 89da861b authored by Mark Valence's avatar Mark Valence
Browse files

Bug hunting -- various problems with opening caches.

parent 0ebf86f2
No related branches found
No related tags found
No related merge requests found
...@@ -92,6 +92,7 @@ typedef struct ldbm_dbcache { ...@@ -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;
......
...@@ -27,7 +27,7 @@ ldbm_cache_open( ...@@ -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( ...@@ -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 ) {
/* already open - return it */
if (li->li_dbcache[i].dbc_flags != flags
&& li->li_dbcache[i].dbc_refcnt == 0)
{
/* 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.
*
* FIXME: what about the case where the refcount
* is > 0? right now, we're using it anyway and
* just praying. Can there be more than one open
* cache to the same db?
*
* Also, it's really only necessary to compare the
* read-only flag, instead of all of the flags,
* but for now I'm checking all of them.
*/
lru = i;
empty = MAXDBCACHE;
break;
}
li->li_dbcache[i].dbc_refcnt++;
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 */ /* keep track of lru db */
if ( li->li_dbcache[i].dbc_lastref < oldtime && if ( li->li_dbcache[i].dbc_lastref < oldtime
li->li_dbcache[i].dbc_refcnt == 0 ) { && li->li_dbcache[i].dbc_refcnt == 0 )
lru = i; {
oldtime = li->li_dbcache[i].dbc_lastref; lru = i;
oldtime = li->li_dbcache[i].dbc_lastref;
}
} }
}
/* no empty slots, not already open - close lru and use that slot */ i = empty;
if ( i == MAXDBCACHE ) { if ( i == MAXDBCACHE ) {
i = lru; /* no empty slots, not already open - close lru and use that slot */
if ( li->li_dbcache[i].dbc_refcnt != 0 ) { if ( li->li_dbcache[lru].dbc_refcnt == 0 ) {
Debug( LDAP_DEBUG_ANY, i = lru;
"ldbm_cache_open no unused db to close - waiting\n", ldbm_close( li->li_dbcache[i].dbc_db );
0, 0, 0 ); free( li->li_dbcache[i].dbc_name );
lru = -1; li->li_dbcache[i].dbc_name = NULL;
while ( lru == -1 ) { } 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, ldap_pvt_thread_cond_wait( &li->li_dbcache_cv,
&li->li_dbcache_mutex ); &li->li_dbcache_mutex );
for ( i = 0; i < MAXDBCACHE; i++ ) { /* after waiting for a free slot, go back to square
if ( li->li_dbcache[i].dbc_refcnt * one: look for an open cache for this db, or an
== 0 ) { * empty slot, or an unref'ed cache, or wait again.
lru = i; */
break;
}
}
} }
i = lru;
} }
ldbm_close( li->li_dbcache[i].dbc_db ); } while (i == MAXDBCACHE);
free( li->li_dbcache[i].dbc_name );
li->li_dbcache[i].dbc_name = NULL;
}
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( ...@@ -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 ) ...@@ -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 ) ...@@ -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 );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment