Hierarchical cache management.

This commit is contained in:
Howard Chu 2003-04-16 16:23:36 +00:00
parent d9d5912383
commit 377bccbc6c
17 changed files with 1030 additions and 1445 deletions

View file

@ -18,13 +18,13 @@ bdb_add(Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct berval pdn;
Entry *p = NULL;
const char *text;
Entry *p;
EntryInfo *ei;
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
DB_TXN *ltid = NULL;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
#ifdef BDB_SUBENTRIES
int subentry;
@ -137,42 +137,37 @@ retry: /* transaction retry */
dnParent( &op->oq_add.rs_e->e_nname, &pdn );
}
if( pdn.bv_len != 0 ) {
Entry *matched = NULL;
/* get parent */
rs->sr_err = bdb_dn2entry_r( op->o_bd, ltid, &pdn, &p, &matched, 0, locker, &lock );
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( p == NULL ) {
if ( matched != NULL ) {
rs->sr_matched = ch_strdup( matched->e_dn );
rs->sr_ref = is_entry_referral( matched )
? get_entry_referrals( op, matched )
: NULL;
bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, matched );
matched = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,
NULL, &op->oq_add.rs_e->e_name, LDAP_SCOPE_DEFAULT );
}
/* get entry or parent */
rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->ora_e->e_nname, &ei,
1, locker, &lock, op->o_tmpmemctx );
switch( rs->sr_err ) {
case 0:
rs->sr_err = LDAP_ALREADY_EXISTS;
goto return_results;
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
p = ei->bei_e;
if ( p ) {
if ( !bvmatch( &pdn, &p->e_nname ) ) {
rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
op->o_tmpmemctx );
rs->sr_ref = is_entry_referral( p )
? get_entry_referrals( op, p )
: NULL;
bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
p = NULL;
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"bdb_add: parent does not exist\n", 0, 0, 0 );
@ -185,7 +180,7 @@ retry: /* transaction retry */
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
ch_free( (char *)rs->sr_matched );
op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
@ -370,8 +365,26 @@ retry: /* transaction retry */
goto return_results;;
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_add: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_add: txn_begin(2) failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err, 0 );
#endif
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
/* dn2id index */
rs->sr_err = bdb_dn2id_add( op->o_bd, ltid, &pdn, op->oq_add.rs_e );
rs->sr_err = bdb_dn2id_add( op->o_bd, lt2, &pdn, op->oq_add.rs_e );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
@ -395,7 +408,7 @@ retry: /* transaction retry */
}
/* id2entry index */
rs->sr_err = bdb_id2entry_add( op->o_bd, ltid, op->oq_add.rs_e );
rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->oq_add.rs_e );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR, "bdb_add: id2entry_add failed\n", 0, 0, 0 );
@ -415,7 +428,7 @@ retry: /* transaction retry */
}
/* attribute indexes */
rs->sr_err = bdb_index_entry_add( op, ltid, op->oq_add.rs_e );
rs->sr_err = bdb_index_entry_add( op, lt2, op->oq_add.rs_e );
if ( rs->sr_err != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
@ -434,7 +447,11 @@ retry: /* transaction retry */
rs->sr_text = "index generation failed";
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
if( op->o_noop ) {
if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
@ -454,32 +471,21 @@ retry: /* transaction retry */
rs->sr_text = "txn_prepare failed";
} else {
int ret = bdb_cache_add_entry_rw(bdb->bi_dbenv,
&bdb->bi_cache, op->oq_add.rs_e, CACHE_WRITE_LOCK,
locker, &lock);
switch ( ret ) {
case 0:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
default:
ret = LDAP_OTHER;
struct berval nrdn;
if (pdn.bv_len) {
nrdn.bv_val = op->ora_e->e_nname.bv_val;
nrdn.bv_len = pdn.bv_val - nrdn.bv_val - 1;
} else {
nrdn = op->ora_e->e_nname;
}
if ( ret ) {
if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
rs->sr_text = "cache add & txn_abort failed";
} else {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "cache add failed";
}
bdb_cache_add(bdb, ei, op->oq_add.rs_e, &nrdn, locker );
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
rs->sr_text = "txn_commit failed";
} else {
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
rs->sr_text = "txn_commit failed";
} else {
rs->sr_err = LDAP_SUCCESS;
}
rs->sr_err = LDAP_SUCCESS;
}
}
}
@ -497,9 +503,6 @@ retry: /* transaction retry */
op->o_noop ? " (no-op)" : "", op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
#endif
rs->sr_text = NULL;
if ( !noop ) {
bdb_cache_entry_commit( op->oq_add.rs_e );
}
}
else {
#ifdef NEW_LOGGING

View file

@ -82,16 +82,39 @@ typedef struct bdb_idl_cache_entry_s {
} bdb_idl_cache_entry_t;
#endif
/* BDB backend specific entry info */
typedef struct bdb_entry_info {
struct bdb_entry_info *bei_parent;
ID bei_id;
int bei_state;
#define CACHE_ENTRY_DELETED 1
/*
* remaining fields require backend cache lock to access
*/
struct berval bei_nrdn;
struct berval bei_rdn;
Entry *bei_e;
Avlnode *bei_kids;
ldap_pvt_thread_mutex_t bei_kids_mutex;
struct bdb_entry_info *bei_lrunext; /* for cache lru list */
struct bdb_entry_info *bei_lruprev;
} EntryInfo;
#undef BEI
#define BEI(e) ((EntryInfo *) ((e)->e_private))
/* for the in-core cache of entries */
typedef struct bdb_cache {
int c_maxsize;
int c_cursize;
Avlnode *c_dntree;
Avlnode *c_idtree;
Entry *c_lruhead; /* lru - add accessed entries here */
Entry *c_lrutail; /* lru - rem lru entries from here */
ldap_pvt_thread_rdwr_t c_rwlock;
ldap_pvt_thread_mutex_t lru_mutex;
int c_maxsize;
int c_cursize;
EntryInfo c_dntree;
Avlnode *c_idtree;
EntryInfo *c_lruhead; /* lru - add accessed entries here */
EntryInfo *c_lrutail; /* lru - rem lru entries from here */
ldap_pvt_thread_rdwr_t c_rwlock;
ldap_pvt_thread_mutex_t lru_mutex;
} Cache;
#define CACHE_READ_LOCK 0

View file

@ -21,7 +21,7 @@ bdb_bind( Operation *op, SlapReply *rs )
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *e;
Attribute *a;
Entry *matched;
EntryInfo *ei;
#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
char krbname[MAX_K_NAME_SZ + 1];
AttributeDescription *krbattr = slap_schema.si_ad_krbName;
@ -59,7 +59,8 @@ bdb_bind( Operation *op, SlapReply *rs )
dn2entry_retry:
/* get entry with reader lock */
rs->sr_err = bdb_dn2entry_r( op->o_bd, NULL, &op->o_req_ndn, &e, &matched, 0, locker, &lock );
rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &op->o_req_ndn, &ei, 1,
locker, &lock, op->o_tmpmemctx );
switch(rs->sr_err) {
case DB_NOTFOUND:
@ -78,17 +79,17 @@ dn2entry_retry:
return rs->sr_err;
}
if ( e == NULL ) {
if( matched != NULL ) {
rs->sr_ref = is_entry_referral( matched )
? get_entry_referrals( op, matched )
e = ei->bei_e;
if ( rs->sr_err == DB_NOTFOUND ) {
if( e != NULL ) {
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
if (rs->sr_ref)
rs->sr_matched = ch_strdup( matched->e_name.bv_val );
bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
matched = NULL;
rs->sr_matched = ch_strdup( e->e_name.bv_val );
bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,
NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );

File diff suppressed because it is too large Load diff

View file

@ -17,8 +17,8 @@ int
bdb_compare( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *matched;
Entry *e;
EntryInfo *ei;
Attribute *a;
int manageDSAit = get_manageDSAit( op );
@ -36,7 +36,7 @@ bdb_compare( Operation *op, SlapReply *rs )
dn2entry_retry:
/* get entry */
rs->sr_err = bdb_dn2entry_r( op->o_bd, NULL, &op->o_req_ndn, &e, &matched, 0, locker, &lock );
rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &op->o_req_ndn, &ei, 1, locker, &lock, op->o_tmpmemctx );
switch( rs->sr_err ) {
case DB_NOTFOUND:
@ -54,14 +54,15 @@ dn2entry_retry:
goto return_results;
}
if ( e == NULL ) {
if ( matched != NULL ) {
rs->sr_matched = ch_strdup( matched->e_dn );
rs->sr_ref = is_entry_referral( matched )
? get_entry_referrals( op, matched )
e = ei->bei_e;
if ( rs->sr_err == DB_NOTFOUND ) {
if ( e != NULL ) {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
matched = NULL;
bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,

View file

@ -21,14 +21,15 @@ bdb_delete( Operation *op, SlapReply *rs )
struct berval pdn = {0, NULL};
Entry *e = NULL;
Entry *p = NULL;
EntryInfo *ei = NULL, *eip = NULL;
int manageDSAit = get_manageDSAit( op );
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
DB_TXN *ltid = NULL;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
u_int32_t locker = 0;
DB_LOCK lock;
DB_LOCK lock, plock;
int noop = 0;
@ -47,6 +48,7 @@ bdb_delete( Operation *op, SlapReply *rs )
retry: /* transaction retry */
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
@ -99,27 +101,38 @@ retry: /* transaction retry */
dnParent( &op->o_req_ndn, &pdn );
}
if( pdn.bv_len != 0 ) {
/* get parent */
rs->sr_err = bdb_dn2entry_r( op->o_bd, ltid, &pdn, &p, NULL, 0, locker, &lock );
/* get entry */
rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->o_req_ndn, &ei, 1,
locker, &lock, op->o_tmpmemctx );
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if( p == NULL) {
if ( rs->sr_err == 0 ) {
e = ei->bei_e;
eip = ei->bei_parent;
bdb_cache_find_entry_id( op->o_bd, ltid, eip->bei_id, &eip,
0, locker, &plock, op->o_tmpmemctx );
}
if ( eip ) {
p = eip->bei_e;
}
if ( pdn.bv_len != 0 ) {
if( p == NULL || !bvmatch( &pdn, &p->e_nname )) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
"<=- bdb_delete: parent does not exist\n", 0, 0, 0 );
@ -208,25 +221,6 @@ retry: /* transaction retry */
}
}
/* get entry for read/modify/write */
rs->sr_err = bdb_dn2entry_w( op->o_bd, ltid, &op->o_req_ndn, &e, &matched, DB_RMW, locker, &lock );
switch( rs->sr_err ) {
case 0:
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
goto retry;
case LDAP_BUSY:
rs->sr_text = "ldap server busy";
goto return_results;
default:
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( e == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ARGS,
@ -310,7 +304,27 @@ retry: /* transaction retry */
goto done;
}
rs->sr_err = bdb_dn2id_children( op->o_bd, ltid, &e->e_nname, 0 );
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_delete: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_delete: txn_begin(2) failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err, 0 );
#endif
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
/* Can't do it if we have kids */
rs->sr_err = ei->bei_kids ? 0 : bdb_dn2id_children( op->o_bd, lt2,
&e->e_nname, 0 );
if( rs->sr_err != DB_NOTFOUND ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -345,7 +359,7 @@ retry: /* transaction retry */
}
/* delete from dn2id */
rs->sr_err = bdb_dn2id_delete( op->o_bd, ltid, pdn.bv_val, e );
rs->sr_err = bdb_dn2id_delete( op->o_bd, lt2, pdn.bv_val, e );
if ( rs->sr_err != 0 ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -366,7 +380,7 @@ retry: /* transaction retry */
}
/* delete from id2entry */
rs->sr_err = bdb_id2entry_delete( op->o_bd, ltid, e );
rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e );
if ( rs->sr_err != 0 ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -388,7 +402,7 @@ retry: /* transaction retry */
}
/* delete indices for old attributes */
rs->sr_err = bdb_index_entry_del( op, ltid, e );
rs->sr_err = bdb_index_entry_del( op, lt2, e );
if ( rs->sr_err != LDAP_SUCCESS ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -406,6 +420,11 @@ retry: /* transaction retry */
rs->sr_err = LDAP_OTHER;
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
#if 0 /* Do we want to reclaim deleted IDs? */
ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
@ -423,6 +442,8 @@ retry: /* transaction retry */
rs->sr_err = LDAP_SUCCESS;
}
} else {
bdb_cache_delete_entry( &bdb->bi_cache, e, bdb->bi_dbenv,
locker, &lock );
rs->sr_err = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;
@ -477,7 +498,11 @@ return_results:
done:
/* free entry */
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
if ( rs->sr_err == LDAP_SUCCESS ) {
bdb_entry_return( e );
} else {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
}
}
if( ltid != NULL ) {

View file

@ -15,48 +15,60 @@
/*
* dn2entry - look up dn in the cache/indexes and return the corresponding
* entry.
* entry. If the requested DN is not found and matched is TRUE, return info
* for the closest ancestor of the DN. Otherwise e is NULL.
*/
int
bdb_dn2entry_rw(
bdb_dn2entry(
BackendDB *be,
DB_TXN *tid,
struct berval *dn,
Entry **e,
Entry **matched,
int flags,
int rw,
EntryInfo **e,
int matched,
u_int32_t locker,
DB_LOCK *lock )
DB_LOCK *lock,
void *ctx )
{
EntryInfo *ei = NULL;
int rc;
ID id, id2 = 0;
#ifdef NEW_LOGGING
LDAP_LOG ( CACHE, ARGS, "bdb_dn2entry_rw(\"%s\")\n", dn->bv_val, 0, 0 );
LDAP_LOG ( CACHE, ARGS, "bdb_dn2entry(\"%s\")\n", dn->bv_val, 0, 0 );
#else
Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry_rw(\"%s\")\n",
Debug(LDAP_DEBUG_TRACE, "bdb_dn2entry(\"%s\")\n",
dn->bv_val, 0, 0 );
#endif
*e = NULL;
if( matched != NULL ) {
*matched = NULL;
rc = bdb_dn2id_matched( be, tid, dn, &id, &id2, flags );
rc = bdb_cache_find_entry_ndn2id( be, tid, dn, &ei, locker, ctx );
if ( rc ) {
if ( matched && rc == DB_NOTFOUND ) {
/* Set the return value, whether we have its entry
* or not.
*/
*e = ei;
if ( ei && ei->bei_id )
bdb_cache_find_entry_id( be, tid, ei->bei_id,
&ei, 1, locker, lock, ctx );
else if ( ei )
bdb_cache_entryinfo_unlock( ei );
} else if ( ei ) {
bdb_cache_entryinfo_unlock( ei );
}
} else {
rc = bdb_dn2id( be, tid, dn, &id, flags );
}
if( rc != 0 ) {
return rc;
}
if( id2 == 0 ) {
rc = bdb_id2entry_rw( be, tid, id, e, rw, locker, lock );
} else {
rc = bdb_id2entry_r( be, tid, id2, matched, locker, lock );
rc = bdb_cache_find_entry_id( be, tid, ei->bei_id, &ei, 1,
locker, lock, ctx );
if ( rc == 0 ) {
*e = ei;
} else if ( matched && rc == DB_NOTFOUND ) {
/* always return EntryInfo */
ei = ei->bei_parent;
bdb_cache_find_entry_id( be, tid, ei->bei_id, &ei, 1,
locker, lock, ctx );
*e = ei;
}
}
return rc;

View file

@ -299,7 +299,7 @@ bdb_dn2id(
DB_TXN *txn,
struct berval *dn,
ID *id,
int flags )
void *ctx )
{
int rc;
DBT key, data;
@ -314,14 +314,9 @@ bdb_dn2id(
assert (id);
*id = bdb_cache_find_entry_ndn2id(be, &bdb->bi_cache, dn);
if (*id != NOID) {
return 0;
}
DBTzero( &key );
key.size = dn->bv_len + 2;
key.data = ch_malloc( key.size );
key.data = sl_malloc( key.size, ctx );
((char *)key.data)[0] = DN_BASE_PREFIX;
AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 );
@ -332,7 +327,7 @@ bdb_dn2id(
data.flags = DB_DBT_USERMEM;
/* fetch it */
rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags | flags);
rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
if( rc != 0 ) {
#ifdef NEW_LOGGING
@ -352,134 +347,7 @@ bdb_dn2id(
#endif
}
ch_free( key.data );
return rc;
}
int
bdb_dn2id_matched(
BackendDB *be,
DB_TXN *txn,
struct berval *in,
ID *id,
ID *id2,
int flags )
{
int rc;
DBT key, data;
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
char *buf;
struct berval dn;
ID cached_id;
#ifdef NEW_LOGGING
LDAP_LOG ( INDEX, ARGS,
"=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val, 0, 0 );
#endif
DBTzero( &key );
key.size = in->bv_len + 2;
buf = ch_malloc( key.size );
key.data = buf;
dn.bv_val = buf+1;
dn.bv_len = key.size - 2;
AC_MEMCPY( dn.bv_val, in->bv_val, key.size - 1 );
/* store the ID */
DBTzero( &data );
data.data = id;
data.ulen = sizeof(ID);
data.flags = DB_DBT_USERMEM;
while(1) {
dn.bv_val[-1] = DN_BASE_PREFIX;
*id = NOID;
/* lookup cache */
cached_id = bdb_cache_find_entry_ndn2id(be, &bdb->bi_cache, &dn);
if (cached_id != NOID) {
rc = 0;
*id = cached_id;
if ( dn.bv_val != buf+1 ) {
*id2 = *id;
}
break;
} else {
/* fetch it */
rc = db->get(db, txn, &key, &data, bdb->bi_db_opflags | flags );
}
if( rc == DB_NOTFOUND ) {
struct berval pdn;
if ( ! be_issuffix( be, &dn ) ) {
dnParent( &dn, &pdn );
} else {
#ifdef NEW_LOGGING
LDAP_LOG ( INDEX, DETAIL1,
"<= bdb_dn2id_matched: no match\n", 0, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"<= bdb_dn2id_matched: no match\n",
0, 0, 0 );
#endif
break;
}
key.size = pdn.bv_len + 2;
dn = pdn;
key.data = pdn.bv_val - 1;
} else if ( rc == 0 ) {
if( data.size != sizeof( ID ) ) {
#ifdef NEW_LOGGING
LDAP_LOG ( INDEX, DETAIL1,
"<= bdb_dn2id_matched: get size mismatch:"
"expected %ld, got %ld\n",
(long) sizeof(ID), (long) data.size, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"<= bdb_dn2id_matched: get size mismatch: "
"expected %ld, got %ld\n",
(long) sizeof(ID), (long) data.size, 0 );
#endif
}
if( dn.bv_val != buf+1 ) {
*id2 = *id;
}
#ifdef NEW_LOGGING
LDAP_LOG ( INDEX, DETAIL1,
"<= bdb_dn2id_matched: id=0x%08lx: %s %s\n",
(long) *id, *id2 == 0 ? "entry" : "matched", dn.bv_val );
#else
Debug( LDAP_DEBUG_TRACE,
"<= bdb_dn2id_matched: id=0x%08lx: %s %s\n",
(long) *id, *id2 == 0 ? "entry" : "matched", dn.bv_val );
#endif
break;
} else {
#ifdef NEW_LOGGING
LDAP_LOG ( INDEX, ERR,
"<= bdb_dn2id_matched: get failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#else
Debug( LDAP_DEBUG_ANY,
"<= bdb_dn2id_matched: get failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#endif
break;
}
}
ch_free( buf );
sl_free( key.data, ctx );
return rc;
}
@ -523,11 +391,11 @@ bdb_dn2id_children(
#ifdef NEW_LOGGING
LDAP_LOG ( INDEX, DETAIL1,
"<= bdb_dn2id_children( %s ): %schildren (%d)\n",
"<= bdb_dn2id_children( %s ): %s (%d)\n",
dn->bv_val, rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
db_strerror(rc)), rc );
#else
Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children( %s ): %schildren (%d)\n",
Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children( %s ): %s (%d)\n",
dn->bv_val,
rc == 0 ? "" : ( rc == DB_NOTFOUND ? "no " :
db_strerror(rc) ), rc );

View file

@ -76,14 +76,11 @@ int bdb_id2entry_update(
return bdb_id2entry_put(be, tid, e, 0);
}
int bdb_id2entry_rw(
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
ID id,
Entry **e,
int rw,
u_int32_t locker,
DB_LOCK *lock )
Entry **e )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_id2entry->bdi_db;
@ -100,12 +97,8 @@ int bdb_id2entry_rw(
DBTzero( &data );
data.flags = DB_DBT_MALLOC;
if ((*e = bdb_cache_find_entry_id(bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock)) != NULL) {
return 0;
}
/* fetch it */
rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags | ( rw ? DB_RMW : 0 ));
rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags );
if( rc != 0 ) {
return rc;
@ -128,38 +121,6 @@ int bdb_id2entry_rw(
#ifdef BDB_HIER
bdb_fix_dn(be, id, *e);
#endif
ret = bdb_cache_add_entry_rw( bdb->bi_dbenv,
&bdb->bi_cache, *e, rw, locker, lock);
while ( ret == 1 || ret == -1 ) {
Entry *ee;
int add_loop_cnt = 0;
if ( (*e)->e_private != NULL ) {
free ((*e)->e_private);
}
(*e)->e_private = NULL;
if ( (ee = bdb_cache_find_entry_id
(bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock) ) != NULL) {
bdb_entry_return ( *e );
*e = ee;
return 0;
}
if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
bdb_entry_return ( *e );
*e = NULL;
return LDAP_BUSY;
}
}
if ( ret != 0 ) {
if ( (*e)->e_private != NULL )
free ( (*e)->e_private );
bdb_entry_return( *e );
*e = NULL;
}
rc = ret;
}
if (rc == 0) {
bdb_cache_entry_commit(*e);
}
return rc;
@ -175,8 +136,6 @@ int bdb_id2entry_delete(
DBT key;
int rc;
bdb_cache_delete_entry(&bdb->bi_cache, e);
DBTzero( &key );
key.data = (char *) &e->e_id;
key.size = sizeof(ID);
@ -252,7 +211,7 @@ int bdb_entry_release(
bdb_unlocked_cache_return_entry_rw( &bdb->bi_cache, e, rw );
} else {
bdb_cache_return_entry_rw( bdb->bi_dbenv, &bdb->bi_cache, e, rw, &boi->boi_lock );
ch_free( boi );
sl_free( boi, o->o_tmpmemctx );
o->o_private = NULL;
}
} else {
@ -279,6 +238,7 @@ int bdb_entry_get(
struct bdb_op_info *boi = NULL;
DB_TXN *txn = NULL;
Entry *e;
EntryInfo *ei;
int rc;
const char *at_name = at->ad_cname.bv_val;
@ -321,7 +281,7 @@ int bdb_entry_get(
dn2entry_retry:
/* can we find entry */
rc = bdb_dn2entry_rw( op->o_bd, txn, ndn, &e, NULL, 0, rw, locker, &lock );
rc = bdb_dn2entry( op->o_bd, txn, ndn, &ei, 0, locker, &lock, op->o_tmpmemctx );
switch( rc ) {
case DB_NOTFOUND:
case 0:
@ -342,6 +302,7 @@ dn2entry_retry:
}
return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
}
if (ei) e = ei->bei_e;
if (e == NULL) {
#ifdef NEW_LOGGING
LDAP_LOG( BACK_BDB, INFO,
@ -417,7 +378,7 @@ return_results:
* release it later??
*/
if ( op && !boi ) {
boi = ch_calloc(1,sizeof(struct bdb_op_info));
boi = sl_calloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx);
boi->boi_lock = lock;
op->o_private = boi;
}

View file

@ -502,8 +502,6 @@ bdb_db_destroy( BackendDB *be )
#endif
}
bdb_cache_release_all (&bdb->bi_cache);
rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
bdb->bi_dbenv = NULL;
if( rc != 0 ) {

View file

@ -41,6 +41,7 @@ int bdb_modify_internal(
return LDAP_INSUFFICIENT_ACCESS;
}
/* save_attrs will be disposed of by bdb_cache_modify */
save_attrs = e->e_attrs;
e->e_attrs = attrs_dup( e->e_attrs );
@ -255,13 +256,6 @@ int bdb_modify_internal(
}
}
/* If we've done repeated mods on a cached entry, then e_attrs
* is no longer contiguous with the entry.
*/
if( (void *) save_attrs != (void *) (e+1)) {
attrs_free( save_attrs );
}
return rc;
}
@ -270,13 +264,14 @@ int
bdb_modify( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *matched = NULL;
Entry *e = NULL;
EntryInfo *ei = NULL;
int manageDSAit = get_manageDSAit( op );
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
DB_TXN *ltid = NULL;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
Entry dummy;
u_int32_t locker = 0;
DB_LOCK lock;
@ -297,8 +292,8 @@ bdb_modify( Operation *op, SlapReply *rs )
if( 0 ) {
retry: /* transaction retry */
if( e != NULL ) {
bdb_cache_delete_entry(&bdb->bi_cache, e);
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
}
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1, "bdb_modify: retrying...\n", 0, 0, 0 );
@ -356,8 +351,9 @@ retry: /* transaction retry */
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
/* get entry */
rs->sr_err = bdb_dn2entry_w( op->o_bd, ltid, &op->o_req_ndn, &e, &matched, 0, locker, &lock );
/* get entry or ancestor */
rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->o_req_ndn, &ei, 1,
locker, &lock, op->o_tmpmemctx );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
@ -384,15 +380,16 @@ retry: /* transaction retry */
}
}
e = ei->bei_e;
/* acquire and lock entry */
if ( e == NULL ) {
if ( matched != NULL ) {
rs->sr_matched = ch_strdup( matched->e_dn );
rs->sr_ref = is_entry_referral( matched )
? get_entry_referrals( op, matched )
if ( rs->sr_err == DB_NOTFOUND ) {
if ( e != NULL ) {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, matched);
matched = NULL;
bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, e);
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,
@ -440,9 +437,27 @@ retry: /* transaction retry */
}
#endif
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_modify: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_modify: txn_begin(2) failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err, 0 );
#endif
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
/* Modify the entry */
rs->sr_err = bdb_modify_internal( op, ltid, op->oq_modify.rs_modlist, e,
&rs->sr_text, textbuf, textlen );
dummy = *e;
rs->sr_err = bdb_modify_internal( op, lt2, op->oq_modify.rs_modlist,
&dummy, &rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
@ -465,7 +480,7 @@ retry: /* transaction retry */
}
/* change the entry itself */
rs->sr_err = bdb_id2entry_update( op->o_bd, ltid, e );
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
if ( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
@ -483,6 +498,11 @@ retry: /* transaction retry */
rs->sr_text = "entry update failed";
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
if( op->o_noop ) {
if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
@ -492,6 +512,7 @@ retry: /* transaction retry */
rs->sr_err = LDAP_SUCCESS;
}
} else {
bdb_cache_modify( e, dummy.e_attrs, bdb->bi_dbenv, locker, &lock );
rs->sr_err = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;

View file

@ -24,14 +24,15 @@ bdb_modrdn( Operation *op, SlapReply *rs )
int isroot = -1;
Entry *e = NULL;
Entry *p = NULL;
Entry *matched;
EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
/* LDAP v2 supporting correct attribute handling. */
LDAPRDN new_rdn = NULL;
LDAPRDN old_rdn = NULL;
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
DB_TXN * ltid = NULL;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
Entry dummy, *save;
ID id;
@ -46,7 +47,7 @@ bdb_modrdn( Operation *op, SlapReply *rs )
int manageDSAit = get_manageDSAit( op );
u_int32_t locker = 0;
DB_LOCK lock;
DB_LOCK lock, plock, nplock;
int noop = 0;
@ -68,7 +69,6 @@ bdb_modrdn( Operation *op, SlapReply *rs )
if( 0 ) {
retry: /* transaction retry */
if (e != NULL) {
bdb_cache_delete_entry(&bdb->bi_cache, e);
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
e = NULL;
}
@ -137,7 +137,8 @@ retry: /* transaction retry */
op->o_private = &opinfo;
/* get entry */
rs->sr_err = bdb_dn2entry_w( op->o_bd, ltid, &op->o_req_ndn, &e, &matched, DB_RMW, locker, &lock );
rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->o_req_ndn, &ei, 1,
locker, &lock, op->o_tmpmemctx );
switch( rs->sr_err ) {
case 0:
@ -155,14 +156,15 @@ retry: /* transaction retry */
goto return_results;
}
if ( e == NULL ) {
if( matched != NULL ) {
rs->sr_matched = ch_strdup( matched->e_dn );
rs->sr_ref = is_entry_referral( matched )
? get_entry_referrals( op, matched )
e = ei->bei_e;
if ( rs->sr_err == DB_NOTFOUND ) {
if( e != NULL ) {
rs->sr_matched = ch_strdup( e->e_dn );
rs->sr_ref = is_entry_referral( e )
? get_entry_referrals( op, e )
: NULL;
bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, matched);
matched = NULL;
bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,
@ -203,7 +205,8 @@ retry: /* transaction retry */
}
#ifndef BDB_HIER
rs->sr_err = bdb_dn2id_children( op->o_bd, ltid, &e->e_nname, 0 );
rs->sr_err = ei->bei_kids ? 0 : bdb_dn2id_children( op->o_bd, ltid,
&e->e_nname, 0 );
if ( rs->sr_err != DB_NOTFOUND ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -269,7 +272,9 @@ retry: /* transaction retry */
/* Make sure parent entry exist and we can write its
* children.
*/
rs->sr_err = bdb_dn2entry_r( op->o_bd, ltid, &p_ndn, &p, NULL, 0, locker, &lock );
eip = ei->bei_parent;
rs->sr_err = bdb_cache_find_entry_id( op->o_bd, ltid,
eip->bei_id, &eip, 0, locker, &plock, op->o_tmpmemctx );
switch( rs->sr_err ) {
case 0:
@ -287,6 +292,7 @@ retry: /* transaction retry */
goto return_results;
}
p = eip->bei_e;
if( p == NULL) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
@ -459,11 +465,11 @@ retry: /* transaction retry */
/* newSuperior == entry being moved?, if so ==> ERROR */
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
rs->sr_err = bdb_dn2entry_r( op->o_bd,
ltid, np_ndn, &np, NULL, 0, locker, &lock );
rs->sr_err = bdb_dn2entry( op->o_bd, ltid, np_ndn,
&neip, 0, locker, &nplock, op->o_tmpmemctx );
switch( rs->sr_err ) {
case 0:
case 0: np = neip->bei_e;
case DB_NOTFOUND:
break;
case DB_LOCK_DEADLOCK:
@ -661,7 +667,11 @@ retry: /* transaction retry */
new_ndn.bv_val, 0, 0 );
#endif
rs->sr_err = bdb_dn2id ( op->o_bd, ltid, &new_ndn, &id, 0 );
/* Shortcut the search */
nei = neip ? neip : eip;
rs->sr_err = bdb_cache_find_entry_ndn2id ( op->o_bd, ltid, &new_ndn,
&nei, locker, op->o_tmpmemctx );
if ( nei ) bdb_cache_entryinfo_unlock( nei );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
@ -741,9 +751,31 @@ retry: /* transaction retry */
goto return_results;
}
}
/* nested transaction */
rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rs->sr_err != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_modrdn: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_modrdn: txn_begin(2) failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err, 0 );
#endif
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
dummy = *e;
save = e;
e = &dummy;
/* delete old one */
rs->sr_err = bdb_dn2id_delete( op->o_bd, ltid, p_ndn.bv_val, e );
rs->sr_err = bdb_dn2id_delete( op->o_bd, lt2, p_ndn.bv_val, e );
if ( rs->sr_err != 0 ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -755,14 +787,12 @@ retry: /* transaction retry */
goto return_results;
}
(void) bdb_cache_delete_entry(&bdb->bi_cache, e);
/* Binary format uses a single contiguous block, cannot
* free individual fields. But if a previous modrdn has
* already happened, must free the names.
* already happened, must free the names. The frees are
* done in bdb_cache_modrdn().
*/
#ifdef BDB_HIER
ch_free(e->e_name.bv_val);
e->e_name.bv_val = ch_malloc(new_dn.bv_len + new_ndn.bv_len + 2);
e->e_name.bv_len = new_dn.bv_len;
e->e_nname.bv_val = e->e_name.bv_val + new_dn.bv_len + 1;
@ -772,8 +802,6 @@ retry: /* transaction retry */
#else
if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
e->e_bv.bv_val + e->e_bv.bv_len ) {
ch_free(e->e_name.bv_val);
ch_free(e->e_nname.bv_val);
e->e_name.bv_val = NULL;
e->e_nname.bv_val = NULL;
}
@ -783,7 +811,7 @@ retry: /* transaction retry */
new_ndn.bv_val = NULL;
#endif
/* add new one */
rs->sr_err = bdb_dn2id_add( op->o_bd, ltid, np_ndn, e );
rs->sr_err = bdb_dn2id_add( op->o_bd, lt2, np_ndn, e );
if ( rs->sr_err != 0 ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -804,7 +832,7 @@ retry: /* transaction retry */
#endif
/* modify entry */
rs->sr_err = bdb_modify_internal( op, ltid, &mod[0], e,
rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], e,
&rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
@ -820,7 +848,7 @@ retry: /* transaction retry */
}
/* id2entry index */
rs->sr_err = bdb_id2entry_update( op->o_bd, ltid, e );
rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e );
if ( rs->sr_err != 0 ) {
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
@ -831,6 +859,11 @@ retry: /* transaction retry */
rs->sr_text = "entry update failed";
goto return_results;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
goto return_results;
}
if( op->o_noop ) {
if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
@ -849,21 +882,12 @@ retry: /* transaction retry */
if(( rs->sr_err=TXN_PREPARE( ltid, gid )) != 0 ) {
rs->sr_text = "txn_prepare failed";
} else {
if( bdb_cache_update_entry(&bdb->bi_cache, e) == -1 ) {
if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
rs->sr_text ="cache update & txn_abort failed";
} else {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "cache update failed";
}
bdb_cache_modrdn( save, &op->orr_newrdn, e, neip,
bdb->bi_dbenv, locker, &lock );
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
rs->sr_text = "txn_commit failed";
} else {
bdb_cache_entry_commit( e );
if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
rs->sr_text = "txn_commit failed";
} else {
rs->sr_err = LDAP_SUCCESS;
}
rs->sr_err = LDAP_SUCCESS;
}
}
}

View file

@ -20,8 +20,9 @@ bdb_exop_passwd( Operation *op, SlapReply *rs )
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
int rc;
Entry *e = NULL;
EntryInfo *ei;
struct berval hash = { 0, NULL };
DB_TXN *ltid = NULL;
DB_TXN *ltid = NULL, *lt2;
struct bdb_op_info opinfo;
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
@ -101,7 +102,6 @@ bdb_exop_passwd( Operation *op, SlapReply *rs )
if( 0 ) {
retry: /* transaction retry */
if ( e != NULL ) {
bdb_cache_delete_entry(&bdb->bi_cache, e);
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
}
#ifdef NEW_LOGGING
@ -150,7 +150,7 @@ retry: /* transaction retry */
op->o_private = &opinfo;
/* get entry */
rc = bdb_dn2entry_w( op->o_bd, ltid, &ndn, &e, NULL, 0 , locker, &lock);
rc = bdb_dn2entry( op->o_bd, ltid, &ndn, &ei, 0 , locker, &lock, op->o_tmpmemctx );
switch(rc) {
case DB_LOCK_DEADLOCK:
@ -168,6 +168,8 @@ retry: /* transaction retry */
goto done;
}
if ( ei ) e = ei->bei_e;
if( e == NULL ) {
rs->sr_text = "could not locate authorization entry";
rc = LDAP_NO_SUCH_OBJECT;
@ -198,9 +200,31 @@ retry: /* transaction retry */
goto done;
}
/* nested transaction */
rc = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
bdb->bi_db_opflags );
rs->sr_text = NULL;
if( rc != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
"bdb_exop_passwd: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_exop_passwd: txn_begin(2) failed: %s (%d)\n",
db_strerror(rs->sr_err), rs->sr_err, 0 );
#endif
rc = LDAP_OTHER;
rs->sr_text = "internal error";
goto done;
}
{
Modifications ml;
struct berval vals[2];
Entry dummy, *save;
save = e;
dummy = *e;
e = &dummy;
vals[0] = hash;
vals[1].bv_val = NULL;
@ -211,7 +235,7 @@ retry: /* transaction retry */
ml.sml_op = LDAP_MOD_REPLACE;
ml.sml_next = NULL;
rc = bdb_modify_internal( op, ltid,
rc = bdb_modify_internal( op, lt2,
&ml, e, &rs->sr_text, textbuf, textlen );
if ( (rc == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
@ -232,7 +256,7 @@ retry: /* transaction retry */
}
/* change the entry itself */
rc = bdb_id2entry_update( op->o_bd, ltid, e );
rc = bdb_id2entry_update( op->o_bd, lt2, e );
if( rc != 0 ) {
switch(rc) {
case DB_LOCK_DEADLOCK:
@ -242,11 +266,17 @@ retry: /* transaction retry */
rs->sr_text = "entry update failed";
rc = LDAP_OTHER;
}
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rc = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
}
if( rc == 0 ) {
if( op->o_noop ) {
rc = TXN_ABORT( ltid );
} else {
bdb_cache_modify( save, e->e_attrs,
bdb->bi_dbenv, locker, &lock );
rc = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;

View file

@ -52,13 +52,9 @@ bdb_db_cache(
/*
* dn2entry.c
*/
int bdb_dn2entry_rw LDAP_P(( BackendDB *be, DB_TXN *tid,
struct berval *dn, Entry **e, Entry **matched, int flags, int rw,
u_int32_t locker, DB_LOCK *lock));
#define bdb_dn2entry_r(be, tid, dn, e, m, f, locker, lock) \
bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0, locker, lock)
#define bdb_dn2entry_w(be, tid, dn, e, m, f, locker, lock) \
bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1, locker, lock)
int bdb_dn2entry LDAP_P(( BackendDB *be, DB_TXN *tid,
struct berval *dn, EntryInfo **e, int matched,
u_int32_t locker, DB_LOCK *lock, void *ctx));
/*
* dn2id.c
@ -68,15 +64,7 @@ int bdb_dn2id(
DB_TXN *tid,
struct berval *dn,
ID *id,
int flags );
int bdb_dn2id_matched(
BackendDB *be,
DB_TXN *tid,
struct berval *dn,
ID *id,
ID *id2,
int flags );
void *ctx );
int bdb_dn2id_add(
BackendDB *be,
@ -143,18 +131,11 @@ int bdb_id2entry_delete(
DB_TXN *tid,
Entry *e);
int bdb_id2entry_rw(
int bdb_id2entry(
BackendDB *be,
DB_TXN *tid,
ID id,
Entry **e,
int rw,
u_int32_t locker,
DB_LOCK *lock );
#define bdb_id2entry_r(be, tid, id, e, locker, lock) \
bdb_id2entry_rw((be), (tid), (id), (e), 0, locker, lock)
#define bdb_id2entry_w(be, tid, id, e, locker, lock) \
bdb_id2entry_rw((be), (tid), (id), (e), 1, locker, lock)
Entry **e);
void bdb_entry_free ( Entry *e );
@ -303,46 +284,84 @@ BI_op_extended bdb_exop_passwd;
* cache.c
*/
void bdb_cache_entry_commit( Entry *e );
#define bdb_cache_entryinfo_lock(e) \
ldap_pvt_thread_mutex_lock( &(e)->bei_kids_mutex )
#define bdb_cache_entryinfo_unlock(e) \
ldap_pvt_thread_mutex_unlock( &(e)->bei_kids_mutex )
#if 0
void bdb_cache_return_entry_rw( DB_ENV *env, Cache *cache, Entry *e,
int rw, DB_LOCK *lock );
#else
#define bdb_cache_return_entry_rw( env, cache, e, rw, lock ) \
bdb_cache_entry_db_unlock( env, lock )
#define bdb_cache_return_entry( env, lock ) \
bdb_cache_entry_db_unlock( env, lock )
#endif
#define bdb_cache_return_entry_r(env, c, e, l) \
bdb_cache_return_entry_rw((env), (c), (e), 0, (l))
#define bdb_cache_return_entry_w(env, c, e, l) \
bdb_cache_return_entry_rw((env), (c), (e), 1, (l))
#if 0
void bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
#else
#define bdb_unlocked_cache_return_entry_rw( a, b, c )
#endif
#define bdb_unlocked_cache_return_entry_r( c, e ) \
bdb_unlocked_cache_return_entry_rw((c), (e), 0)
#define bdb_unlocked_cache_return_entry_w( c, e ) \
bdb_unlocked_cache_return_entry_rw((c), (e), 1)
int bdb_cache_add_entry_rw(
DB_ENV *env,
Cache *cache,
int bdb_cache_add(
struct bdb_info *bdb,
EntryInfo *pei,
Entry *e,
int rw,
struct berval *nrdn,
u_int32_t locker
);
int bdb_cache_modrdn(
Entry *e,
struct berval *nrdn,
Entry *new,
EntryInfo *ein,
DB_ENV *env,
u_int32_t locker,
DB_LOCK *lock
DB_LOCK *lock
);
int bdb_cache_modify(
Entry *e,
Attribute *newAttrs,
DB_ENV *env,
u_int32_t locker,
DB_LOCK *lock
);
int bdb_cache_update_entry(
Cache *cache,
Entry *e
);
ID bdb_cache_find_entry_ndn2id(
Backend *be,
Cache *cache,
struct berval *ndn
);
Entry* bdb_cache_find_entry_id(
DB_ENV *env,
Cache *cache,
ID id,
int rw,
int bdb_cache_find_entry_ndn2id(
Backend *be,
DB_TXN *txn,
struct berval *ndn,
EntryInfo **res,
u_int32_t locker,
DB_LOCK *lock
void *ctx
);
int bdb_cache_find_entry_id(
Backend *be,
DB_TXN *tid,
ID id,
EntryInfo **eip,
int islocked,
u_int32_t locker,
DB_LOCK *lock,
void *ctx
);
int bdb_cache_delete_entry(
Cache *cache,
Entry *e
Cache *cache,
Entry *e,
DB_ENV *env,
u_int32_t locker,
DB_LOCK *lock
);
void bdb_cache_release_all( Cache *cache );

View file

@ -17,7 +17,7 @@ bdb_referrals( Operation *op, SlapReply *rs )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
Entry *e = NULL;
Entry *matched = NULL;
EntryInfo *ei;
int rc = LDAP_SUCCESS;
u_int32_t locker;
@ -43,20 +43,15 @@ bdb_referrals( Operation *op, SlapReply *rs )
dn2entry_retry:
/* get entry */
rc = bdb_dn2entry_r( op->o_bd, NULL, &op->o_req_ndn, &e, &matched, 0, locker, &lock );
rc = bdb_dn2entry( op->o_bd, NULL, &op->o_req_ndn, &ei, 1, locker,
&lock, op->o_tmpmemctx );
e = ei->bei_e;
switch(rc) {
case DB_NOTFOUND:
rc = 0;
case 0:
break;
case LDAP_BUSY:
if (e != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
}
send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );
LOCK_ID_FREE ( bdb->bi_dbenv, locker );
return LDAP_BUSY;
@ -73,20 +68,15 @@ dn2entry_retry:
"bdb_referrals: dn2entry failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#endif
if (e != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
}
send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
LOCK_ID_FREE ( bdb->bi_dbenv, locker );
return rs->sr_err;
}
if ( e == NULL ) {
if ( matched != NULL ) {
rs->sr_matched = ch_strdup( matched->e_name.bv_val );
if ( rc == DB_NOTFOUND ) {
rc = 0;
if ( e != NULL ) {
rs->sr_matched = ch_strdup( e->e_name.bv_val );
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
@ -98,13 +88,13 @@ dn2entry_retry:
(long) op->o_tag, op->o_req_dn.bv_val, rs->sr_matched );
#endif
if( is_entry_referral( matched ) ) {
if( is_entry_referral( e ) ) {
rc = LDAP_OTHER;
rs->sr_ref = get_entry_referrals( op, matched );
rs->sr_ref = get_entry_referrals( op, e );
}
bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
matched = NULL;
bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
e = NULL;
} else if ( default_referral != NULL ) {
rc = LDAP_OTHER;
rs->sr_ref = referral_rewrite( default_referral,

View file

@ -35,7 +35,7 @@ static void send_pagerequest_response(
* dereferenced entry on success, NULL on any failure.
*/
static Entry * deref_base (
BackendDB *be,
Operation *op,
SlapReply *rs,
Entry *e,
Entry **matched,
@ -44,14 +44,15 @@ static Entry * deref_base (
ID *tmp,
ID *visited )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct berval ndn;
EntryInfo *ei;
DB_LOCK lockr;
rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;
rs->sr_text = "maximum deref depth exceeded";
while (BDB_IDL_N(tmp) < be->be_max_deref_depth) {
while (BDB_IDL_N(tmp) < op->o_bd->be_max_deref_depth) {
/* Remember the last entry we looked at, so we can
* report broken links
@ -84,8 +85,9 @@ static Entry * deref_base (
break;
}
rs->sr_err = bdb_dn2entry_r( be, NULL, &ndn, &e,
NULL, 0, locker, &lockr );
rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &ndn, &ei,
0, locker, &lockr, op->o_tmpmemctx );
if ( ei ) e = ei->bei_e;
if (!e) {
rs->sr_err = LDAP_ALIAS_PROBLEM;
rs->sr_text = "aliasedObject not found";
@ -129,6 +131,7 @@ static int search_aliases(
ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp;
ID cursora, ida, cursoro, ido, *subscop2;
Entry *matched, *a;
EntryInfo *ei;
struct berval bv_alias = { sizeof("alias")-1, "alias" };
AttributeAssertion aa_alias;
Filter af;
@ -194,11 +197,13 @@ static int search_aliases(
for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;
ida = bdb_idl_next(curscop, &cursora))
{
rs->sr_err = bdb_id2entry_r(op->o_bd, NULL, ida, &a,
locker, &lockr);
ei = NULL;
rs->sr_err = bdb_cache_find_entry_id(op->o_bd, NULL,
ida, &ei, 0, locker, &lockr, op->o_tmpmemctx );
if (rs->sr_err != LDAP_SUCCESS) {
continue;
}
a = ei->bei_e;
/* This should only happen if the curscop IDL has maxed out and
* turned into a range that spans IDs indiscriminately
@ -211,7 +216,7 @@ static int search_aliases(
/* Actually dereference the alias */
BDB_IDL_ZERO(tmp);
a = deref_base( op->o_bd, rs, a, &matched, locker, &lockr,
a = deref_base( op, rs, a, &matched, locker, &lockr,
tmp, visited );
if (a) {
/* If the target was not already in our current candidates,
@ -257,8 +262,11 @@ nextido:
* we should never see the ID of an entry that doesn't exist.
* Set the name so that the scope's IDL can be retrieved.
*/
rs->sr_err = bdb_id2entry_r(op->o_bd, NULL, ido, &e, locker, &locka);
ei = NULL;
rs->sr_err = bdb_cache_find_entry_id(op->o_bd, NULL, ido, &ei,
0, locker, &locka, op->o_tmpmemctx );
if (rs->sr_err != LDAP_SUCCESS) goto nextido;
e = ei->bei_e;
sf->f_dn = &e->e_nname;
}
return rs->sr_err;
@ -338,8 +346,9 @@ int bdb_search( Operation *op, SlapReply *rs )
time_t stoptime;
ID id, cursor;
ID candidates[BDB_IDL_UM_SIZE];
Entry *e = NULL;
Entry *e = NULL, dummy;
Entry *matched = NULL;
EntryInfo *ei;
struct berval realbase = { 0, NULL };
int manageDSAit;
int tentries = 0;
@ -451,22 +460,16 @@ int bdb_search( Operation *op, SlapReply *rs )
} else {
dn2entry_retry:
/* get entry with reader lock */
rs->sr_err = bdb_dn2entry_r( op->o_bd, NULL, &sop->o_req_ndn, &e,
&matched, 0, locker, &lock );
rs->sr_err = bdb_dn2entry( op->o_bd, NULL, &sop->o_req_ndn, &ei,
1, locker, &lock, op->o_tmpmemctx );
}
switch(rs->sr_err) {
case DB_NOTFOUND:
matched = ei->bei_e; break;
case 0:
break;
e = ei->bei_e; break;
case LDAP_BUSY:
if (e != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
matched, &lock);
}
send_ldap_error( sop, rs, LDAP_BUSY, "ldap server busy" );
LOCK_ID_FREE (bdb->bi_dbenv, locker );
return LDAP_BUSY;
@ -474,13 +477,6 @@ dn2entry_retry:
case DB_LOCK_NOTGRANTED:
goto dn2entry_retry;
default:
if (e != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache,
matched, &lock);
}
send_ldap_error( sop, rs, LDAP_OTHER, "internal error" );
LOCK_ID_FREE (bdb->bi_dbenv, locker );
return rs->sr_err;
@ -488,7 +484,7 @@ dn2entry_retry:
if ( e && (op->ors_deref & LDAP_DEREF_FINDING) && is_entry_alias(e) ) {
BDB_IDL_ZERO(candidates);
e = deref_base( op->o_bd, rs, e, &matched, locker, &lock,
e = deref_base( op, rs, e, &matched, locker, &lock,
candidates, NULL );
}
@ -648,13 +644,24 @@ dn2entry_retry:
/* compute it anyway; root does not use it */
stoptime = op->o_time + sop->oq_search.rs_tlimit;
/* need normalized dn below */
ber_dupbv( &realbase, &e->e_nname );
dummy.e_nname = realbase;
dummy.e_id = e->e_id;
if ( e != &slap_entry_root ) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
e = NULL;
/* select candidates */
if ( sop->oq_search.rs_scope == LDAP_SCOPE_BASE ) {
rs->sr_err = base_candidate( op->o_bd, e, candidates );
rs->sr_err = base_candidate( op->o_bd, &dummy, candidates );
} else {
BDB_IDL_ALL( bdb, candidates );
rs->sr_err = search_candidates( op, sop, rs, e, locker, candidates );
rs->sr_err = search_candidates( op, sop, rs, &dummy, locker, candidates );
}
/* start cursor at beginning of candidates.
@ -680,14 +687,6 @@ dn2entry_retry:
}
#endif
/* need normalized dn below */
ber_dupbv( &realbase, &e->e_nname );
if ( e != &slap_entry_root ) {
bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
e = NULL;
if ( candidates[0] == 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
@ -849,8 +848,9 @@ loop_begin:
#endif
id2entry_retry:
/* get the entry with reader lock */
rs->sr_err = bdb_id2entry_r( op->o_bd, NULL, id,
&e, locker, &lock );
ei = NULL;
rs->sr_err = bdb_cache_find_entry_id( op->o_bd, NULL,
id, &ei, 0, locker, &lock, op->o_tmpmemctx );
if (rs->sr_err == LDAP_BUSY) {
rs->sr_text = "ldap server busy";
@ -863,6 +863,12 @@ id2entry_retry:
goto id2entry_retry;
}
if ( ei && rs->sr_err == 0 ) {
e = ei->bei_e;
} else {
e = NULL;
}
if ( e == NULL ) {
if( !BDB_IDL_IS_RANGE(candidates) ) {
/* only complain for non-range IDLs */

View file

@ -133,21 +133,24 @@ int bdb_tool_next_id(
DB_TXN *tid,
Entry *e,
struct berval *text,
int hole )
int hole,
u_int32_t locker )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct berval dn = e->e_nname;
struct berval pdn;
EntryInfo *ei = NULL;
int rc;
rc = bdb_dn2id( be, tid, &dn, &e->e_id, 0 );
rc = bdb_cache_find_entry_ndn2id( be, tid, &dn, &ei, locker, NULL );
if ( ei ) bdb_cache_entryinfo_unlock( ei );
if ( rc == DB_NOTFOUND ) {
if ( be_issuffix( be, &dn ) ) {
pdn = slap_empty_bv;
} else {
dnParent( &dn, &pdn );
e->e_nname = pdn;
rc = bdb_tool_next_id( be, tid, e, text, 1 );
rc = bdb_tool_next_id( be, tid, e, text, 1, locker );
if ( rc ) {
return rc;
}
@ -221,6 +224,7 @@ ID bdb_tool_entry_put(
DB_TXN *tid = NULL;
struct berval pdn;
Operation op = {0};
u_int32_t locker;
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
@ -253,8 +257,9 @@ ID bdb_tool_entry_put(
return NOID;
}
locker = TXN_ID( tid );
/* add dn2id indices */
rc = bdb_tool_next_id( be, tid, e, text, 0 );
rc = bdb_tool_next_id( be, tid, e, text, 0, locker );
if( rc != 0 ) {
goto done;
}