]> git.sur5r.net Git - openldap/commitdiff
Tentative fix for ITS #402. (Not tested yet.) If successful, this patch
authorHoward Chu <hyc@openldap.org>
Fri, 17 Dec 1999 10:04:31 +0000 (10:04 +0000)
committerHoward Chu <hyc@openldap.org>
Fri, 17 Dec 1999 10:04:31 +0000 (10:04 +0000)
should also be applied to back-bdb2/idl.c.

servers/slapd/back-ldbm/idl.c

index 22093a78e607efbf5936b3ed00f8309d9e5d25b2..54b058cdc24125aa0da2750d3b0d7c6597a13f14 100644 (file)
@@ -484,18 +484,52 @@ idl_insert_key(
                /* is there a next block? */
                if ( !first && !ID_BLOCK_NOID(idl, i + 1) ) {
                        /* read it in */
-                       sprintf( kstr, "%c%ld%s", CONT_PREFIX,
+                       k2.dptr = (char *) ch_malloc( key.dsize + CONT_SIZE );
+                       sprintf( k2.dptr, "%c%ld%s", CONT_PREFIX,
                                ID_BLOCK_ID(idl, i + 1), key.dptr );
-                       k2.dptr = kstr;
-                       k2.dsize = strlen( kstr ) + 1;
+                       k2.dsize = strlen( k2.dptr ) + 1;
                        if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) {
                                Debug( LDAP_DEBUG_ANY,
                                    "idl_fetch_one (%s) returns NULL\n",
                                    k2.dptr, 0, 0 );
                                /* split the original block */
+                               free( k2.dptr );
                                goto split;
                        }
 
+                       /* If the new id is less than the last id in the
+                        * current block, it must not be put into the next
+                        * block. Push the last id of the current block
+                        * into the next block instead.
+                        */
+                       if (id < ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp) - 1)) {
+                           ID id2 = ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp) - 1);
+                           Datum k3;
+
+                           ldbm_datum_init( k3 );
+
+                           --ID_BLOCK_NIDS(tmp);
+                           /* This must succeed since we just popped one
+                            * ID off the end of it.
+                            */
+                           rc = idl_insert( &tmp, id, db->dbc_maxids );
+                           assert( rc == 0 );
+                           k3.dptr = kstr;
+                           k3.dsize = strlen( kstr ) + 1;
+                           if ( (rc = idl_store( be, db, k3, tmp )) != 0 ) {
+                               Debug( LDAP_DEBUG_ANY,
+                           "idl_store of (%s) returns %d\n", k3.dptr, rc, 0 );
+                           }
+                           free( kstr );
+                           kstr = k2.dptr;
+
+                           id = id2;
+                           /* This new id will necessarily be inserted
+                            * as the first id of the next block by the
+                            * following switch() statement.
+                            */
+                       }
+
                        switch ( (rc = idl_insert( &tmp2, id,
                            db->dbc_maxids )) ) {
                        case 1:         /* id inserted first in block */
@@ -504,7 +538,11 @@ idl_insert_key(
                                /* FALL */
 
                        case 2:         /* id already there - how? */
-                       case 0:         /* id inserted */
+                       case 0:         /* id inserted: this can never be
+                                        * the result of idl_insert, because
+                                        * we guaranteed that idl_change_first
+                                        * will always be called.
+                                        */
                                if ( rc == 2 ) {
                                        Debug( LDAP_DEBUG_ANY,
                                            "id %ld already in next block\n",