Moved IDL cache code to standalone functions.

Use IDL cache in bdb_dn2id_children.
This commit is contained in:
Howard Chu 2003-04-22 05:14:27 +00:00
parent f0577fcb08
commit bd871d710d
3 changed files with 229 additions and 197 deletions

View File

@ -376,6 +376,15 @@ bdb_dn2id_children(
((char *)key.data)[0] = DN_ONE_PREFIX;
AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, &key, NULL );
if ( rc != LDAP_NO_SUCH_OBJECT ) {
sl_free( key.data, o->o_tmpmemctx );
return rc;
}
}
#endif
/* we actually could do a empty get... */
DBTzero( &data );
data.data = &id;
@ -513,26 +522,21 @@ bdb_hdb_compare(
return rc;
}
/* This function constructs a full DN for a given id.
/* This function constructs a full DN for a given entry.
*/
int bdb_fix_dn(
BackendDB *be,
ID id,
Entry *e
)
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
idNode *n, *o;
int rlen, nrlen;
EntryInfo *ei;
int rlen = 0, nrlen = 0;
char *ptr, *nptr;
ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
o = bdb_find_id_node(id, bdb->bi_tree);
rlen = be->be_suffix[0].bv_len + 1;
nrlen = be->be_nsuffix[0].bv_len + 1;
for (n = o; n && n->i_parent; n=n->i_parent) {
rlen += n->i_rdn->rdn.bv_len + 1;
nrlen += n->i_rdn->nrdn.bv_len + 1;
for ( ei = BEI(e); ei; ei=ei->bei_parent ) {
rlen += ei->bei_rdn.bv_len + 1;
nrlen += ei->bei_nrdn.bv_len + 1;
}
e->e_name.bv_len = rlen - 1;
e->e_nname.bv_len = nrlen - 1;
@ -540,16 +544,16 @@ int bdb_fix_dn(
e->e_nname.bv_val = e->e_name.bv_val + rlen;
ptr = e->e_name.bv_val;
nptr = e->e_nname.bv_val;
for (n = o; n && n->i_parent; n=n->i_parent) {
ptr = lutil_strcopy(ptr, n->i_rdn->rdn.bv_val);
*ptr++ = ',';
nptr = lutil_strcopy(nptr, n->i_rdn->nrdn.bv_val);
*nptr++ = ',';
for ( ei = BEI(e); ei; ei=ei->bei_parent ) {
ptr = lutil_strcopy(ptr, ei->bei_rdn.bv_val);
nptr = lutil_strcopy(nptr, ei->bei_nrdn.bv_val);
if ( ei->bei_parent ) {
*ptr++ = ',';
*nptr++ = ',';
}
}
ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
strcpy(ptr, be->be_suffix[0].bv_val);
strcpy(nptr, be->be_nsuffix[0].bv_val);
*ptr = '\0';
*nptr = '\0';
return 0;
}
@ -594,6 +598,11 @@ bdb_dn2id_add(
key.size = sizeof(ID);
key.flags = DB_DBT_USERMEM;
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
bdb_idl_cache_del( bdb, db, &key );
}
#endif
data.data = d;
data.size = sizeof(diskNode) + rlen + nrlen + 2;
data.flags = DB_DBT_USERMEM;
@ -648,6 +657,11 @@ bdb_dn2id_delete(
data.dlen = data.size;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
bdb_idl_cache_del( bdb, db, &key );
}
#endif
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
@ -717,54 +731,40 @@ bdb_dn2id_children(
Entry *e )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
DBT key, data;
DBC *cursor;
int rc;
ID id;
idNode *n;
diskNode d;
rc = bdb_dn2id(be, txn, dn, &id, flags);
if (rc != 0)
return rc;
DBTzero(&key);
key.size = sizeof(ID);
key.data = &e->e_id;
key.flags = DB_DBT_USERMEM;
ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
n = bdb_find_id_node(id, bdb->bi_tree);
ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);
if (!n->i_kids)
return DB_NOTFOUND;
else
return 0;
}
/* Since we don't store IDLs for onelevel or subtree, we have to construct
* them on the fly... Perhaps the i_kids tree ought to just be an IDL?
*/
static int
insert_one(
void *v_n,
void *v_ids
)
{
idNode *n = v_n;
ID *ids = v_ids;
return bdb_idl_insert(ids, n->i_id);
}
static int
insert_sub(
void *v_n,
void *v_ids
)
{
idNode *n = v_n;
ID *ids = v_ids;
int rc;
rc = bdb_idl_insert(ids, n->i_id);
if (rc == 0) {
ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr);
rc = avl_apply(n->i_kids, insert_sub, ids, -1, AVL_INORDER);
ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr);
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, &key, NULL );
if ( rc != LDAP_NO_SUCH_OBJECT ) {
sl_free( key.data, o->o_tmpmemctx );
return rc;
}
}
#endif
DBTzero(&data);
data.ulen = sizeof(d);
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
data.dlen = sizeof(d);
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
if ( rc == 0 ) {
rc = cursor->c_get( cursor, &key, &data, DB_NEXT_DUP );
}
cursor->c_close( cursor );
return rc;
}

View File

@ -295,6 +295,146 @@ bdb_show_key(
}
}
#ifdef SLAP_IDL_CACHE
/* Find a db/key pair in the IDL cache. If ids is non-NULL,
* copy the cached IDL into it, otherwise just return the status.
*/
int
bdb_idl_cache_get(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID *ids )
{
bdb_idl_cache_entry_t idl_tmp;
bdb_idl_cache_entry_t *matched_idl_entry;
DBT2bv( key, &idl_tmp.kstr );
idl_tmp.db = db;
ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock );
matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
bdb_idl_entry_cmp );
if ( matched_idl_entry != NULL ) {
if ( matched_idl_entry->idl && ids )
BDB_IDL_CPY( ids, matched_idl_entry->idl );
ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_DELETE( bdb, matched_idl_entry );
IDL_LRU_ADD( bdb, matched_idl_entry );
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
if ( matched_idl_entry->idl )
return LDAP_SUCCESS;
else
return DB_NOTFOUND;
}
ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock );
return LDAP_NO_SUCH_OBJECT;
}
void
bdb_idl_cache_put(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID *ids,
int rc )
{
bdb_idl_cache_entry_t idl_tmp;
bdb_idl_cache_entry_t *ee;
ee = (bdb_idl_cache_entry_t *) ch_malloc(
sizeof( bdb_idl_cache_entry_t ) );
ee->db = db;
if ( rc == DB_NOTFOUND) {
ee->idl = NULL;
} else {
ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) );
BDB_IDL_CPY( ee->idl, ids );
}
ee->idl_lru_prev = NULL;
ee->idl_lru_next = NULL;
ber_dupbv( &ee->kstr, &idl_tmp.kstr );
ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee,
bdb_idl_entry_cmp, avl_dup_error ))
{
ch_free( ee->kstr.bv_val );
ch_free( ee->idl );
ch_free( ee );
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
return;
}
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_ADD( bdb, ee );
if ( ++bdb->bi_idl_cache_size > bdb->bi_idl_cache_max_size ) {
int i = 0;
while ( bdb->bi_idl_lru_tail != NULL && i < 10 ) {
ee = bdb->bi_idl_lru_tail;
if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee,
bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( INDEX, ERR,
"bdb_idl_cache_put: AVL delete failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_put: "
"AVL delete failed\n",
0, 0, 0 );
#endif
}
IDL_LRU_DELETE( bdb, ee );
i++;
--bdb->bi_idl_cache_size;
ch_free( ee->kstr.bv_val );
ch_free( ee->idl );
ch_free( ee );
}
}
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
}
void
bdb_idl_cache_del(
struct bdb_info *bdb,
DB *db,
DBT *key )
{
bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
DBT2bv( key, &idl_tmp.kstr );
idl_tmp.db = db;
ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
bdb_idl_entry_cmp );
if ( matched_idl_entry != NULL ) {
if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( INDEX, ERR,
"bdb_idl_cache_del: AVL delete failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY, "=> bdb_idl_cache_del: "
"AVL delete failed\n",
0, 0, 0 );
#endif
}
--bdb->bi_idl_cache_size;
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_DELETE( bdb, matched_idl_entry );
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
free( matched_idl_entry->kstr.bv_val );
if ( matched_idl_entry->idl )
free( matched_idl_entry->idl );
free( matched_idl_entry );
}
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
}
#endif
int
bdb_idl_fetch_key(
BackendDB *be,
@ -312,9 +452,6 @@ bdb_idl_fetch_key(
size_t len;
int rc2;
int flags = bdb->bi_db_opflags | DB_MULTIPLE;
#ifdef SLAP_IDL_CACHE
bdb_idl_cache_entry_t idl_tmp;
#endif
/* If using BerkeleyDB 4.0, the buf must be large enough to
* grab the entire IDL in one get(), otherwise BDB will leak
@ -348,27 +485,9 @@ bdb_idl_fetch_key(
assert( ids != NULL );
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_entry_t *matched_idl_entry;
DBT2bv( key, &idl_tmp.kstr );
idl_tmp.db = db;
ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock );
matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
bdb_idl_entry_cmp );
if ( matched_idl_entry != NULL ) {
if ( matched_idl_entry->idl )
BDB_IDL_CPY( ids, matched_idl_entry->idl );
ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock );
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_DELETE( bdb, matched_idl_entry );
IDL_LRU_ADD( bdb, matched_idl_entry );
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
if ( matched_idl_entry->idl )
return LDAP_SUCCESS;
else
return DB_NOTFOUND;
}
ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock );
if ( bdb->bi_idl_cache_size ) {
rc = bdb_idl_cache_get( bdb, db, key, ids );
if ( rc != LDAP_NO_SUCH_OBJECT ) return rc;
}
#endif
@ -491,58 +610,7 @@ bdb_idl_fetch_key(
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_entry_t *ee;
ee = (bdb_idl_cache_entry_t *) ch_malloc(
sizeof( bdb_idl_cache_entry_t ) );
ee->db = db;
if ( rc == DB_NOTFOUND) {
ee->idl = NULL;
} else {
ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) );
BDB_IDL_CPY( ee->idl, ids );
}
ee->idl_lru_prev = NULL;
ee->idl_lru_next = NULL;
ber_dupbv( &ee->kstr, &idl_tmp.kstr );
ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee,
bdb_idl_entry_cmp, avl_dup_error ))
{
ch_free( ee->kstr.bv_val );
ch_free( ee->idl );
ch_free( ee );
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
return rc;
}
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_ADD( bdb, ee );
if ( ++bdb->bi_idl_cache_size > bdb->bi_idl_cache_max_size ) {
int i = 0;
while ( bdb->bi_idl_lru_tail != NULL && i < 10 ) {
ee = bdb->bi_idl_lru_tail;
if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee,
bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( INDEX, ERR,
"bdb_idl_fetch_key: AVL delete failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
"AVL delete failed\n",
0, 0, 0 );
#endif
}
IDL_LRU_DELETE( bdb, ee );
i++;
--bdb->bi_idl_cache_size;
ch_free( ee->kstr.bv_val );
ch_free( ee->idl );
ch_free( ee );
}
}
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
bdb_idl_cache_put( bdb, db, key, ids, rc );
}
#endif
@ -582,35 +650,7 @@ bdb_idl_insert_key(
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_size ) {
bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
DBT2bv( key, &idl_tmp.kstr );
idl_tmp.db = db;
ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
bdb_idl_entry_cmp );
if ( matched_idl_entry != NULL ) {
if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( INDEX, ERR,
"bdb_idl_fetch_key: AVL delete failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
"AVL delete failed\n",
0, 0, 0 );
#endif
}
--bdb->bi_idl_cache_size;
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_DELETE( bdb, matched_idl_entry );
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
free( matched_idl_entry->kstr.bv_val );
if ( matched_idl_entry->idl )
free( matched_idl_entry->idl );
free( matched_idl_entry );
}
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
bdb_idl_cache_del( bdb, db, key );
}
#endif
@ -807,35 +847,7 @@ bdb_idl_delete_key(
#ifdef SLAP_IDL_CACHE
if ( bdb->bi_idl_cache_max_size ) {
bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp;
DBT2bv( key, &idl_tmp.kstr );
idl_tmp.db = db;
ldap_pvt_thread_rdwr_wlock( &bdb->bi_idl_tree_rwlock );
matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp,
bdb_idl_entry_cmp );
if ( matched_idl_entry != NULL ) {
if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry,
bdb_idl_entry_cmp ) == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( INDEX, ERR,
"bdb_idl_fetch_key: AVL delete failed\n",
0, 0, 0 );
#else
Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: "
"AVL delete failed\n",
0, 0, 0 );
#endif
}
--bdb->bi_idl_cache_size;
ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock );
IDL_LRU_DELETE( bdb, matched_idl_entry );
ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock );
free( matched_idl_entry->kstr.bv_val );
if ( matched_idl_entry->idl )
free( matched_idl_entry->idl );
free( matched_idl_entry );
}
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_idl_tree_rwlock );
bdb_idl_cache_del( bdb, db, key );
}
#endif

View File

@ -145,6 +145,26 @@ void bdb_entry_free ( Entry *e );
*/
#ifdef SLAP_IDL_CACHE
int bdb_idl_entry_cmp( const void*, const void* );
int bdb_idl_cache_get(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID *ids );
void
bdb_idl_cache_put(
struct bdb_info *bdb,
DB *db,
DBT *key,
ID *ids,
int rc );
void
bdb_idl_cache_del(
struct bdb_info *bdb,
DB *db,
DBT *key );
#endif
unsigned bdb_idl_search( ID *ids, ID id );