From: Howard Chu Date: Wed, 26 Feb 2003 12:09:10 +0000 (+0000) Subject: Fix attribute/group to allow TXN to abort on lock failure. Save and X-Git-Tag: NO_SLAP_OP_BLOCKS~283 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=18554e751116cb74935f2a2a90809dc60a04937b;p=openldap Fix attribute/group to allow TXN to abort on lock failure. Save and restore op->o_do_not_cache on TXN retry, bdb_group will set it if it fails to get a lock. --- diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 3e85b1a7ad..20aa3193db 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -99,6 +99,7 @@ retry: /* transaction retry */ rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; + op->o_do_not_cache = opinfo.boi_acl_cache; if( rc != 0 ) { rc = LDAP_OTHER; text = "internal error"; @@ -134,6 +135,7 @@ retry: /* transaction retry */ opinfo.boi_txn = ltid; opinfo.boi_locker = locker; opinfo.boi_err = 0; + opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; /* diff --git a/servers/slapd/back-bdb/attribute.c b/servers/slapd/back-bdb/attribute.c index a98a16fa85..f5cbdf7577 100644 --- a/servers/slapd/back-bdb/attribute.c +++ b/servers/slapd/back-bdb/attribute.c @@ -104,6 +104,12 @@ dn2entry_retry: break; case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: + /* the txn must abort and retry */ + if ( txn ) { + boi->boi_err = rc; + return LDAP_BUSY; + } + ldap_pvt_thread_yield(); goto dn2entry_retry; default: boi->boi_err = rc; diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 5a28d25581..449d0f6d73 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -157,6 +157,7 @@ struct bdb_op_info { DB_TXN* boi_txn; u_int32_t boi_err; u_int32_t boi_locker; + int boi_acl_cache; }; #define DB_OPEN(db, file, name, type, flags, mode) \ diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index 79cb460843..3aff606e71 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -70,6 +70,7 @@ retry: /* transaction retry */ rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; + op->o_do_not_cache = opinfo.boi_acl_cache; if( rc != 0 ) { rc = LDAP_OTHER; text = "internal error"; @@ -106,6 +107,7 @@ retry: /* transaction retry */ opinfo.boi_txn = ltid; opinfo.boi_locker = locker; opinfo.boi_err = 0; + opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; if ( !be_issuffix( be, ndn ) ) { diff --git a/servers/slapd/back-bdb/group.c b/servers/slapd/back-bdb/group.c index 1df9e776ed..4113eaa936 100644 --- a/servers/slapd/back-bdb/group.c +++ b/servers/slapd/back-bdb/group.c @@ -109,9 +109,19 @@ dn2entry_retry: /* can we find group entry */ rc = bdb_dn2entry_r( be, txn, gr_ndn, &e, NULL, 0, locker, &lock ); if( rc ) { - if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) - goto dn2entry_retry; boi->boi_err = rc; + if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) { + if ( txn ) { + /* must let owning txn abort, but our result + * is still inconclusive, so don't let it + * get cached. + */ + op->o_do_not_cache = 1; + return( 1 ); + } + ldap_pvt_thread_yield(); + goto dn2entry_retry; + } if ( free_lock_id ) { LOCK_ID_FREE ( bdb->bi_dbenv, locker ); } diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index a3b0846639..98fc5edd90 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -319,6 +319,7 @@ retry: /* transaction retry */ rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; + op->o_do_not_cache = opinfo.boi_acl_cache; if( rc != 0 ) { rc = LDAP_OTHER; text = "internal error"; @@ -351,6 +352,7 @@ retry: /* transaction retry */ opinfo.boi_txn = ltid; opinfo.boi_locker = locker; opinfo.boi_err = 0; + opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; /* get entry */ diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index 8fcba26ffd..e3f054d1f5 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -108,6 +108,7 @@ retry: /* transaction retry */ rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; + op->o_do_not_cache = opinfo.boi_acl_cache; if( rc != 0 ) { rc = LDAP_OTHER; text = "internal error"; @@ -141,6 +142,7 @@ retry: /* transaction retry */ opinfo.boi_txn = ltid; opinfo.boi_locker = locker; opinfo.boi_err = 0; + opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; /* get entry */ @@ -276,6 +278,12 @@ retry: /* transaction retry */ rc = access_allowed( be, conn, op, p, children, NULL, ACL_WRITE, NULL ); + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + if ( ! rc ) { rc = LDAP_INSUFFICIENT_ACCESS; #ifdef NEW_LOGGING @@ -326,6 +334,12 @@ retry: /* transaction retry */ rc = access_allowed( be, conn, op, p, children, NULL, ACL_WRITE, NULL ); + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + p = NULL; if ( ! rc ) { @@ -467,6 +481,12 @@ retry: /* transaction retry */ rc = access_allowed( be, conn, op, np, children, NULL, ACL_WRITE, NULL ); + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + if( ! rc ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, DETAIL1, @@ -528,6 +548,12 @@ retry: /* transaction retry */ rc = access_allowed( be, conn, op, np, children, NULL, ACL_WRITE, NULL ); + switch( opinfo.boi_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + np = NULL; if ( ! rc ) { diff --git a/servers/slapd/back-bdb/passwd.c b/servers/slapd/back-bdb/passwd.c index 1e5818992c..d258265e22 100644 --- a/servers/slapd/back-bdb/passwd.c +++ b/servers/slapd/back-bdb/passwd.c @@ -123,6 +123,7 @@ retry: /* transaction retry */ rc = TXN_ABORT( ltid ); ltid = NULL; op->o_private = NULL; + op->o_do_not_cache = opinfo.boi_acl_cache; if( rc != 0 ) { rc = LDAP_OTHER; *text = "internal error"; @@ -156,6 +157,7 @@ retry: /* transaction retry */ opinfo.boi_txn = ltid; opinfo.boi_locker = locker; opinfo.boi_err = 0; + opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; /* get entry */