Commit e1dc2bea authored by Howard Chu's avatar Howard Chu
Browse files

ITS#5262, sync with HEAD

parent 250e14d5
......@@ -70,13 +70,15 @@ typedef struct __db_locker * BDB_LOCKER;
extern int __lock_getlocker(DB_LOCKTAB *lt, u_int32_t locker, int create, DB_LOCKER **ret);
#define CURSOR_SETLOCKER(cursor, id) cursor->locker = id
#define CURSOR_GETLOCKER(cursor) cursor->locker
#define CURSOR_GETLOCKER(cursor) cursor->locker
#define BDB_LOCKID(locker) locker->id
#else
typedef u_int32_t BDB_LOCKER;
#define CURSOR_SETLOCKER(cursor, id) cursor->locker = id
#define CURSOR_GETLOCKER(cursor) cursor->locker
#define BDB_LOCKID(locker) locker
#endif
......@@ -106,7 +108,7 @@ typedef struct bdb_entry_info {
* to avoid conflicting with BDB's internal locks. So add a byte here
* that is always zero.
*/
char bei_lockpad;
short bei_lockpad;
short bei_state;
#define CACHE_ENTRY_DELETED 1
......@@ -312,6 +314,25 @@ struct bdb_op_info {
#define TXN_ID(txn) (txn)->locker
#endif
/* #undef BDB_LOG_DEBUG */
#ifdef BDB_LOG_DEBUG
/* env->log_printf appeared in 4.4 */
#if DB_VERSION_FULL >= 0x04040000
#define BDB_LOG_PRINTF(env,txn,fmt,...) (env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
#else
extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
const char *fmt,...);
#define BDB_LOG_PRINTF(env,txn,fmt,...) __db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
#endif
#else /* !BDB_LOG_DEBUG */
#define BDB_LOG_PRINTF(a,b,c,...)
#endif /* BDB_LOG_DEBUG */
#endif
#ifndef DB_BUFFER_SMALL
......
......@@ -155,12 +155,6 @@ bdb_cache_lru_link( struct bdb_info *bdb, EntryInfo *ei )
* alternatives though.
*/
#if DB_VERSION_FULL >= 0x04060012
#define BDB_LOCKID(locker) locker->id
#else
#define BDB_LOCKID(locker) locker
#endif
/* Atomically release and reacquire a lock */
int
bdb_cache_entry_db_relock(
......@@ -351,6 +345,8 @@ bdb_entryinfo_add_internal(
ei->bei_rdn.bv_val = NULL;
#endif
} else {
int rc;
bdb->bi_cache.c_eiused++;
ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
......@@ -360,8 +356,13 @@ bdb_entryinfo_add_internal(
*/
if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id )
bdb->bi_cache.c_leaves++;
avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
rc = avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
avl_dup_error );
if ( rc ) {
/* This should never happen; entry cache is corrupt */
bdb->bi_dbenv->log_flush( bdb->bi_dbenv, NULL );
assert( !rc );
}
#ifdef BDB_HIER
ei->bei_parent->bei_ckids++;
#endif
......@@ -380,7 +381,7 @@ bdb_entryinfo_add_internal(
int
bdb_cache_find_ndn(
Operation *op,
DB_TXN *txn,
BDB_LOCKER locker,
struct berval *ndn,
EntryInfo **res )
{
......@@ -418,6 +419,7 @@ bdb_cache_find_ndn(
ei.bei_parent = eip;
ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
if ( !ei2 ) {
DB_LOCK lock;
int len = ei.bei_nrdn.bv_len;
if ( BER_BVISEMPTY( ndn )) {
......@@ -429,18 +431,27 @@ bdb_cache_find_ndn(
(ei.bei_nrdn.bv_val - ndn->bv_val);
bdb_cache_entryinfo_unlock( eip );
rc = bdb_dn2id( op, txn, &ei.bei_nrdn, &ei );
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s",
ei.bei_nrdn.bv_val );
lock.mode = DB_LOCK_NG;
rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, locker, &lock );
if (rc) {
bdb_cache_entryinfo_lock( eip );
bdb_cache_entry_db_unlock( bdb, &lock );
*res = eip;
return rc;
}
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Read got %s(%d)",
ei.bei_nrdn.bv_val, ei.bei_id );
/* DN exists but needs to be added to cache */
ei.bei_nrdn.bv_len = len;
rc = bdb_entryinfo_add_internal( bdb, &ei, &ei2 );
/* add_internal left eip and c_rwlock locked */
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
bdb_cache_entry_db_unlock( bdb, &lock );
if ( rc ) {
*res = eip;
return rc;
......@@ -484,7 +495,6 @@ bdb_cache_find_ndn(
int
hdb_cache_find_parent(
Operation *op,
DB_TXN *txn,
BDB_LOCKER locker,
ID id,
EntryInfo **res )
......@@ -498,7 +508,7 @@ hdb_cache_find_parent(
ei.bei_ckids = 0;
for (;;) {
rc = hdb_dn2id_parent( op, txn, locker, &ei, &eip.bei_id );
rc = hdb_dn2id_parent( op, locker, &ei, &eip.bei_id );
if ( rc ) break;
/* Save the previous node, if any */
......@@ -821,7 +831,7 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
#ifndef BDB_HIER
rc = bdb_id2entry( op->o_bd, tid, locker, id, &ep );
if ( rc == 0 ) {
rc = bdb_cache_find_ndn( op, tid,
rc = bdb_cache_find_ndn( op, locker,
&ep->e_nname, eip );
if ( *eip ) flag |= ID_LOCKED;
if ( rc ) {
......@@ -835,7 +845,7 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
}
}
#else
rc = hdb_cache_find_parent(op, tid, locker, id, eip );
rc = hdb_cache_find_parent(op, locker, id, eip );
if ( rc == 0 ) flag |= ID_LOCKED;
#endif
}
......
......@@ -372,6 +372,9 @@ retry: /* transaction retry */
goto return_results;
}
BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Starting delete %s(%d)",
e->e_nname.bv_val, e->e_id );
/* Can't do it if we have kids */
rs->sr_err = bdb_cache_children( op, lt2, e );
if( rs->sr_err != DB_NOTFOUND ) {
......@@ -492,6 +495,9 @@ retry: /* transaction retry */
p = NULL;
}
BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Commit1 delete %s(%d)",
e->e_nname.bv_val, e->e_id );
if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "txn_commit(2) failed";
......@@ -517,6 +523,10 @@ retry: /* transaction retry */
goto return_results;
}
} else {
BDB_LOG_PRINTF( bdb->bi_dbenv, ltid, "slapd Cache delete %s(%d)",
e->e_nname.bv_val, e->e_id );
rc = bdb_cache_delete( bdb, e, locker, &lock );
switch( rc ) {
case DB_LOCK_DEADLOCK:
......@@ -529,6 +539,9 @@ retry: /* transaction retry */
ltid = NULL;
op->o_private = NULL;
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)",
e->e_nname.bv_val, e->e_id );
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(bdb_delete) ": txn_%s failed: %s (%d)\n",
......
......@@ -45,7 +45,7 @@ bdb_dn2entry(
*e = NULL;
rc = bdb_cache_find_ndn( op, tid, dn, &ei );
rc = bdb_cache_find_ndn( op, locker, dn, &ei );
if ( rc ) {
if ( matched && rc == DB_NOTFOUND ) {
/* Set the return value, whether we have its entry
......
......@@ -23,6 +23,29 @@
#include "idl.h"
#include "lutil.h"
#define bdb_dn2id_lock BDB_SYMBOL(dn2id_lock)
static int
bdb_dn2id_lock( struct bdb_info *bdb, struct berval *dn,
int rw, BDB_LOCKER locker, DB_LOCK *lock )
{
int rc;
DBT lockobj;
int db_rw;
if (rw)
db_rw = DB_LOCK_WRITE;
else
db_rw = DB_LOCK_READ;
lockobj.data = dn->bv_val;
lockobj.size = dn->bv_len;
rc = LOCK_GET(bdb->bi_dbenv, BDB_LOCKID(locker), DB_LOCK_NOWAIT,
&lockobj, db_rw, lock);
return rc;
}
#ifndef BDB_HIER
int
bdb_dn2id_add(
......@@ -146,10 +169,11 @@ bdb_dn2id_delete(
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
int rc;
DBT key;
char *buf;
DBT key;
DB_LOCK lock;
struct berval pdn, ptr;
int rc;
Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", 0x%08lx )\n",
e->e_ndn, e->e_id, 0 );
......@@ -165,6 +189,10 @@ bdb_dn2id_delete(
AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
ptr.bv_val[ptr.bv_len] = '\0';
/* We hold this lock until the TXN completes */
rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
if ( rc ) return rc;
/* delete it */
rc = db->del( db, txn, &key, 0 );
if( rc != 0 ) {
......@@ -244,12 +272,14 @@ done:
int
bdb_dn2id(
Operation *op,
DB_TXN *txn,
struct berval *dn,
EntryInfo *ei )
EntryInfo *ei,
BDB_LOCKER locker,
DB_LOCK *lock )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
DBC *cursor;
int rc;
DBT key, data;
ID nid;
......@@ -267,8 +297,17 @@ bdb_dn2id(
data.ulen = sizeof(ID);
data.flags = DB_DBT_USERMEM;
rc = bdb_dn2id_lock( bdb, dn, 0, locker, lock );
if ( rc ) return rc;
rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
if ( locker ) {
CURSOR_SETLOCKER(cursor, locker);
}
/* fetch it */
rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags );
rc = cursor->c_get( cursor, &key, &data, DB_SET );
if( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n",
......@@ -279,6 +318,7 @@ bdb_dn2id(
ei->bei_id, 0, 0 );
}
cursor->c_close( cursor );
op->o_tmpfree( key.data, op->o_tmpmemctx );
return rc;
}
......@@ -568,6 +608,7 @@ hdb_dn2id_delete(
int rc;
ID nid;
unsigned char dlen[2];
DB_LOCK lock;
DBTzero(&key);
key.size = sizeof(ID);
......@@ -581,6 +622,10 @@ hdb_dn2id_delete(
data.dlen = data.size;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
/* We hold this lock until the TXN completes */
rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
if ( rc ) return rc;
key.data = &nid;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
......@@ -638,9 +683,10 @@ hdb_dn2id_delete(
int
hdb_dn2id(
Operation *op,
DB_TXN *txn,
struct berval *in,
EntryInfo *ei )
EntryInfo *ei,
BDB_LOCKER locker,
DB_LOCK *lock )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
......@@ -669,9 +715,15 @@ hdb_dn2id(
data.dlen = data.ulen;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
rc = bdb_dn2id_lock( bdb, in, 0, locker, lock );
if ( rc ) return rc;
rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
if ( locker ) {
CURSOR_SETLOCKER( cursor, locker );
}
d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
d->nrdnlen[1] = nrlen & 0xff;
d->nrdnlen[0] = (nrlen >> 8) | 0x80;
......@@ -711,7 +763,6 @@ hdb_dn2id(
int
hdb_dn2id_parent(
Operation *op,
DB_TXN *txn,
BDB_LOCKER locker,
EntryInfo *ei,
ID *idp )
......@@ -735,9 +786,9 @@ hdb_dn2id_parent(
DBTzero(&data);
data.flags = DB_DBT_USERMEM;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
if ( !txn && locker ) {
if ( locker ) {
CURSOR_SETLOCKER(cursor, locker);
}
......
......@@ -504,7 +504,7 @@ ext_candidates(
BDB_IDL_ZERO( ids );
if ( mra->ma_rule == slap_schema.si_mr_distinguishedNameMatch ) {
ei = NULL;
rc = bdb_cache_find_ndn( op, NULL, &mra->ma_value, &ei );
rc = bdb_cache_find_ndn( op, locker, &mra->ma_value, &ei );
if ( rc == LDAP_SUCCESS )
bdb_idl_insert( ids, ei->bei_id );
if ( ei )
......@@ -518,7 +518,7 @@ ext_candidates(
struct berval pdn;
ei = NULL;
dnParent( &mra->ma_value, &pdn );
bdb_cache_find_ndn( op, NULL, &pdn, &ei );
bdb_cache_find_ndn( op, locker, &pdn, &ei );
if ( ei ) {
bdb_cache_entryinfo_unlock( ei );
while ( ei && ei->bei_id ) {
......@@ -538,7 +538,7 @@ ext_candidates(
scope = LDAP_SCOPE_BASE;
if ( scope > LDAP_SCOPE_BASE ) {
ei = NULL;
rc = bdb_cache_find_ndn( op, NULL, &mra->ma_value, &ei );
rc = bdb_cache_find_ndn( op, locker, &mra->ma_value, &ei );
if ( ei )
bdb_cache_entryinfo_unlock( ei );
if ( rc == LDAP_SUCCESS ) {
......
......@@ -551,7 +551,7 @@ retry: /* transaction retry */
/* Shortcut the search */
nei = neip ? neip : eip;
rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
rs->sr_err = bdb_cache_find_ndn ( op, locker, &new_ndn, &nei );
if ( nei ) bdb_cache_entryinfo_unlock( nei );
switch( rs->sr_err ) {
case DB_LOCK_DEADLOCK:
......
......@@ -97,9 +97,10 @@ int bdb_dn2entry LDAP_P(( Operation *op, DB_TXN *tid,
int bdb_dn2id(
Operation *op,
DB_TXN *tid,
struct berval *dn,
EntryInfo *ei );
EntryInfo *ei,
BDB_LOCKER locker,
DB_LOCK *lock );
int bdb_dn2id_add(
Operation *op,
......@@ -132,7 +133,6 @@ int bdb_dn2idl(
int bdb_dn2id_parent(
Operation *op,
DB_TXN *txn,
BDB_LOCKER locker,
EntryInfo *ei,
ID *idp );
......@@ -529,7 +529,7 @@ int bdb_cache_modify(
);
int bdb_cache_find_ndn(
Operation *op,
DB_TXN *txn,
BDB_LOCKER locker,
struct berval *ndn,
EntryInfo **res
);
......@@ -552,7 +552,6 @@ int bdb_cache_find_id(
int
bdb_cache_find_parent(
Operation *op,
DB_TXN *txn,
BDB_LOCKER locker,
ID id,
EntryInfo **res
......
......@@ -231,7 +231,7 @@ ID bdb_tool_dn2id_get(
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
rc = bdb_cache_find_ndn( &op, NULL, dn, &ei );
rc = bdb_cache_find_ndn( &op, 0, dn, &ei );
if ( ei ) bdb_cache_entryinfo_unlock( ei );
if ( rc == DB_NOTFOUND )
return NOID;
......@@ -306,7 +306,7 @@ Entry* bdb_tool_entry_get( BackendDB *be, ID id )
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
rc = bdb_cache_find_parent( &op, NULL, CURSOR_GETLOCKER(cursor), id, &ei );
rc = bdb_cache_find_parent( &op, CURSOR_GETLOCKER(cursor), id, &ei );
if ( rc == LDAP_SUCCESS ) {
bdb_cache_entryinfo_unlock( ei );
e->e_private = ei;
......@@ -340,7 +340,7 @@ static int bdb_tool_next_id(
return 0;
}
rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
rc = bdb_cache_find_ndn( op, TXN_ID( tid ), &ndn, &ei );
if ( ei ) bdb_cache_entryinfo_unlock( ei );
if ( rc == DB_NOTFOUND ) {
if ( !be_issuffix( op->o_bd, &ndn ) ) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment