]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldbm/idl.c
ITS#2864 don't use sl_mark/release.
[openldap] / servers / slapd / back-ldbm / idl.c
index a070f46adf399002cb42b59d386bad7cc9bb4f01..dbcc8f41b7a18eb96df3ff9112b39b427be4a0c5 100644 (file)
@@ -1,8 +1,17 @@
 /* idl.c - ldap id list handling routines */
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2003 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
+ * <http://www.OpenLDAP.org/license.html>.
  */
 
 #include "portable.h"
@@ -48,17 +57,29 @@ static void cont_free( Datum *cont )
 #ifdef LDBM_DEBUG_IDL
 static void idl_check(ID_BLOCK *idl)
 {
-       int i;
+       int i, max;
        ID_BLOCK last;
 
-       if( ID_BLOCK_INDIRECT(idl) || ID_BLOCK_ALLIDS(idl)
-               || ID_BLOCK_NIDS(idl) <= 1 )
+       if( ID_BLOCK_ALLIDS(idl) )
+       {
+               return;
+       }
+#ifndef USE_INDIRECT_NIDS
+       if( ID_BLOCK_INDIRECT(idl) )
+       {
+               for ( max = 0; !ID_BLOCK_NOID(idl, max); max++ ) ;
+       } else
+#endif
+       {
+               max = ID_BLOCK_NIDS(idl);
+       }
+       if ( max <= 1 )
        {
                return;
        }
 
        for( last = ID_BLOCK_ID(idl, 0), i = 1;
-               i < ID_BLOCK_NIDS(idl);
+               i < max;
                last = ID_BLOCK_ID(idl, i), i++ )
        {
                assert (last < ID_BLOCK_ID(idl, i) );
@@ -170,8 +191,7 @@ idl_fetch(
        Datum   data;
        ID_BLOCK        *idl;
        ID_BLOCK        **tmp;
-       int     nids;
-       unsigned i;
+       unsigned        i, nids, nblocks;
 
        idl = idl_fetch_one( be, db, key );
 
@@ -197,21 +217,17 @@ idl_fetch(
 
 #ifndef USE_INDIRECT_NIDS
        /* count the number of blocks & allocate space for pointers to them */
-       for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ )
+       for ( nblocks = 0; !ID_BLOCK_NOID(idl, nblocks); nblocks++ )
                ;       /* NULL */
 #else
-       i = ID_BLOCK_NIDS(idl);
+       nblocks = ID_BLOCK_NIDS(idl);
 #endif
-       tmp = (ID_BLOCK **) ch_malloc( (i + 1) * sizeof(ID_BLOCK *) );
+       tmp = (ID_BLOCK **) ch_malloc( nblocks * sizeof(ID_BLOCK *) );
 
        /* read in all the blocks */
        cont_alloc( &data, &key );
        nids = 0;
-#ifndef USE_INDIRECT_NIDS
-       for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) {
-#else
-       for ( i = 0; i < ID_BLOCK_NIDS(idl); i++ ) {
-#endif
+       for ( i = 0; i < nblocks; i++ ) {
                cont_id( &data, ID_BLOCK_ID(idl, i) );
 
                if ( (tmp[i] = idl_fetch_one( be, db, data )) == NULL ) {
@@ -228,7 +244,6 @@ idl_fetch(
 
                nids += ID_BLOCK_NIDS(tmp[i]);
        }
-       tmp[i] = NULL;
        cont_free( &data );
        idl_free( idl );
 
@@ -238,7 +253,7 @@ idl_fetch(
        nids = 0;
 
        /* copy in all the ids from the component blocks */
-       for ( i = 0; tmp[i] != NULL; i++ ) {
+       for ( i = 0; i < nblocks; i++ ) {
                if ( tmp[i] == NULL ) {
                        continue;
                }
@@ -253,6 +268,8 @@ idl_fetch(
        }
        free( (char *) tmp );
 
+       assert( ID_BLOCK_NIDS(idl) == nids );
+
 #ifdef LDBM_DEBUG_IDL
        idl_check(idl);
 #endif
@@ -296,11 +313,6 @@ idl_store(
        flags = LDBM_REPLACE;
        rc = ldbm_cache_store( db, key, data, flags );
 
-#ifdef LDBM_DEBUG
-       Statslog( LDAP_DEBUG_STATS, "<= idl_store(): rc=%d\n",
-               rc, 0, 0, 0, 0 );
-#endif
-
        /* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */
        return( rc );
 }
@@ -550,14 +562,13 @@ idl_insert_key(
 
 #ifndef USE_INDIRECT_NIDS
        /* select the block to try inserting into *//* XXX linear search XXX */
-       for ( i = 0; !ID_BLOCK_NOID(idl, i) && id > ID_BLOCK_ID(idl, i); i++ )
+       for ( i = 0; !ID_BLOCK_NOID(idl, i) && id >= ID_BLOCK_ID(idl, i); i++ )
                ;       /* NULL */
 #else
        i = idl_find(idl, id);
-       if (ID_BLOCK_ID(idl, i) < id)
+       if (ID_BLOCK_ID(idl, i) <= id)
                i++;
 #endif
-
        if ( i != 0 ) {
                i--;
                first = 0;
@@ -565,6 +576,11 @@ idl_insert_key(
                first = 1;
        }
 
+       /* At this point, the following condition must be true:
+        * ID_BLOCK_ID(idl, i) <= id && id < ID_BLOCK_ID(idl, i+1)
+        * except when i is the first or the last block.
+        */
+
        /* get the block */
        cont_alloc( &k2, &key );
        cont_id( &k2, ID_BLOCK_ID(idl, i) );
@@ -626,10 +642,11 @@ idl_insert_key(
 #else
                if ( !first && (unsigned long)(i + 1) < ID_BLOCK_NIDS(idl) ) {
 #endif
+                       Datum k3;
                        /* read it in */
-                       cont_alloc( &k2, &key );
-                       cont_id( &k2, ID_BLOCK_ID(idl, i) );
-                       if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) {
+                       cont_alloc( &k3, &key );
+                       cont_id( &k3, ID_BLOCK_ID(idl, i + 1) );
+                       if ( (tmp2 = idl_fetch_one( be, db, k3 )) == NULL ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG( INDEX, ERR,
                                           "idl_insert_key: idl_fetch_one returned NULL\n", 0, 0, 0);
@@ -640,7 +657,7 @@ idl_insert_key(
 #endif
 
                                /* split the original block */
-                               cont_free( &k2 );
+                               cont_free( &k3 );
                                goto split;
                        }
 
@@ -680,7 +697,7 @@ idl_insert_key(
                            db->dbc_maxids )) ) {
                        case 1:         /* id inserted first in block */
                                rc = idl_change_first( be, db, key, idl,
-                                   i + 1, k2, tmp2 );
+                                   i + 1, k3, tmp2 );
                                /* FALL */
 
                        case 2:         /* id already there - how? */
@@ -704,6 +721,8 @@ idl_insert_key(
 
                                idl_free( tmp );
                                idl_free( tmp2 );
+                               cont_free( &k3 );
+                               cont_free( &k2 );
                                idl_free( idl );
                                return( 0 );
 
@@ -712,6 +731,7 @@ idl_insert_key(
                        }
 
                        idl_free( tmp2 );
+                       cont_free( &k3 );
                }
 
 split: