]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/id2entry.c
Merge remote-tracking branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / servers / slapd / back-bdb / id2entry.c
index 76ad30ce3bf9a90cd92195bd2112674068df8d6a..03c142ea1cf82f57cfd15d2e72634ed8fedb183e 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2008 The OpenLDAP Foundation.
+ * Copyright 2000-2013 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,7 +93,6 @@ int bdb_id2entry_update(
 int bdb_id2entry(
        BackendDB *be,
        DB_TXN *tid,
-       BDB_LOCKER locker,
        ID id,
        Entry **e )
 {
@@ -120,11 +119,6 @@ int bdb_id2entry(
        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;
@@ -137,24 +131,26 @@ int bdb_id2entry(
        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 );
+       if ( eh.nvals ) {
+               /* 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 );
@@ -163,11 +159,15 @@ finish:
                return rc;
        }
 
+       if ( eh.nvals ) {
 #ifdef SLAP_ZONE_ALLOC
-       rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
+               rc = entry_decode(&eh, e, bdb->bi_cache.c_zctx);
 #else
-       rc = entry_decode(&eh, e);
+               rc = entry_decode(&eh, e);
 #endif
+       } else {
+               *e = entry_alloc();
+       }
 
        if( rc == 0 ) {
                (*e)->e_id = id;
@@ -248,7 +248,7 @@ int bdb_entry_release(
        /* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
                        SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
  
-       if ( slapMode == SLAP_SERVER_MODE ) {
+       if ( slapMode & SLAP_SERVER_MODE ) {
                /* If not in our cache, just free it */
                if ( !e->e_private ) {
 #ifdef SLAP_ZONE_ALLOC
@@ -273,13 +273,18 @@ int bdb_entry_release(
                                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 );
+                                       /* Cleanup, or let caller know we unlocked */
+                                       if ( bli->bli_flag & BLI_DONTFREE )
+                                               bli->bli_flag = 0;
+                                       else
+                                               op->o_tmpfree( bli, op->o_tmpmemctx );
                                        break;
                                }
                        }
                        if ( !boi->boi_locks ) {
                                LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
-                               op->o_tmpfree( boi, op->o_tmpmemctx );
+                               if ( !(boi->boi_flag & BOI_DONTFREE))
+                                       op->o_tmpfree( boi, op->o_tmpmemctx );
                        }
                }
        } else {
@@ -322,9 +327,7 @@ int bdb_entry_get(
        int     rc;
        const char *at_name = at ? at->ad_cname.bv_val : "(null)";
 
-       BDB_LOCKER      locker = 0;
        DB_LOCK         lock;
-       int             free_lock_id = 0;
 
        Debug( LDAP_DEBUG_ARGS,
                "=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); 
@@ -342,11 +345,8 @@ int bdb_entry_get(
                        txn = boi->boi_txn;
        }
 
-       if ( txn != NULL ) {
-               locker = TXN_ID ( txn );
-       } else {
-               rc = LOCK_ID ( bdb->bi_dbenv, &locker );
-               free_lock_id = 1;
+       if ( !txn ) {
+               rc = bdb_reader_get( op, bdb->bi_dbenv, &txn );
                switch(rc) {
                case 0:
                        break;
@@ -357,7 +357,7 @@ int bdb_entry_get(
 
 dn2entry_retry:
        /* can we find entry */
-       rc = bdb_dn2entry( op, txn, ndn, &ei, 0, locker, &lock );
+       rc = bdb_dn2entry( op, txn, ndn, &ei, 0, &lock );
        switch( rc ) {
        case DB_NOTFOUND:
        case 0:
@@ -366,16 +366,13 @@ dn2entry_retry:
        case DB_LOCK_NOTGRANTED:
                /* the txn must abort and retry */
                if ( txn ) {
-                       boi->boi_err = rc;
+                       if ( boi ) boi->boi_err = rc;
                        return LDAP_BUSY;
                }
                ldap_pvt_thread_yield();
                goto dn2entry_retry;
        default:
                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;
@@ -383,9 +380,6 @@ dn2entry_retry:
                Debug( LDAP_DEBUG_ACL,
                        "=> bdb_entry_get: cannot find entry: \"%s\"\n",
                                ndn->bv_val, 0, 0 ); 
-               if ( free_lock_id ) {
-                       LOCK_ID_FREE( bdb->bi_dbenv, locker );
-               }
                return LDAP_NO_SUCH_OBJECT; 
        }
        
@@ -416,7 +410,7 @@ return_results:
                bdb_cache_return_entry_rw(bdb, e, rw, &lock);
 
        } else {
-               if ( slapMode == SLAP_SERVER_MODE ) {
+               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
@@ -434,6 +428,7 @@ return_results:
                                                op->o_tmpmemctx );
                                        bli->bli_next = boi->boi_locks;
                                        bli->bli_id = e->e_id;
+                                       bli->bli_flag = 0;
                                        bli->bli_lock = lock;
                                        boi->boi_locks = bli;
                                }
@@ -444,10 +439,6 @@ return_results:
                }
        }
 
-       if ( free_lock_id ) {
-               LOCK_ID_FREE( bdb->bi_dbenv, locker );
-       }
-
        Debug( LDAP_DEBUG_TRACE,
                "bdb_entry_get: rc=%d\n",
                rc, 0, 0 );