/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2000-2007 The OpenLDAP Foundation.
+ * Copyright 2000-2013 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#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 (!locker)
- return 0;
-
- 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(
/* store it -- don't override */
rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
if( rc != 0 ) {
- Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add 0x%lx: put failed: %s %d\n",
- e->e_id, db_strerror(rc), rc );
+ char buf[ SLAP_TEXT_BUFLEN ];
+ snprintf( buf, sizeof( buf ), "%s => bdb_dn2id_add dn=\"%s\" ID=0x%lx",
+ op->o_log_prefix, e->e_name.bv_val, e->e_id );
+ Debug( LDAP_DEBUG_ANY, "%s: put failed: %s %d\n",
+ buf, db_strerror(rc), rc );
goto done;
}
DB *db = bdb->bi_dn2id->bdi_db;
char *buf;
DBT key;
- DB_LOCK lock;
struct berval pdn, ptr;
int rc;
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 ) goto done;
-
/* delete it */
rc = db->del( db, txn, &key, 0 );
if( rc != 0 ) {
Operation *op,
struct berval *dn,
EntryInfo *ei,
- BDB_LOCKER locker,
- DB_LOCK *lock )
+ DB_TXN *txn,
+ DBC **cursor )
{
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;
data.ulen = sizeof(ID);
data.flags = DB_DBT_USERMEM;
- rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
- if ( rc ) goto leave;
-
- rc = bdb_dn2id_lock( bdb, dn, 0, locker, lock );
- if ( rc ) goto nolock;
-
- if ( locker ) {
- CURSOR_SETLOCKER(cursor, locker);
- }
+ rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
/* fetch it */
- rc = cursor->c_get( cursor, &key, &data, DB_SET );
-
-nolock:
- cursor->c_close( cursor );
-leave:
+ if ( !rc )
+ rc = (*cursor)->c_get( *cursor, &key, &data, DB_SET );
if( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n",
int
bdb_dn2idl(
Operation *op,
- BDB_LOCKER locker,
+ DB_TXN *txn,
struct berval *ndn,
EntryInfo *ei,
ID *ids,
#ifndef BDB_MULTIPLE_SUFFIXES
if ( prefix == DN_SUBTREE_PREFIX
- && ( ei->bei_id == 0 || ei->bei_parent->bei_id == 0 )) {
+ && ( ei->bei_id == 0 ||
+ ( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len ))) {
BDB_IDL_ALL(bdb, ids);
return 0;
}
AC_MEMCPY( &((char *)key.data)[1], ndn->bv_val, key.size - 1 );
BDB_IDL_ZERO( ids );
- rc = bdb_idl_fetch_key( op->o_bd, db, locker, &key, ids, NULL, 0 );
+ rc = bdb_idl_fetch_key( op->o_bd, db, txn, &key, ids, NULL, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE,
)
{
diskNode *un, *cn;
- int rc, ul, cl;
+ int rc;
un = (diskNode *)usrkey->data;
cn = (diskNode *)curkey->data;
}
}
BEI(e)->bei_modrdns = max;
- ptr[-1] = '\0';
- nptr[-1] = '\0';
+ if ( ptr > e->e_name.bv_val ) ptr[-1] = '\0';
+ if ( nptr > e->e_nname.bv_val ) nptr[-1] = '\0';
return 0;
}
tmp[1] = eip->bei_id;
*ptr = DN_ONE_PREFIX;
bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
- *ptr = DN_SUBTREE_PREFIX;
- for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
- tmp[1] = eip->bei_id;
- bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
+ if ( eip->bei_parent ) {
+ *ptr = DN_SUBTREE_PREFIX;
+ for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
+ tmp[1] = eip->bei_id;
+ bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
+ }
+ /* Handle DB with empty suffix */
+ if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
+ tmp[1] = eip->bei_id;
+ bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
+ }
}
}
-leave:
op->o_tmpfree( d, op->o_tmpmemctx );
Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 );
int rc;
ID nid;
unsigned char dlen[2];
- DB_LOCK lock;
Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_delete 0x%lx: \"%s\"\n",
e->e_id, e->e_ndn, 0 );
d->nrdnlen[0] = (BEI(e)->bei_nrdn.bv_len >> 8) | 0x80;
dlen[0] = d->nrdnlen[0];
dlen[1] = d->nrdnlen[1];
- strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val );
+ memcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val, BEI(e)->bei_nrdn.bv_len+1 );
data.data = d;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
- if ( rc ) goto leave;
-
- /* We hold this lock until the TXN completes */
- rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
- if ( rc ) goto nolock;
+ if ( rc ) goto func_leave;
/* Delete our ID from the parent's list */
rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
rc = cursor->c_del( cursor, 0 );
}
-nolock:
cursor->c_close( cursor );
-leave:
+func_leave:
op->o_tmpfree( d, op->o_tmpmemctx );
/* Delete IDL cache entries */
tmp[1] = eip->bei_id;
*ptr = DN_ONE_PREFIX;
bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
- *ptr = DN_SUBTREE_PREFIX;
- for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
- tmp[1] = eip->bei_id;
- bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
+ if ( eip ->bei_parent ) {
+ *ptr = DN_SUBTREE_PREFIX;
+ for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
+ tmp[1] = eip->bei_id;
+ bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
+ }
+ /* Handle DB with empty suffix */
+ if ( !op->o_bd->be_suffix[0].bv_len && eip ) {
+ tmp[1] = eip->bei_id;
+ bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
+ }
}
}
Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 );
Operation *op,
struct berval *in,
EntryInfo *ei,
- BDB_LOCKER locker,
- DB_LOCK *lock )
+ DB_TXN *txn,
+ DBC **cursor )
{
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 = 0, nrlen;
diskNode *d;
char *ptr;
data.dlen = data.ulen;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
- rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
+ rc = db->cursor( db, txn, 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;
*ptr = '\0';
data.data = d;
- rc = bdb_dn2id_lock( bdb, in, 0, locker, lock );
- if ( rc ) goto leave;
-
- rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
+ rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE );
if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] ||
strncmp( d->nrdn, in->bv_val, nrlen ))) {
rc = DB_NOTFOUND;
/* FIXME: do we need to lock the parent
* entryinfo? Seems safe...
*/
- cursor->c_count( cursor, &dkids, 0 );
+ (*cursor)->c_count( *cursor, &dkids, 0 );
ei->bei_parent->bei_dkids = dkids;
}
}
-leave:
- cursor->c_close( cursor );
op->o_tmpfree( d, op->o_tmpmemctx );
if( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n",
int
hdb_dn2id_parent(
Operation *op,
- BDB_LOCKER locker,
+ DB_TXN *txn,
EntryInfo *ei,
ID *idp )
{
DBTzero(&data);
data.flags = DB_DBT_USERMEM;
- rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
+ rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
- if ( locker ) {
- CURSOR_SETLOCKER(cursor, locker);
- }
data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
d = op->o_tmpalloc( data.ulen, op->o_tmpmemctx );
struct dn2id_cookie {
struct bdb_info *bdb;
Operation *op;
- BDB_LOCKER locker;
+ DB_TXN *txn;
EntryInfo *ei;
ID *ids;
ID *tmp;
cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, ids);
if ( cx->rc == LDAP_SUCCESS ) {
if ( cx->depth ) {
+ bdb_idl_delete( cx->tmp, cx->id ); /* ITS#6983, drop our own ID */
bdb_idl_append( cx->ids, cx->tmp );
cx->need_sort = 1;
}
cx->rc = cx->dbc->c_close( cx->dbc );
done_one:
bdb_cache_entryinfo_lock( cx->ei );
- cx->ei->bei_state ^= CACHE_ENTRY_ONELEVEL;
+ cx->ei->bei_state &= ~CACHE_ENTRY_ONELEVEL;
bdb_cache_entryinfo_unlock( cx->ei );
if ( cx->rc )
return cx->rc;
for ( cx->id = bdb_idl_first( save, &idcurs );
cx->id != NOID;
cx->id = bdb_idl_next( save, &idcurs )) {
- cx->ei = bdb_cache_find_info( cx->bdb, cx->id );
- if ( !cx->ei ||
- ( cx->ei->bei_state & CACHE_ENTRY_NO_KIDS ))
+ EntryInfo *ei2;
+ cx->ei = NULL;
+ if ( bdb_cache_find_id( cx->op, cx->txn, cx->id, &cx->ei,
+ ID_NOENTRY, NULL ))
continue;
-
- BDB_ID2DISK( cx->id, &cx->nid );
- hdb_dn2idl_internal( cx );
- if ( !BDB_IDL_IS_ZERO( cx->tmp ))
- nokids = 0;
+ if ( cx->ei ) {
+ ei2 = cx->ei;
+ if ( !( ei2->bei_state & CACHE_ENTRY_NO_KIDS )) {
+ BDB_ID2DISK( cx->id, &cx->nid );
+ hdb_dn2idl_internal( cx );
+ if ( !BDB_IDL_IS_ZERO( cx->tmp ))
+ nokids = 0;
+ }
+ bdb_cache_entryinfo_lock( ei2 );
+ ei2->bei_finders--;
+ bdb_cache_entryinfo_unlock( ei2 );
+ }
}
cx->depth--;
cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
- if ( nokids ) ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
+ if ( nokids ) {
+ bdb_cache_entryinfo_lock( ei );
+ ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
+ bdb_cache_entryinfo_unlock( ei );
+ }
}
/* Make sure caller knows it had kids! */
cx->tmp[0]=1;
int
hdb_dn2idl(
Operation *op,
- BDB_LOCKER locker,
+ DB_TXN *txn,
struct berval *ndn,
EntryInfo *ei,
ID *ids,
#ifndef BDB_MULTIPLE_SUFFIXES
if ( op->ors_scope != LDAP_SCOPE_ONELEVEL &&
( ei->bei_id == 0 ||
- ei->bei_parent->bei_id == 0 ))
+ ( ei->bei_parent->bei_id == 0 && op->o_bd->be_suffix[0].bv_len )))
{
BDB_IDL_ALL( bdb, ids );
return 0;
cx.tmp = stack;
cx.buf = stack + BDB_IDL_UM_SIZE;
cx.op = op;
- cx.locker = locker;
+ cx.txn = txn;
cx.need_sort = 0;
cx.depth = 0;