X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fdn2id.c;h=eb7fbdb3fa52b8843392884c0f944102c3739b39;hb=19deaedb59bfda97526836af89d56d5d8b1d8c14;hp=185c73491bc9b781da8874dceb3a21b03b9f70a9;hpb=e6b1d69163d56e7944e6601b9a3bebc87f6cc7f8;p=openldap diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index 185c73491b..eb7fbdb3fa 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2005 The OpenLDAP Foundation. + * Copyright 2000-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -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, u_int32_t 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, locker, DB_LOCK_NOWAIT, + &lockobj, db_rw, lock); + return rc; +} + #ifndef BDB_HIER int bdb_dn2id_add( @@ -39,8 +62,8 @@ bdb_dn2id_add( char *buf; struct berval ptr, pdn; - Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add( \"%s\", 0x%08lx )\n", - e->e_ndn, (long) e->e_id, 0 ); + Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add 0x%lx: \"%s\"\n", + e->e_id, e->e_ndn, 0 ); assert( e->e_id != NOID ); DBTzero( &key ); @@ -63,8 +86,8 @@ 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: put failed: %s %d\n", - db_strerror(rc), rc, 0 ); + Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add 0x%lx: put failed: %s %d\n", + e->e_id, db_strerror(rc), rc ); goto done; } @@ -76,8 +99,8 @@ bdb_dn2id_add( rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "=> bdb_dn2id_add: subtree (%s) put failed: %d\n", - ptr.bv_val, rc, 0 ); + "=> bdb_dn2id_add 0x%lx: subtree (%s) put failed: %d\n", + e->e_id, ptr.bv_val, rc ); goto done; } @@ -97,8 +120,8 @@ bdb_dn2id_add( if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "=> bdb_dn2id_add: parent (%s) insert failed: %d\n", - ptr.bv_val, rc, 0 ); + "=> bdb_dn2id_add 0x%lx: parent (%s) insert failed: %d\n", + e->e_id, ptr.bv_val, rc ); goto done; } } @@ -115,8 +138,8 @@ bdb_dn2id_add( if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n", - ptr.bv_val, rc, 0 ); + "=> bdb_dn2id_add 0x%lx: subtree (%s) insert failed: %d\n", + e->e_id, ptr.bv_val, rc ); break; } #ifdef BDB_MULTIPLE_SUFFIXES @@ -133,7 +156,7 @@ bdb_dn2id_add( done: op->o_tmpfree( buf, op->o_tmpmemctx ); - Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add: %d\n", rc, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 ); return rc; } @@ -146,13 +169,14 @@ 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 ); + Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete 0x%lx: \"%s\"\n", + e->e_id, e->e_ndn, 0 ); DBTzero( &key ); key.size = e->e_nname.bv_len + 2; @@ -165,11 +189,15 @@ 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 ) goto done; + /* delete it */ rc = db->del( db, txn, &key, 0 ); if( rc != 0 ) { - Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete: delete failed: %s %d\n", - db_strerror(rc), rc, 0 ); + Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete 0x%lx: delete failed: %s %d\n", + e->e_id, db_strerror(rc), rc ); goto done; } @@ -178,11 +206,11 @@ bdb_dn2id_delete( #endif { buf[0] = DN_SUBTREE_PREFIX; - rc = db->del( db, txn, &key, 0 ); + rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n", - ptr.bv_val, rc, 0 ); + "=> bdb_dn2id_delete 0x%lx: subtree (%s) delete failed: %d\n", + e->e_id, ptr.bv_val, rc ); goto done; } @@ -202,8 +230,8 @@ bdb_dn2id_delete( if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "=> bdb_dn2id_delete: parent (%s) delete failed: %d\n", - ptr.bv_val, rc, 0 ); + "=> bdb_dn2id_delete 0x%lx: parent (%s) delete failed: %d\n", + e->e_id, ptr.bv_val, rc ); goto done; } } @@ -219,8 +247,8 @@ bdb_dn2id_delete( rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n", - ptr.bv_val, rc, 0 ); + "=> bdb_dn2id_delete 0x%lx: subtree (%s) delete failed: %d\n", + e->e_id, ptr.bv_val, rc ); goto done; } #ifdef BDB_MULTIPLE_SUFFIXES @@ -237,24 +265,27 @@ bdb_dn2id_delete( done: op->o_tmpfree( buf, op->o_tmpmemctx ); - Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete %d\n", rc, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete 0x%lx: %d\n", e->e_id, rc, 0 ); return rc; } int bdb_dn2id( Operation *op, - DB_TXN *txn, struct berval *dn, - EntryInfo *ei ) + EntryInfo *ei, + u_int32_t 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; Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id(\"%s\")\n", dn->bv_val, 0, 0 ); + DBTzero( &key ); key.size = dn->bv_len + 2; key.data = op->o_tmpalloc( key.size, op->o_tmpmemctx ); @@ -267,18 +298,31 @@ bdb_dn2id( 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->locker = locker; + } + /* fetch it */ - rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags ); + rc = cursor->c_get( cursor, &key, &data, DB_SET ); + +nolock: + cursor->c_close( cursor ); +leave: if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n", db_strerror( rc ), rc, 0 ); } else { BDB_DISK2ID( &nid, &ei->bei_id ); - Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%08lx\n", + Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%lx\n", ei->bei_id, 0, 0 ); } - op->o_tmpfree( key.data, op->o_tmpmemctx ); return rc; } @@ -404,6 +448,31 @@ typedef struct diskNode { unsigned char entryID[sizeof(ID)]; /* variable placement */ } diskNode; +/* Sort function for the sorted duplicate data items of a dn2id key. + * Sorts based on normalized RDN, in length order. + */ +int +hdb_dup_compare( + DB *db, + const DBT *usrkey, + const DBT *curkey +) +{ + diskNode *un, *cn; + int rc, ul, cl; + + un = (diskNode *)usrkey->data; + cn = (diskNode *)curkey->data; + + /* data is not aligned, cannot compare directly */ + rc = un->nrdnlen[0] - cn->nrdnlen[0]; + if ( rc ) return rc; + rc = un->nrdnlen[1] - cn->nrdnlen[1]; + if ( rc ) return rc; + + return strcmp( un->nrdn, cn->nrdn ); +} + /* This function constructs a full DN for a given entry. */ int hdb_fix_dn( @@ -479,6 +548,9 @@ hdb_dn2id_add( diskNode *d; char *ptr; + Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id_add 0x%lx: \"%s\"\n", + e->e_id, e->e_ndn, 0 ); + nrlen = dn_rdnlen( op->o_bd, &e->e_nname ); if (nrlen) { rlen = dn_rdnlen( op->o_bd, &e->e_name ); @@ -545,7 +617,10 @@ hdb_dn2id_add( 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 ); return rc; } @@ -565,6 +640,10 @@ hdb_dn2id_delete( 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 ); DBTzero(&key); key.size = sizeof(ID); @@ -579,8 +658,6 @@ hdb_dn2id_delete( data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; key.data = &nid; - rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags ); - if ( rc ) return rc; d = op->o_tmpalloc( data.size, op->o_tmpmemctx ); d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff; @@ -590,6 +667,13 @@ hdb_dn2id_delete( strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val ); 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; + /* Delete our ID from the parent's list */ rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE ); if ( rc == 0 ) { @@ -610,7 +694,10 @@ hdb_dn2id_delete( if ( rc == 0 ) rc = cursor->c_del( cursor, 0 ); } + +nolock: cursor->c_close( cursor ); +leave: op->o_tmpfree( d, op->o_tmpmemctx ); /* Delete IDL cache entries */ @@ -628,6 +715,7 @@ hdb_dn2id_delete( 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 ); return rc; } @@ -635,9 +723,10 @@ hdb_dn2id_delete( int hdb_dn2id( Operation *op, - DB_TXN *txn, struct berval *in, - EntryInfo *ei ) + EntryInfo *ei, + u_int32_t locker, + DB_LOCK *lock ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; @@ -649,6 +738,8 @@ hdb_dn2id( unsigned char dlen[2]; ID idp, parentID; + Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 ); + nrlen = dn_rdnlen( op->o_bd, in ); if (!nrlen) nrlen = in->bv_len; @@ -666,8 +757,11 @@ 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 = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags ); if ( rc ) return rc; + if ( locker ) { + cursor->locker = locker; + } d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx ); d->nrdnlen[1] = nrlen & 0xff; @@ -678,6 +772,9 @@ hdb_dn2id( *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 ); if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] || strncmp( d->nrdn, in->bv_val, nrlen ))) { @@ -699,8 +796,17 @@ hdb_dn2id( 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", + db_strerror( rc ), rc, 0 ); + } else { + Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n", + ei->bei_id, 0, 0 ); + } return rc; } @@ -708,7 +814,6 @@ hdb_dn2id( int hdb_dn2id_parent( Operation *op, - DB_TXN *txn, u_int32_t locker, EntryInfo *ei, ID *idp ) @@ -732,9 +837,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->locker = locker; }