X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fid2entry.c;h=98c75bb9fa952e6b69ca561d72b4b2edf30c8c9f;hb=4e32148ac59ba6b4f3acc79a3b782cd3556f941a;hp=2635e1d42400b5ddf3a6020fa425853bfbc5ca34;hpb=d9927adf88298b8dbfeb47bde1f7dda8127cc18f;p=openldap diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 2635e1d424..98c75bb9fa 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2004 The OpenLDAP Foundation. + * Copyright 2000-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -18,9 +18,9 @@ #include #include +#include #include "back-bdb.h" -#include "external.h" static int bdb_id2entry_put( BackendDB *be, @@ -33,6 +33,7 @@ static int bdb_id2entry_put( DBT key, data; struct berval bv; int rc; + ID nid; #ifdef BDB_HIER struct berval odn, ondn; @@ -44,8 +45,11 @@ static 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 @@ -89,34 +93,81 @@ int bdb_id2entry_update( int bdb_id2entry( BackendDB *be, DB_TXN *tid, + BDB_LOCKER locker, ID id, Entry **e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_id2entry->bdi_db; DBT key, data; - struct berval bv; - int rc = 0, ret = 0; + DBC *cursor; + EntryHeader eh; + char buf[16]; + int rc = 0, off; + 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; + data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; /* fetch it */ - rc = db->get( db, tid, &key, &data, bdb->bi_db_opflags ); + rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); + if ( rc ) return rc; + + /* Use our own locker if needed */ + if ( !tid && locker ) { + CURSOR_SETLOCKER( cursor, locker ); + } + + /* Get the nattrs / nvals counts first */ + data.ulen = data.dlen = sizeof(buf); + data.data = buf; + rc = cursor->c_get( cursor, &key, &data, DB_SET ); + if ( rc ) goto finish; + + + eh.bv.bv_val = buf; + eh.bv.bv_len = data.size; + rc = entry_header( &eh ); + if ( rc ) goto finish; + + /* Get the size */ + data.flags ^= DB_DBT_PARTIAL; + data.ulen = 0; + rc = cursor->c_get( cursor, &key, &data, DB_CURRENT ); + if ( rc != DB_BUFFER_SMALL ) goto finish; + + /* Allocate a block and retrieve the data */ + off = eh.data - eh.bv.bv_val; + eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + data.size; + eh.bv.bv_val = ch_malloc( eh.bv.bv_len ); + eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval ); + data.data = eh.data; + data.ulen = data.size; + + /* skip past already parsed nattr/nvals */ + eh.data += off; + + rc = cursor->c_get( cursor, &key, &data, DB_CURRENT ); + +finish: + cursor->c_close( cursor ); if( rc != 0 ) { return rc; } - DBT2bv( &data, &bv ); - - rc = entry_decode( &bv, e ); +#ifdef SLAP_ZONE_ALLOC + rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx); +#else + rc = entry_decode(&eh, e); +#endif if( rc == 0 ) { (*e)->e_id = id; @@ -124,8 +175,13 @@ int bdb_id2entry( /* only free on error. On success, the entry was * decoded in place. */ - ch_free( data.data ); +#ifndef SLAP_ZONE_ALLOC + ch_free(eh.bv.bv_val); +#endif } +#ifdef SLAP_ZONE_ALLOC + ch_free(eh.bv.bv_val); +#endif return rc; } @@ -139,10 +195,12 @@ int bdb_id2entry_delete( DB *db = bdb->bi_id2entry->bdi_db; DBT key; int rc; + 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 ); @@ -151,51 +209,39 @@ int bdb_id2entry_delete( } int bdb_entry_return( - Entry *e ) + Entry *e +) { /* 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 - * in e_bv. Since the Entry structure is allocated as a single - * block, e_attrs is always a fixed offset from e. The exception - * is when an entry has been modified, in which case we also need - * to free e_attrs. + * in e_bv. */ - if( !e->e_bv.bv_val ) { /* A regular entry, from do_add */ - entry_free( e ); - return 0; - } - if( (void *) e->e_attrs != (void *) (e+1)) { - attrs_free( e->e_attrs ); - } - - /* 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 ) { - ch_free(e->e_name.bv_val); - ch_free(e->e_nname.bv_val); + if ( e->e_bv.bv_val ) { + /* 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 ) { + ch_free(e->e_name.bv_val); + ch_free(e->e_nname.bv_val); + } e->e_name.bv_val = NULL; e->e_nname.bv_val = NULL; + /* In tool mode the e_bv buffer is realloc'd, leave it alone */ + if( !(slapMode & SLAP_TOOL_MODE) ) { + free( e->e_bv.bv_val ); + } + BER_BVZERO( &e->e_bv ); } -#ifndef BDB_HIER - /* In tool mode the e_bv buffer is realloc'd, leave it alone */ - if( !(slapMode & SLAP_TOOL_MODE) ) { - free( e->e_bv.bv_val ); - } -#else - free( e->e_bv.bv_val ); -#endif - free( e ); - + entry_free( e ); 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, @@ -204,25 +250,51 @@ int bdb_entry_release( 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; - } + 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 ); + bdb_unlocked_cache_return_entry_rw( bdb, e, rw ); } else { - bdb_cache_return_entry_rw( bdb->bi_dbenv, &bdb->bi_cache, e, rw, &boi->boi_lock ); - o->o_tmpfree( boi, o->o_tmpmemctx ); - 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, 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) 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; @@ -246,23 +318,15 @@ int bdb_entry_get( int rc; const char *at_name = at ? at->ad_cname.bv_val : "(null)"; - u_int32_t locker = 0; + BDB_LOCKER 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->be_private == boi->boi_bdb->be_private ) { @@ -308,66 +372,23 @@ dn2entry_retry: } 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; } @@ -375,23 +396,34 @@ dn2entry_retry: return_results: if( rc != LDAP_SUCCESS ) { /* free entry */ - bdb_cache_return_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, rw, &lock); + bdb_cache_return_entry_rw(bdb, e, rw, &lock); } else { if ( slapMode == SLAP_SERVER_MODE ) { *ent = e; /* big drag. we need a place to store a read lock so we can - * release it later?? + * release it later?? If we're in a txn, nothing is needed + * here because the locks will go away with the txn. */ - if ( op && !boi ) { - boi = op->o_tmpcalloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx); - boi->boi_lock = lock; - op->o_private = boi; + 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); + bdb_cache_return_entry_rw(bdb, e, rw, &lock); } } @@ -399,12 +431,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); }