mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-30 13:30:57 +08:00
More deadlock tweaks.
This commit is contained in:
parent
6f632af413
commit
aee837c999
@ -239,7 +239,11 @@ bdb_entryinfo_add_internal(
|
|||||||
*/
|
*/
|
||||||
if ( bdb_cache_entry_db_lock( env, locker, elru, 1, 1,
|
if ( bdb_cache_entry_db_lock( env, locker, elru, 1, 1,
|
||||||
&lock ) == 0 ) {
|
&lock ) == 0 ) {
|
||||||
if ( !elru->bei_e ) {
|
/* If there's no entry, or this node is in
|
||||||
|
* the process of linking into the cache,
|
||||||
|
* skip it.
|
||||||
|
*/
|
||||||
|
if ( !elru->bei_e || (elru->bei_state & CACHE_ENTRY_NOT_LINKED) ) {
|
||||||
bdb_cache_entry_db_unlock( env, &lock );
|
bdb_cache_entry_db_unlock( env, &lock );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -422,8 +426,10 @@ hdb_cache_find_parent(
|
|||||||
{
|
{
|
||||||
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
|
||||||
EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
|
EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
|
||||||
|
char ndn[SLAP_LDAPDN_MAXLEN];
|
||||||
ID parent;
|
ID parent;
|
||||||
int rc;
|
int rc;
|
||||||
|
int addlru = 1;
|
||||||
|
|
||||||
ei.bei_id = id;
|
ei.bei_id = id;
|
||||||
ei.bei_kids = NULL;
|
ei.bei_kids = NULL;
|
||||||
@ -450,16 +456,24 @@ hdb_cache_find_parent(
|
|||||||
if ( avl_insert( &bdb->bi_cache.c_idtree, (caddr_t)ein,
|
if ( avl_insert( &bdb->bi_cache.c_idtree, (caddr_t)ein,
|
||||||
bdb_id_cmp, avl_dup_error ) ) {
|
bdb_id_cmp, avl_dup_error ) ) {
|
||||||
|
|
||||||
/* Hm, can this really happen? */
|
/* Someone else created this node just before us.
|
||||||
|
* Free our new copy and use the existing one.
|
||||||
|
*/
|
||||||
bdb_cache_entryinfo_destroy( ein );
|
bdb_cache_entryinfo_destroy( ein );
|
||||||
ein = (EntryInfo *)avl_find( bdb->bi_cache.c_idtree,
|
ein = (EntryInfo *)avl_find( bdb->bi_cache.c_idtree,
|
||||||
(caddr_t) &ei, bdb_id_cmp );
|
(caddr_t) &ei, bdb_id_cmp );
|
||||||
|
|
||||||
|
/* Link in any kids we've already processed */
|
||||||
if ( ei2 ) {
|
if ( ei2 ) {
|
||||||
bdb_cache_entryinfo_lock( ein );
|
bdb_cache_entryinfo_lock( ein );
|
||||||
avl_insert( &ein->bei_kids, (caddr_t)ei2,
|
avl_insert( &ein->bei_kids, (caddr_t)ei2,
|
||||||
bdb_rdn_cmp, avl_dup_error );
|
bdb_rdn_cmp, avl_dup_error );
|
||||||
bdb_cache_entryinfo_unlock( ein );
|
bdb_cache_entryinfo_unlock( ein );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !eir ) {
|
||||||
|
addlru = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is the first time, save this node
|
/* If this is the first time, save this node
|
||||||
@ -470,27 +484,28 @@ hdb_cache_find_parent(
|
|||||||
/* If there was a previous node, link it to this one */
|
/* If there was a previous node, link it to this one */
|
||||||
if ( ei2 ) ei2->bei_parent = ein;
|
if ( ei2 ) ei2->bei_parent = ein;
|
||||||
|
|
||||||
|
/* Look for this node's parent */
|
||||||
if ( eip.bei_id ) {
|
if ( eip.bei_id ) {
|
||||||
ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
|
ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
|
||||||
(caddr_t) &eip, bdb_id_cmp );
|
(caddr_t) &eip, bdb_id_cmp );
|
||||||
} else {
|
} else {
|
||||||
ei2 = &bdb->bi_cache.c_dntree;
|
ei2 = &bdb->bi_cache.c_dntree;
|
||||||
}
|
}
|
||||||
|
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
||||||
|
|
||||||
|
/* Got the parent, link in and we're done. */
|
||||||
if ( ei2 ) {
|
if ( ei2 ) {
|
||||||
ein->bei_parent = ei2;
|
|
||||||
bdb_cache_entryinfo_lock( ei2 );
|
bdb_cache_entryinfo_lock( ei2 );
|
||||||
|
ein->bei_parent = ei2;
|
||||||
avl_insert( &ei2->bei_kids, (caddr_t)ein, bdb_rdn_cmp,
|
avl_insert( &ei2->bei_kids, (caddr_t)ein, bdb_rdn_cmp,
|
||||||
avl_dup_error);
|
avl_dup_error);
|
||||||
bdb_cache_entryinfo_unlock( ei2 );
|
bdb_cache_entryinfo_unlock( ei2 );
|
||||||
*res = eir;
|
|
||||||
bdb_cache_entryinfo_lock( eir );
|
bdb_cache_entryinfo_lock( eir );
|
||||||
}
|
|
||||||
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
|
/* Reset all the state info */
|
||||||
if ( ei2 ) {
|
|
||||||
/* Found a link. Reset all the state info */
|
|
||||||
for (ein = eir; ein != ei2; ein=ein->bei_parent)
|
for (ein = eir; ein != ei2; ein=ein->bei_parent)
|
||||||
ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED;
|
ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED;
|
||||||
|
*res = eir;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ei.bei_kids = NULL;
|
ei.bei_kids = NULL;
|
||||||
@ -532,12 +547,26 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
|
|||||||
*eip = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
|
*eip = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree,
|
||||||
(caddr_t) &ei, bdb_id_cmp );
|
(caddr_t) &ei, bdb_id_cmp );
|
||||||
if ( *eip ) {
|
if ( *eip ) {
|
||||||
|
/* If the lock attempt fails, the info is in use */
|
||||||
if ( ldap_pvt_thread_mutex_trylock(
|
if ( ldap_pvt_thread_mutex_trylock(
|
||||||
&(*eip)->bei_kids_mutex )) {
|
&(*eip)->bei_kids_mutex )) {
|
||||||
ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
|
ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
|
||||||
|
/* If this node is being deleted, treat
|
||||||
|
* as if the delete has already finished
|
||||||
|
*/
|
||||||
if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
|
if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
|
||||||
return DB_NOTFOUND;
|
return DB_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
/* otherwise, wait for the info to free up */
|
||||||
|
ldap_pvt_thread_yield();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
/* If this info isn't hooked up to its parent yet,
|
||||||
|
* unlock and wait for it to be fully initialized
|
||||||
|
*/
|
||||||
|
if ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED ) {
|
||||||
|
bdb_cache_entryinfo_unlock( *eip );
|
||||||
|
ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock );
|
||||||
ldap_pvt_thread_yield();
|
ldap_pvt_thread_yield();
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user