X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fback-bdb%2Fid2entry.c;h=f362739185eac099f3f190bc56105f847879357f;hb=4a004a260932cf3b2b86d0d78ff4ae7b0a049953;hp=151fbb0ebe0bab4d1248c1fa22bab290eb680b58;hpb=e8c58b4e7f21caa6c0b6006e3528cbad9b8aed45;p=openldap diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 151fbb0ebe..f362739185 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -1,8 +1,17 @@ /* id2entry.c - routines to deal with the id2entry database */ /* $OpenLDAP$ */ -/* - * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file +/* This work is part of OpenLDAP Software . + * + * Copyright 2000-2006 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ #include "portable.h" @@ -12,7 +21,7 @@ #include "back-bdb.h" -int bdb_id2entry_put( +static int bdb_id2entry_put( BackendDB *be, DB_TXN *tid, Entry *e, @@ -23,10 +32,11 @@ int bdb_id2entry_put( DBT key, data; struct berval bv; int rc; + ID nid; #ifdef BDB_HIER struct berval odn, ondn; - /* We only store rdns, and they go in the id2parent database. */ + /* We only store rdns, and they go in the dn2id database. */ odn = e->e_name; ondn = e->e_nname; @@ -34,8 +44,11 @@ int bdb_id2entry_put( e->e_nname = slap_empty_bv; #endif DBTzero( &key ); - key.data = (char *) &e->e_id; + + /* Store ID in BigEndian format */ + key.data = &nid; key.size = sizeof(ID); + BDB_ID2DISK( e->e_id, &nid ); rc = entry_encode( e, &bv ); #ifdef BDB_HIER @@ -76,36 +89,41 @@ int bdb_id2entry_update( return bdb_id2entry_put(be, tid, e, 0); } -int bdb_id2entry_rw( +int bdb_id2entry( BackendDB *be, DB_TXN *tid, - ID id, - Entry **e, - int rw, u_int32_t locker, - DB_LOCK *lock ) + ID id, + Entry **e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_id2entry->bdi_db; DBT key, data; + DBC *cursor; struct berval bv; - int rc = 0, ret = 0; + int rc = 0; + ID nid; *e = NULL; DBTzero( &key ); - key.data = (char *) &id; + key.data = &nid; key.size = sizeof(ID); + BDB_ID2DISK( id, &nid ); DBTzero( &data ); data.flags = DB_DBT_MALLOC; - if ((*e = bdb_cache_find_entry_id(bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock)) != NULL) { - return 0; - } - /* fetch it */ - rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags | ( rw ? DB_RMW : 0 )); + rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); + if ( rc ) return rc; + + /* Use our own locker if needed */ + if ( !tid && locker ) + cursor->locker = locker; + + rc = cursor->c_get( cursor, &key, &data, DB_SET ); + cursor->c_close( cursor ); if( rc != 0 ) { return rc; @@ -113,7 +131,11 @@ int bdb_id2entry_rw( DBT2bv( &data, &bv ); - rc = entry_decode( &bv, e ); +#ifdef SLAP_ZONE_ALLOC + rc = entry_decode(&bv, e, bdb->bi_cache.c_zctx); +#else + rc = entry_decode(&bv, e); +#endif if( rc == 0 ) { (*e)->e_id = id; @@ -121,46 +143,13 @@ int bdb_id2entry_rw( /* only free on error. On success, the entry was * decoded in place. */ - ch_free( data.data ); - } - - if ( rc == 0 ) { -#ifdef BDB_HIER - bdb_fix_dn(be, id, *e); +#ifndef SLAP_ZONE_ALLOC + ch_free(data.data); #endif - ret = bdb_cache_add_entry_rw( bdb->bi_dbenv, - &bdb->bi_cache, *e, rw, locker, lock); - while ( ret == 1 || ret == -1 ) { - Entry *ee; - int add_loop_cnt = 0; - if ( (*e)->e_private != NULL ) { - free ((*e)->e_private); - } - (*e)->e_private = NULL; - if ( (ee = bdb_cache_find_entry_id - (bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock) ) != NULL) { - bdb_entry_return ( *e ); - *e = ee; - return 0; - } - if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) { - bdb_entry_return ( *e ); - *e = NULL; - return LDAP_BUSY; - } - } - if ( ret != 0 ) { - if ( (*e)->e_private != NULL ) - free ( (*e)->e_private ); - bdb_entry_return( *e ); - *e = NULL; - } - rc = ret; - } - - if (rc == 0) { - bdb_cache_entry_commit(*e); } +#ifdef SLAP_ZONE_ALLOC + ch_free(data.data); +#endif return rc; } @@ -174,12 +163,12 @@ int bdb_id2entry_delete( DB *db = bdb->bi_id2entry->bdi_db; DBT key; int rc; - - bdb_cache_delete_entry(&bdb->bi_cache, e); + ID nid; DBTzero( &key ); - key.data = (char *) &e->e_id; + key.data = &nid; key.size = sizeof(ID); + BDB_ID2DISK( e->e_id, &nid ); /* delete from database */ rc = db->del( db, tid, &key, 0 ); @@ -187,9 +176,23 @@ int bdb_id2entry_delete( return rc; } +#ifdef SLAP_ZONE_ALLOC int bdb_entry_return( - Entry *e ) + struct bdb_info *bdb, + Entry *e, + int zseq +) +#else +int bdb_entry_return( + Entry *e +) +#endif { +#ifdef SLAP_ZONE_ALLOC + if (!slap_zn_validate(bdb->bi_cache.c_zctx, e, zseq)) { + return 0; + } +#endif /* Our entries are allocated in two blocks; the data comes from * the db itself and the Entry structure and associated pointers * are allocated in entry_decode. The db data pointer is saved @@ -198,27 +201,18 @@ int bdb_entry_return( * is when an entry has been modified, in which case we also need * to free e_attrs. */ - if( !e->e_bv.bv_val ) { /* A regular entry, from do_add */ + +#ifdef LDAP_COMP_MATCH + comp_tree_free( e->e_attrs ); +#endif + if( !e->e_bv.bv_val ) { /* Entry added by do_add */ entry_free( e ); return 0; } if( (void *) e->e_attrs != (void *) (e+1)) { attrs_free( e->e_attrs ); } -#if defined(SLAP_NVALUES) && !defined(SLAP_NVALUES_ON_DISK) - else { - /* nvals are not contiguous with the rest. oh well. */ - Attribute *a; - for (a = e->e_attrs; a; a=a->a_next) { - if (a->a_nvals != a->a_vals) { - ber_bvarray_free( a->a_nvals ); - a->a_nvals = NULL; - } - } - } -#endif -#ifndef BDB_HIER /* See if the DNs were changed by modrdn */ if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val > e->e_bv.bv_val + e->e_bv.bv_len ) { @@ -227,51 +221,83 @@ int bdb_entry_return( e->e_name.bv_val = NULL; e->e_nname.bv_val = NULL; } -#else - /* We had to construct the dn and ndn as well, in a single block */ - if( e->e_name.bv_val ) { - free( e->e_name.bv_val ); - } -#endif +#ifndef SLAP_ZONE_ALLOC /* In tool mode the e_bv buffer is realloc'd, leave it alone */ if( !(slapMode & SLAP_TOOL_MODE) ) { free( e->e_bv.bv_val ); } +#endif /* !SLAP_ZONE_ALLOC */ +#ifdef SLAP_ZONE_ALLOC + slap_zn_free( e, bdb->bi_cache.c_zctx ); +#else free( e ); +#endif return 0; } int bdb_entry_release( - Operation *o, + Operation *op, Entry *e, int rw ) { - struct bdb_info *bdb = (struct bdb_info *) o->o_bd->be_private; + struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; struct bdb_op_info *boi = NULL; /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE, SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */ if ( slapMode == SLAP_SERVER_MODE ) { + /* If not in our cache, just free it */ + if ( !e->e_private ) { +#ifdef SLAP_ZONE_ALLOC + return bdb_entry_return( bdb, e, -1 ); +#else + return bdb_entry_return( e ); +#endif + } /* free entry and reader or writer lock */ - if ( o ) { - boi = (struct bdb_op_info *)o->o_private; + if ( op ) { + boi = (struct bdb_op_info *)op->o_private; } /* lock is freed with txn */ if ( !boi || boi->boi_txn ) { bdb_unlocked_cache_return_entry_rw( &bdb->bi_cache, e, rw ); } else { - bdb_cache_return_entry_rw( bdb->bi_dbenv, &bdb->bi_cache, e, rw, &boi->boi_lock ); - ch_free( boi ); - o->o_private = NULL; + struct bdb_lock_info *bli, *prev; + for ( prev=(struct bdb_lock_info *)&boi->boi_locks, + bli = boi->boi_locks; bli; prev=bli, bli=bli->bli_next ) { + if ( bli->bli_id == e->e_id ) { + bdb_cache_return_entry_rw( bdb->bi_dbenv, &bdb->bi_cache, + e, rw, &bli->bli_lock ); + prev->bli_next = bli->bli_next; + op->o_tmpfree( bli, op->o_tmpmemctx ); + break; + } + } + if ( !boi->boi_locks ) { + op->o_tmpfree( boi, op->o_tmpmemctx ); + op->o_private = NULL; + } } } else { +#ifdef SLAP_ZONE_ALLOC + int zseq = -1; + if (e->e_private != NULL) { + BEI(e)->bei_e = NULL; + zseq = BEI(e)->bei_zseq; + } +#else if (e->e_private != NULL) - free (e->e_private); + BEI(e)->bei_e = NULL; +#endif e->e_private = NULL; +#ifdef SLAP_ZONE_ALLOC + bdb_entry_return ( bdb, e, zseq ); +#else bdb_entry_return ( e ); +#endif } return 0; @@ -290,30 +316,23 @@ int bdb_entry_get( struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; struct bdb_op_info *boi = NULL; DB_TXN *txn = NULL; - Entry *e; + Entry *e = NULL; + EntryInfo *ei; int rc; - const char *at_name = at->ad_cname.bv_val; + const char *at_name = at ? at->ad_cname.bv_val : "(null)"; u_int32_t locker = 0; DB_LOCK lock; int free_lock_id = 0; -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, ARGS, - "bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); - LDAP_LOG( BACK_BDB, ARGS, - "bdb_entry_get: oc: \"%s\", at: \"%s\"\n", - oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); -#else Debug( LDAP_DEBUG_ARGS, "=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); Debug( LDAP_DEBUG_ARGS, "=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n", oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); -#endif if( op ) boi = (struct bdb_op_info *) op->o_private; - if( boi != NULL && op->o_bd == boi->boi_bdb ) { + if( boi != NULL && op->o_bd->be_private == boi->boi_bdb->be_private ) { txn = boi->boi_txn; locker = boi->boi_locker; } @@ -333,7 +352,7 @@ int bdb_entry_get( dn2entry_retry: /* can we find entry */ - rc = bdb_dn2entry_rw( op->o_bd, txn, ndn, &e, NULL, 0, rw, locker, &lock ); + rc = bdb_dn2entry( op, txn, ndn, &ei, 0, locker, &lock ); switch( rc ) { case DB_NOTFOUND: case 0: @@ -348,73 +367,46 @@ dn2entry_retry: ldap_pvt_thread_yield(); goto dn2entry_retry; default: - boi->boi_err = rc; + if ( boi ) boi->boi_err = rc; if ( free_lock_id ) { LOCK_ID_FREE( bdb->bi_dbenv, locker ); } return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY; } + if (ei) e = ei->bei_e; if (e == NULL) { -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, INFO, - "bdb_entry_get: cannot find entry (%s)\n", - ndn->bv_val, 0, 0 ); -#else Debug( LDAP_DEBUG_ACL, "=> bdb_entry_get: cannot find entry: \"%s\"\n", ndn->bv_val, 0, 0 ); -#endif if ( free_lock_id ) { LOCK_ID_FREE( bdb->bi_dbenv, locker ); } return LDAP_NO_SUCH_OBJECT; } -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, DETAIL1, "bdb_entry_get: found entry (%s)\n", - ndn->bv_val, 0, 0 ); -#else Debug( LDAP_DEBUG_ACL, "=> bdb_entry_get: found entry: \"%s\"\n", ndn->bv_val, 0, 0 ); -#endif -#ifdef BDB_ALIASES /* find attribute values */ if( is_entry_alias( e ) ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, INFO, - "bdb_entry_get: entry (%s) is an alias\n", e->e_name.bv_val, 0, 0 ); -#else Debug( LDAP_DEBUG_ACL, "<= bdb_entry_get: entry is an alias\n", 0, 0, 0 ); -#endif rc = LDAP_ALIAS_PROBLEM; goto return_results; } -#endif if( is_entry_referral( e ) ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, INFO, - "bdb_entry_get: entry (%s) is a referral.\n", e->e_name.bv_val, 0, 0); -#else Debug( LDAP_DEBUG_ACL, "<= bdb_entry_get: entry is a referral\n", 0, 0, 0 ); -#endif rc = LDAP_REFERRAL; goto return_results; } if ( oc && !is_entry_objectclass( e, oc, 0 )) { -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, INFO, - "bdb_entry_get: failed to find objectClass.\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_ACL, - "<= bdb_entry_get: failed to find objectClass\n", - 0, 0, 0 ); -#endif + "<= bdb_entry_get: failed to find objectClass %s\n", + oc->soc_cname.bv_val, 0, 0 ); rc = LDAP_NO_SUCH_ATTRIBUTE; goto return_results; } @@ -423,15 +415,33 @@ return_results: if( rc != LDAP_SUCCESS ) { /* free entry */ bdb_cache_return_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, rw, &lock); + } else { - *ent = e; - /* big drag. we need a place to store a read lock so we can - * release it later?? - */ - if ( op && !boi ) { - boi = ch_calloc(1,sizeof(struct bdb_op_info)); - boi->boi_lock = lock; - op->o_private = boi; + if ( slapMode == SLAP_SERVER_MODE ) { + *ent = e; + /* big drag. we need a place to store a read lock so we can + * release it later?? If we're in a txn, nothing is needed + * here because the locks will go away with the txn. + */ + if ( op ) { + if ( !boi ) { + boi = op->o_tmpcalloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx); + boi->boi_bdb = op->o_bd; + op->o_private = boi; + } + if ( !boi->boi_txn ) { + struct bdb_lock_info *bli; + bli = op->o_tmpalloc( sizeof(struct bdb_lock_info), + op->o_tmpmemctx ); + bli->bli_next = boi->boi_locks; + bli->bli_id = e->e_id; + bli->bli_lock = lock; + boi->boi_locks = bli; + } + } + } else { + *ent = entry_dup( e ); + bdb_cache_return_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, rw, &lock); } } @@ -439,12 +449,8 @@ return_results: LOCK_ID_FREE( bdb->bi_dbenv, locker ); } -#ifdef NEW_LOGGING - LDAP_LOG( BACK_BDB, ENTRY, "bdb_entry_get: rc=%d\n", rc, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "bdb_entry_get: rc=%d\n", rc, 0, 0 ); -#endif return(rc); }