Annotation of kernel/bsd/hfs/hfscommon/BTree/BTreeTreeOps.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:        File:           BTreeTreeOps.c
                     27: 
                     28:        Contains:       Multi-node tree operations for the BTree Module.
                     29: 
                     30:        Version:        xxx put the technology version here xxx
                     31: 
                     32:        Written by:     Gordon Sheridan and Bill Bruffey
                     33: 
                     34:        Copyright:      � 1992-1998 by Apple Computer, Inc., all rights reserved.
                     35: 
                     36:        File Ownership:
                     37: 
                     38:                DRI:                            Don Brady
                     39: 
                     40:                Other Contact:          Mark Day
                     41: 
                     42:                Technology:                     File Systems
                     43: 
                     44:        Writers:
                     45: 
                     46:                (msd)   Mark Day
                     47:                (DSH)   Deric Horn
                     48:                (djb)   Don Brady
                     49: 
                     50:        Change History (most recent first):
                     51: 
                     52:           <CS5>         12/8/97        djb             Radar #2200632, CollapseTree wasn't marking root node dirty.
                     53:           <CS4>        11/24/97        djb             Radar #2005325, InsertLevel incorrectly handled root splits!
                     54:           <CS3>        10/17/97        msd             Conditionalize DebugStrs.
                     55:           <CS2>         5/16/97        msd             InsertNode() needs a return statement in ErrorExit.
                     56:           <CS1>         4/23/97        djb             first checked in
                     57: 
                     58:          <HFS8>         3/17/97        DSH             Conditionalize out Panic assertion for SC.
                     59:          <HFS7>          3/3/97        djb             Removed DebugStr in InsertLevel.
                     60:          <HFS6>         2/19/97        djb             Major re-write of insert code; added InsertLevel and InsertNode.
                     61:          <HFS5>         1/27/97        djb             InsertTree and DeleteTree are now recursive and support variable
                     62:                                                                        sized index keys.
                     63:          <HFS4>         1/16/97        djb             Removed DebugStr in SearchTree. Added initial support for
                     64:                                                                        variable sized index keys.
                     65:          <HFS3>          1/3/97        djb             Changed len8 to length8.
                     66:          <HFS2>          1/3/97        djb             Added support for large keys.
                     67:          <HFS1>        12/19/96        djb             first checked in
                     68: 
                     69:        History applicable to original Scarecrow Design:
                     70: 
                     71:                 <3>    10/25/96        ser             Changing for new VFPI
                     72:                 <2>     1/22/96        dkh             Add #include Memory.h
                     73:                 <1>    10/18/95        rst             Moved from Scarecrow project.
                     74: 
                     75:                <12>     7/18/95        mbb             Change MoveData & ClearBytes to BlockMoveData & BlockZero.
                     76:                <11>     9/30/94        prp             Get in sync with D2 interface changes.
                     77:                <10>     7/25/94        wjk             Eliminate usage of BytePtr in favor of UInt8 *.
                     78:                 <9>     7/22/94        wjk             Convert to the new set of header files.
                     79:                 <8>     12/2/93        wjk             Move from Makefiles to BuildFiles. Fit into the ModernOS and
                     80:                                                                        NRCmds environments.
                     81:                 <7>    11/30/93        wjk             Change some Ptr's to BytePtr's in function definitions so they
                     82:                                                                        agree with their prototypes.
                     83:                 <6>     5/21/93        gs              Debug DeleteTree. Modify InsertTree for BTReplaceRecord.
                     84:                 <5>     5/10/93        gs              Modify RotateLeft, and add DeleteTree, CollapseTree routines.
                     85:                 <4>     3/23/93        gs              revise RotateLeft to use InsertKeyRecord instead of
                     86:                                                                        InsertRecord.
                     87:                 <3>     3/23/93        gs              Implement SplitLeft, InsertTree routine.
                     88:                 <2>      2/8/93        gs              Implement SearchTree, and RotateLeft.
                     89:                 <1>    11/15/92        gs              first checked in
                     90: 
                     91: */
                     92: 
                     93: #include "../headers/BTreesPrivate.h"
                     94: 
                     95: //
                     96: /////////////////////// Routines Internal To BTree Module ///////////////////////
                     97: //
                     98: //     SearchTree
                     99: //     InsertTree
                    100: //
                    101: ////////////////////// Routines Internal To BTreeTreeOps.c //////////////////////
                    102: 
                    103: static OSStatus   AddNewRootNode       (BTreeControlBlockPtr            btreePtr,
                    104:                                                                         NodeDescPtr                             leftNode,
                    105:                                                                         NodeDescPtr                             rightNode );
                    106: 
                    107: static OSStatus   CollapseTree         (BTreeControlBlockPtr            btreePtr,
                    108:                                                                         BlockDescriptor                        *blockPtr );
                    109: 
                    110: static OSStatus   RotateLeft           (BTreeControlBlockPtr            btreePtr,
                    111:                                                                         NodeDescPtr                             leftNode,
                    112:                                                                         NodeDescPtr                             rightNode,
                    113:                                                                         UInt16                                          rightInsertIndex,
                    114:                                                                         KeyPtr                                          keyPtr,
                    115:                                                                         UInt8 *                                         recPtr,
                    116:                                                                         UInt16                                          recSize,
                    117:                                                                         UInt16                                         *insertIndex,
                    118:                                                                         UInt32                                         *insertNodeNum,
                    119:                                                                         Boolean                                        *recordFit,
                    120:                                                                         UInt16                                         *recsRotated );
                    121: 
                    122: static Boolean    RotateRecordLeft     (BTreeControlBlockPtr            btreePtr,
                    123:                                                                         NodeDescPtr                             leftNode,
                    124:                                                                         NodeDescPtr                             rightNode );
                    125: 
                    126: static OSStatus           SplitLeft            (BTreeControlBlockPtr            btreePtr,
                    127:                                                                         BlockDescriptor                        *leftNode,
                    128:                                                                         BlockDescriptor                        *rightNode,
                    129:                                                                         UInt32                                          rightNodeNum,
                    130:                                                                         UInt16                                          index,
                    131:                                                                         KeyPtr                                          keyPtr,
                    132:                                                                         UInt8 *                                         recPtr,
                    133:                                                                         UInt16                                          recSize,
                    134:                                                                         UInt16                                         *insertIndex,
                    135:                                                                         UInt32                                         *insertNodeNum,
                    136:                                                                         UInt16                                         *recsRotated );
                    137:                                                                 
                    138: 
                    139: 
                    140: static OSStatus        InsertLevel             (BTreeControlBlockPtr            btreePtr,
                    141:                                                                         TreePathTable                           treePathTable,
                    142:                                                                         InsertKey                                      *primaryKey,
                    143:                                                                         InsertKey                                      *secondaryKey,
                    144:                                                                         BlockDescriptor                        *targetNode,
                    145:                                                                         UInt16                                          index,
                    146:                                                                         UInt16                                          level,
                    147:                                                                         UInt32                                         *insertNode );
                    148:                                                 
                    149: static OSErr           InsertNode              (BTreeControlBlockPtr            btreePtr,
                    150:                                                                         InsertKey                                      *key,
                    151:                                                                         BlockDescriptor                        *rightNode,
                    152:                                                                         UInt32                                          node,
                    153:                                                                         UInt16                                          index,
                    154:                                                                         UInt32                                         *newNode,       
                    155:                                                                         UInt16                                         *newIndex,
                    156:                                                                         BlockDescriptor                        *leftNode,
                    157:                                                                         Boolean                                        *updateParent,
                    158:                                                                         Boolean                                        *insertParent,
                    159:                                                                         Boolean                                        *rootSplit );
                    160:                                                                         
                    161: static UInt16          GetKeyLength    (const BTreeControlBlock *btreePtr,
                    162:                                                                         const BTreeKey *key,
                    163:                                                                         Boolean forLeafNode );
                    164: 
                    165: 
                    166: 
                    167: //////////////////////// BTree Multi-node Tree Operations ///////////////////////
                    168: 
                    169: 
                    170: /*-------------------------------------------------------------------------------
                    171: 
                    172: Routine:       SearchTree      -       Search BTree for key and set up Tree Path Table.
                    173: 
                    174: Function:      Searches BTree for specified key, setting up the Tree Path Table to
                    175:                        reflect the search path.
                    176: 
                    177: 
                    178: Input:         btreePtr                - pointer to control block of BTree to search
                    179:                        keyPtr                  - pointer to the key to search for
                    180:                        treePathTable   - pointer to the tree path table to construct
                    181:                        
                    182: Output:                nodeNum                 - number of the node containing the key position
                    183:                        iterator                - BTreeIterator specifying record or insert position
                    184:                        
                    185: Result:                noErr                   - key found, index is record index
                    186:                        fsBTRecordNotFoundErr   - key not found, index is insert index
                    187:                        fsBTEmptyErr            - key not found, return params are nil
                    188:                        otherwise                       - catastrophic failure (GetNode/ReleaseNode failed)
                    189: -------------------------------------------------------------------------------*/
                    190: 
                    191: OSStatus       SearchTree      (BTreeControlBlockPtr    btreePtr,
                    192:                                                 BTreeKeyPtr                     searchKey,
                    193:                                                 TreePathTable                   treePathTable,
                    194:                                                 UInt32                                 *nodeNum,
                    195:                                                 BlockDescriptor                *nodePtr,
                    196:                                                 UInt16                                 *returnIndex )
                    197: {
                    198:        OSStatus        err;
                    199:        SInt16          level;
                    200:        UInt32          curNodeNum;
                    201:        NodeRec         nodeRec;
                    202:        UInt16          index;
                    203:        Boolean         keyFound;
                    204:        KeyPtr          keyPtr;
                    205:        UInt8 *         dataPtr;
                    206:        UInt16          dataSize;
                    207:        
                    208:        
                    209:        if (btreePtr->treeDepth == 0)                                           // is the tree empty?
                    210:        {
                    211:                err = fsBTEmptyErr;
                    212:                goto ErrorExit;
                    213:        }
                    214:        
                    215:        curNodeNum              = btreePtr->rootNode;
                    216:        
                    217:        //�� for debugging...
                    218:        treePathTable [0].node          = 0;
                    219:        treePathTable [0].index         = 0;
                    220: 
                    221:        while (true)
                    222:        {
                    223:                PanicIf(curNodeNum == 0, "\pSearchTree: curNodeNum is zero!");
                    224: 
                    225:                err = GetNode (btreePtr, curNodeNum, &nodeRec);
                    226:                if (err != noErr)
                    227:                {
                    228:                        goto ErrorExit;
                    229:                }
                    230:                
                    231:                keyFound = SearchNode (btreePtr, nodeRec.buffer, searchKey, &index);
                    232: 
                    233:                level = ((BTNodeDescriptor*)nodeRec.buffer)->height;    //�� or --level;
                    234:                
                    235: 
                    236:                treePathTable [level].node              = curNodeNum;
                    237: 
                    238:                if ( ((BTNodeDescriptor*)nodeRec.buffer)->type == kLeafNode)
                    239:                {
                    240:                        treePathTable [level].index = index;
                    241:                        break;                  // were done...
                    242:                }
                    243:                
                    244:                if ( (keyFound != true) && (index != 0))
                    245:                        --index;
                    246: 
                    247:                treePathTable [level].index = index;
                    248:                
                    249:                GetRecordByIndex (btreePtr, nodeRec.buffer, index, &keyPtr, &dataPtr, &dataSize);
                    250:                curNodeNum = *(UInt32 *)dataPtr;
                    251:                err = ReleaseNode (btreePtr, &nodeRec);
                    252:                if (err != noErr)
                    253:                {
                    254:                        goto ErrorExit;
                    255:                }
                    256:        }
                    257:        
                    258:        *nodeNum                        = curNodeNum;
                    259:        *nodePtr                        = nodeRec;
                    260:        *returnIndex            = index;
                    261: 
                    262:        if (keyFound)
                    263:                return  noErr;                  // searchKey found, index identifies record in node
                    264:        else
                    265:                return  fsBTRecordNotFoundErr;  // searchKey not found, index identifies insert point
                    266: 
                    267: ErrorExit:
                    268:        
                    269:        *nodeNum                                        = 0;
                    270:        nodePtr->buffer                         = nil;
                    271:        nodePtr->blockHeader            = nil;
                    272:        *returnIndex                            = 0;
                    273: 
                    274:        return  err;
                    275: }
                    276: 
                    277: 
                    278: 
                    279: 
                    280: ////////////////////////////////// InsertTree ///////////////////////////////////
                    281: 
                    282: OSStatus       InsertTree ( BTreeControlBlockPtr                btreePtr,
                    283:                                                 TreePathTable                           treePathTable,
                    284:                                                 KeyPtr                                          keyPtr,
                    285:                                                 UInt8 *                                         recPtr,
                    286:                                                 UInt16                                          recSize,
                    287:                                                 BlockDescriptor                        *targetNode,
                    288:                                                 UInt16                                          index,
                    289:                                                 UInt16                                          level,
                    290:                                                 Boolean                                         replacingKey,
                    291:                                                 UInt32                                         *insertNode )
                    292: {
                    293:        InsertKey                       primaryKey;
                    294:        OSStatus                        err;
                    295: 
                    296:        primaryKey.keyPtr               = keyPtr;
                    297:        primaryKey.keyLength    = GetKeyLength(btreePtr, primaryKey.keyPtr, (level == 1));
                    298:        primaryKey.recPtr               = recPtr;
                    299:        primaryKey.recSize              = recSize;
                    300:        primaryKey.replacingKey = replacingKey;
                    301:        primaryKey.skipRotate   = false;
                    302: 
                    303:        err     = InsertLevel (btreePtr, treePathTable, &primaryKey, nil,
                    304:                                           targetNode, index, level, insertNode );
                    305:                                                
                    306:        return err;
                    307: 
                    308: } // End of InsertTree
                    309: 
                    310: 
                    311: ////////////////////////////////// InsertLevel //////////////////////////////////
                    312: 
                    313: OSStatus       InsertLevel (BTreeControlBlockPtr                btreePtr,
                    314:                                                 TreePathTable                           treePathTable,
                    315:                                                 InsertKey                                      *primaryKey,
                    316:                                                 InsertKey                                      *secondaryKey,
                    317:                                                 BlockDescriptor                        *targetNode,
                    318:                                                 UInt16                                          index,
                    319:                                                 UInt16                                          level,
                    320:                                                 UInt32                                         *insertNode )
                    321: {
                    322:        OSStatus                         err;
                    323:        BlockDescriptor          leftNode;
                    324:        UInt32                           targetNodeNum;
                    325:        UInt32                           newNodeNum;
                    326:        UInt16                           newIndex;
                    327:        Boolean                          insertParent;
                    328:        Boolean                          updateParent;
                    329:        Boolean                          newRoot;
                    330: 
                    331: #if defined(applec) && !defined(__SC__)
                    332:        PanicIf ((level == 1) && (((NodeDescPtr)targetNode->buffer)->type != kLeafNode), "\P InsertLevel: non-leaf at level 1! ");
                    333: #endif
                    334:        leftNode.buffer = nil;
                    335:        targetNodeNum = treePathTable [level].node;
                    336: 
                    337:        insertParent = false;
                    338:        updateParent = false;
                    339: 
                    340:        ////// process first insert //////
                    341:        
                    342:        err = InsertNode (btreePtr, primaryKey, targetNode, targetNodeNum, index,
                    343:                                          &newNodeNum, &newIndex, &leftNode, &updateParent, &insertParent, &newRoot );
                    344:        M_ExitOnError (err);
                    345: 
                    346:        if ( newRoot )
                    347:        {
                    348:                // Extend the treePathTable by adding an entry for the new
                    349:                // root node that references the current targetNode.
                    350:                // 
                    351:                // If inserting the secondaryKey changes the first key of
                    352:                // the target node, then we'll have to update the second
                    353:                // key in the new root node.
                    354: 
                    355:                treePathTable [level + 1].node  = btreePtr->rootNode;
                    356:                treePathTable [level + 1].index = 1;    // 1 since we always split/rotate left
                    357:        }
                    358:        
                    359:        if ( level == 1 )
                    360:                *insertNode = newNodeNum;               
                    361:        
                    362:        ////// process second insert (if any) //////
                    363: 
                    364:        if  ( secondaryKey != nil )
                    365:        {
                    366:                Boolean                         temp;
                    367: 
                    368:                err = InsertNode (btreePtr, secondaryKey, targetNode, newNodeNum, newIndex,
                    369:                                                  &newNodeNum, &newIndex, &leftNode, &updateParent, &insertParent, &temp);
                    370:                M_ExitOnError (err);
                    371:                
                    372:                if ( DEBUG_BUILD && updateParent && newRoot )
                    373:                        DebugStr("\p InsertLevel: New root from primary key, update from secondary key...");
                    374:        }
                    375: 
                    376:        //////////////////////// Update Parent(s) ///////////////////////////////
                    377: 
                    378:        if ( insertParent || updateParent )
                    379:        {
                    380:                BlockDescriptor         parentNode;
                    381:                UInt32                          parentNodeNum;
                    382:                KeyPtr                          keyPtr;
                    383:                UInt8 *                         recPtr;
                    384:                UInt16                          recSize;
                    385:                
                    386:                secondaryKey = nil;
                    387:                
                    388:                PanicIf ( (level == btreePtr->treeDepth), "\p InsertLevel: unfinished insert!?");
                    389: 
                    390:                ++level;
                    391: 
                    392:                // Get Parent Node data...
                    393:                index = treePathTable [level].index;
                    394:                parentNodeNum = treePathTable [level].node;
                    395: 
                    396:                PanicIf ( parentNodeNum == 0, "\p InsertLevel: parent node is zero!?");
                    397: 
                    398:                err = GetNode (btreePtr, parentNodeNum, &parentNode);   // released as target node in next level up
                    399:                M_ExitOnError (err);
                    400: #if defined(applec) && !defined(__SC__)
                    401:                if (DEBUG_BUILD && level > 1)
                    402:                        PanicIf ( ((NodeDescPtr)parentNode.buffer)->type != kIndexNode, "\P InsertLevel: parent node not an index node! ");
                    403: #endif
                    404:                ////////////////////////// Update Parent Index //////////////////////////////
                    405:        
                    406:                if ( updateParent )
                    407:                {
                    408:                        //���debug: check if ptr == targetNodeNum
                    409:                        GetRecordByIndex (btreePtr, parentNode.buffer, index, &keyPtr, &recPtr, &recSize);
                    410:                        PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "\p InsertLevel: parent ptr doesn't match target node!");
                    411:                        
                    412:                        // need to delete and re-insert this parent key/ptr
                    413:                        // we delete it here and it gets re-inserted in the
                    414:                        // InsertLevel call below.
                    415:                        DeleteRecord (btreePtr, parentNode.buffer, index);
                    416:        
                    417:                        primaryKey->keyPtr               = (KeyPtr) GetRecordAddress( btreePtr, targetNode->buffer, 0 );
                    418:                        primaryKey->keyLength    = GetKeyLength(btreePtr, primaryKey->keyPtr, false);
                    419:                        primaryKey->recPtr               = (UInt8 *) &targetNodeNum;
                    420:                        primaryKey->recSize              = sizeof(targetNodeNum);
                    421:                        primaryKey->replacingKey = kReplaceRecord;
                    422:                        primaryKey->skipRotate   = insertParent;                // don't rotate left if we have two inserts occuring
                    423:                }
                    424:        
                    425:                ////////////////////////// Add New Parent Index /////////////////////////////
                    426:        
                    427:                if ( insertParent )
                    428:                {
                    429:                        InsertKey       *insertKeyPtr;
                    430:                        InsertKey       insertKey;
                    431:                        
                    432:                        if ( updateParent )
                    433:                        {
                    434:                                insertKeyPtr = &insertKey;
                    435:                                secondaryKey = &insertKey;
                    436:                        }
                    437:                        else
                    438:                        {
                    439:                                insertKeyPtr = primaryKey;
                    440:                        }
                    441:                        
                    442:                        insertKeyPtr->keyPtr            = (KeyPtr) GetRecordAddress (btreePtr, leftNode.buffer, 0);
                    443:                        insertKeyPtr->keyLength         = GetKeyLength(btreePtr, insertKeyPtr->keyPtr, false);
                    444:                        insertKeyPtr->recPtr            = (UInt8 *) &((NodeDescPtr)targetNode->buffer)->bLink;
                    445:                        insertKeyPtr->recSize           = sizeof(UInt32);
                    446:                        insertKeyPtr->replacingKey      = kInsertRecord;
                    447:                        insertKeyPtr->skipRotate        = false;                // a rotate is OK during second insert
                    448:                }       
                    449:                
                    450:                err = InsertLevel (btreePtr, treePathTable, primaryKey, secondaryKey,
                    451:                                                   &parentNode, index, level, insertNode );
                    452:                M_ExitOnError (err);
                    453:        }
                    454: 
                    455:        err = UpdateNode (btreePtr, targetNode);        // all done with target
                    456:        M_ExitOnError (err);
                    457: 
                    458:        err = UpdateNode (btreePtr, &leftNode);         // all done with left sibling
                    459:        M_ExitOnError (err);
                    460:        
                    461:        return  noErr;
                    462: 
                    463: ErrorExit:
                    464: 
                    465:        (void) ReleaseNode (btreePtr, targetNode);
                    466:        (void) ReleaseNode (btreePtr, &leftNode);
                    467: 
                    468:        Panic ("\p InsertLevel: an error occured!");
                    469: 
                    470:        return  err;
                    471: 
                    472: } // End of InsertLevel
                    473: 
                    474: 
                    475: 
                    476: ////////////////////////////////// InsertNode ///////////////////////////////////
                    477: 
                    478: static OSErr   InsertNode      (BTreeControlBlockPtr    btreePtr,
                    479:                                                         InsertKey                              *key,
                    480: 
                    481:                                                         BlockDescriptor                *rightNode,
                    482:                                                         UInt32                                  node,
                    483:                                                         UInt16                                  index,
                    484: 
                    485:                                                         UInt32                                 *newNode,       
                    486:                                                         UInt16                                 *newIndex,
                    487: 
                    488:                                                         BlockDescriptor                *leftNode,
                    489:                                                         Boolean                                *updateParent,
                    490:                                                         Boolean                                *insertParent,
                    491:                                                         Boolean                                *rootSplit )
                    492: {
                    493:        BlockDescriptor         *targetNode;
                    494:        UInt32                           leftNodeNum;
                    495:        UInt16                           recsRotated;
                    496:        OSErr                            err;
                    497:        Boolean                          recordFit;
                    498: 
                    499:        *rootSplit = false;
                    500:        
                    501:        PanicIf ( rightNode->buffer == leftNode->buffer, "\p InsertNode: rightNode == leftNode, huh?");
                    502:        
                    503:        leftNodeNum = ((NodeDescPtr) rightNode->buffer)->bLink;
                    504: 
                    505: 
                    506:        /////////////////////// Try Simple Insert ///////////////////////////////
                    507: 
                    508:        if ( node == leftNodeNum )
                    509:                targetNode = leftNode;
                    510:        else
                    511:                targetNode = rightNode;
                    512: 
                    513:        recordFit = InsertKeyRecord (btreePtr, targetNode->buffer, index, key->keyPtr, key->keyLength, key->recPtr, key->recSize);
                    514: 
                    515:        if ( recordFit )
                    516:        {
                    517:                *newNode  = node;
                    518:                *newIndex = index;
                    519:        
                    520:                if ( (index == 0) && (((NodeDescPtr) targetNode->buffer)->height != btreePtr->treeDepth) )
                    521:                        *updateParent = true;   // the first record changed so we need to update the parent
                    522:        }
                    523: 
                    524: 
                    525:        //////////////////////// Try Rotate Left ////////////////////////////////
                    526:        
                    527:        if ( !recordFit && leftNodeNum > 0 )
                    528:        {
                    529:                PanicIf ( leftNode->buffer != nil, "\p InsertNode: leftNode already aquired!");
                    530: 
                    531:                if ( leftNode->buffer == nil )
                    532:                {
                    533:                        err = GetNode (btreePtr, leftNodeNum, leftNode);        // will be released by caller or a split below
                    534:                        M_ExitOnError (err);
                    535:                }
                    536: 
                    537:                PanicIf ( ((NodeDescPtr) leftNode->buffer)->fLink != node, "\p InsertNode, RotateLeft: invalid sibling link!" );
                    538: 
                    539:                if ( !key->skipRotate )         // are rotates allowed?
                    540:                {
                    541:                        err = RotateLeft (btreePtr, leftNode->buffer, rightNode->buffer, index, key->keyPtr, key->recPtr,
                    542:                                                          key->recSize, newIndex, newNode, &recordFit, &recsRotated );  
                    543:                        M_ExitOnError (err);
                    544: 
                    545:                        if ( recordFit )
                    546:                        {
                    547:                                if ( key->replacingKey || (recsRotated > 1) || (index > 0) )
                    548:                                        *updateParent = true;                   
                    549:                        }
                    550:                }
                    551:        }       
                    552: 
                    553: 
                    554:        //////////////////////// Try Split Left /////////////////////////////////
                    555: 
                    556:        if ( !recordFit )
                    557:        {
                    558:                // might not have left node...
                    559:                err = SplitLeft (btreePtr, leftNode, rightNode, node, index, key->keyPtr,
                    560:                                                 key->recPtr, key->recSize, newIndex, newNode, &recsRotated);
                    561:                M_ExitOnError (err);
                    562: 
                    563:                // if we split root node - add new root
                    564:                
                    565:                if ( ((NodeDescPtr) rightNode->buffer)->height == btreePtr->treeDepth )
                    566:                {
                    567:                        err = AddNewRootNode (btreePtr, leftNode->buffer, rightNode->buffer);   // Note: does not update TPT
                    568:                        M_ExitOnError (err);
                    569:                        *rootSplit = true;
                    570:                }
                    571:                else
                    572:                {
                    573:                        *insertParent = true;
                    574: 
                    575:                        if ( key->replacingKey || (recsRotated > 1) || (index > 0) )
                    576:                                *updateParent = true;
                    577:                }
                    578:        }
                    579:        
                    580:        return noErr;
                    581: 
                    582: ErrorExit:
                    583: 
                    584:        (void) ReleaseNode (btreePtr, leftNode);
                    585:        return err;
                    586:        
                    587: } // End of InsertNode
                    588: 
                    589: 
                    590: /*-------------------------------------------------------------------------------
                    591: Routine:       DeleteTree      -       One_line_description.
                    592: 
                    593: Function:      Brief_description_of_the_function_and_any_side_effects
                    594: 
                    595: ToDo:          
                    596: 
                    597: Input:         btreePtr                - description
                    598:                        treePathTable   - description
                    599:                        targetNode              - description
                    600:                        index                   - description
                    601:                                                
                    602: Result:                noErr           - success
                    603:                        != noErr        - failure
                    604: -------------------------------------------------------------------------------*/
                    605: 
                    606: OSStatus       DeleteTree                      (BTreeControlBlockPtr            btreePtr,
                    607:                                                                 TreePathTable                           treePathTable,
                    608:                                                                 BlockDescriptor                        *targetNode,
                    609:                                                                 UInt16                                          index,
                    610:                                                                 UInt16                                          level )
                    611: {
                    612:        OSStatus                        err;
                    613:        BlockDescriptor         parentNode;
                    614:        BTNodeDescriptor        *targetNodePtr;
                    615:        UInt32                          targetNodeNum;
                    616:        Boolean                         deleteRequired;
                    617:        Boolean                         updateRequired;
                    618: 
                    619: 
                    620:        deleteRequired = false;
                    621:        updateRequired = false;
                    622: 
                    623:        targetNodeNum = treePathTable[level].node;
                    624:        targetNodePtr = targetNode->buffer;
                    625:        PanicIf (targetNodePtr == nil, "\pDeleteTree: targetNode has nil buffer!");
                    626: 
                    627:        DeleteRecord (btreePtr, targetNodePtr, index);
                    628:                
                    629:        //�� coalesce remaining records?
                    630: 
                    631:        if ( targetNodePtr->numRecords == 0 )   // did we delete the last record?
                    632:        {
                    633:                BlockDescriptor         siblingNode;
                    634:                UInt32                          siblingNodeNum;
                    635: 
                    636:                deleteRequired = true;
                    637:                
                    638:                ////////////////// Get Siblings & Update Links //////////////////////////
                    639:                
                    640:                siblingNodeNum = targetNodePtr->bLink;                          // Left Sibling Node
                    641:                if ( siblingNodeNum != 0 )
                    642:                {
                    643:                        err = GetNode (btreePtr, siblingNodeNum, &siblingNode);
                    644:                        M_ExitOnError (err);
                    645:                        ((NodeDescPtr)siblingNode.buffer)->fLink = targetNodePtr->fLink;
                    646:                        err = UpdateNode (btreePtr, &siblingNode);
                    647:                        M_ExitOnError (err);
                    648:                }
                    649:                else if ( targetNodePtr->type == kLeafNode )            // update firstLeafNode
                    650:                {
                    651:                        btreePtr->firstLeafNode = targetNodePtr->fLink;
                    652:                }
                    653: 
                    654:                siblingNodeNum = targetNodePtr->fLink;                          // Right Sibling Node
                    655:                if ( siblingNodeNum != 0 )
                    656:                {
                    657:                        err = GetNode (btreePtr, siblingNodeNum, &siblingNode);
                    658:                        M_ExitOnError (err);
                    659:                        ((NodeDescPtr)siblingNode.buffer)->bLink = targetNodePtr->bLink;
                    660:                        err = UpdateNode (btreePtr, &siblingNode);
                    661:                        M_ExitOnError (err);
                    662:                }
                    663:                else if ( targetNodePtr->type == kLeafNode )            // update lastLeafNode
                    664:                {
                    665:                        btreePtr->lastLeafNode = targetNodePtr->bLink;
                    666:                }
                    667:                
                    668:                //////////////////////// Free Empty Node ////////////////////////////////
                    669: 
                    670:                ClearNode (btreePtr, targetNodePtr);
                    671:                
                    672:                err = UpdateNode (btreePtr, targetNode);
                    673:                M_ExitOnError (err);
                    674:                err = FreeNode (btreePtr, targetNodeNum);
                    675:                M_ExitOnError (err);
                    676:        }
                    677:        else if ( index == 0 )                  // did we delete the first record?
                    678:        {
                    679:                updateRequired = true;          // yes, so we need to update parent
                    680:        }
                    681: 
                    682: 
                    683:        if ( level == btreePtr->treeDepth )             // then targetNode->buffer is the root node
                    684:        {
                    685:                deleteRequired = false;
                    686:                updateRequired = false;
                    687:                
                    688:                if ( targetNode->buffer == nil )        // then root was freed and the btree is empty
                    689:                {
                    690:                        btreePtr->rootNode  = 0;
                    691:                        btreePtr->treeDepth = 0;
                    692:                }
                    693:                else if ( ((NodeDescPtr)targetNode->buffer)->numRecords == 1 )
                    694:                {
                    695:                        err = CollapseTree (btreePtr, targetNode);
                    696:                        M_ExitOnError (err);
                    697:                }
                    698:        }
                    699: 
                    700: 
                    701:        if ( updateRequired || deleteRequired )
                    702:        {
                    703:                ++level;        // next level
                    704: 
                    705:                //// Get Parent Node and index
                    706:                index = treePathTable [level].index;
                    707:                err = GetNode (btreePtr, treePathTable[level].node, &parentNode);
                    708:                M_ExitOnError (err);
                    709: 
                    710:                if ( updateRequired )
                    711:                {
                    712:                         KeyPtr         keyPtr;
                    713:                         UInt8 *        recPtr;
                    714:                         UInt16         recSize;
                    715:                         UInt32         insertNode;
                    716:                         
                    717:                        //���debug: check if ptr == targetNodeNum
                    718:                        GetRecordByIndex (btreePtr, parentNode.buffer, index, &keyPtr, &recPtr, &recSize);
                    719:                        PanicIf( (*(UInt32 *) recPtr) != targetNodeNum, "\p DeleteTree: parent ptr doesn't match targetNodeNum!!");
                    720:                        
                    721:                        // need to delete and re-insert this parent key/ptr
                    722:                        DeleteRecord (btreePtr, parentNode.buffer, index);
                    723:        
                    724:                        keyPtr = (KeyPtr) GetRecordAddress( btreePtr, targetNode->buffer, 0 );
                    725:                        recPtr = (UInt8 *) &targetNodeNum;
                    726:                        recSize = sizeof(targetNodeNum);
                    727:                        
                    728:                        err = InsertTree (btreePtr, treePathTable, keyPtr, recPtr, recSize,
                    729:                                                          &parentNode, index, level, kReplaceRecord, &insertNode);
                    730:                        M_ExitOnError (err);
                    731:                }
                    732:                else // deleteRequired
                    733:                {
                    734:                        err = DeleteTree (btreePtr, treePathTable, &parentNode, index, level);
                    735:                        M_ExitOnError (err);
                    736:                }
                    737:        }       
                    738: 
                    739: 
                    740:        err = UpdateNode (btreePtr, targetNode);
                    741:        M_ExitOnError (err);
                    742: 
                    743:        return  noErr;
                    744: 
                    745: ErrorExit:
                    746:        
                    747:        (void) ReleaseNode (btreePtr, targetNode);
                    748:        (void) ReleaseNode (btreePtr, &parentNode);
                    749: 
                    750:        return  err;
                    751: 
                    752: } // end DeleteTree
                    753: 
                    754: 
                    755: 
                    756: ///////////////////////////////// CollapseTree //////////////////////////////////
                    757: 
                    758: static OSStatus        CollapseTree    (BTreeControlBlockPtr           btreePtr,
                    759:                                                                 BlockDescriptor                        *blockPtr )
                    760: {
                    761:        OSStatus                err;
                    762:        UInt32                  originalRoot;
                    763:        UInt32                  nodeNum;
                    764:        
                    765:        originalRoot    = btreePtr->rootNode;
                    766:        
                    767:        while (true)
                    768:        {
                    769:                if ( ((NodeDescPtr)blockPtr->buffer)->numRecords > 1)
                    770:                        break;                                                  // this will make a fine root node
                    771:                
                    772:                if ( ((NodeDescPtr)blockPtr->buffer)->type == kLeafNode)
                    773:                        break;                                                  // we've hit bottom
                    774:                
                    775:                nodeNum                         = btreePtr->rootNode;
                    776:                btreePtr->rootNode      = GetChildNodeNum (btreePtr, blockPtr->buffer, 0);
                    777:                --btreePtr->treeDepth;
                    778: 
                    779:                //// Clear and Free Current Old Root Node ////
                    780:                ClearNode (btreePtr, blockPtr->buffer);
                    781:                err = UpdateNode (btreePtr, blockPtr);
                    782:                M_ExitOnError (err);
                    783:                err = FreeNode (btreePtr, nodeNum);
                    784:                M_ExitOnError (err);
                    785:                
                    786:                //// Get New Root Node
                    787:                err = GetNode (btreePtr, btreePtr->rootNode, blockPtr);
                    788:                M_ExitOnError (err);
                    789:        }
                    790:        
                    791:        if (btreePtr->rootNode != originalRoot)
                    792:                M_BTreeHeaderDirty (btreePtr);
                    793:                
                    794:        err = UpdateNode (btreePtr, blockPtr);  // always update!
                    795:        M_ExitOnError (err);
                    796:        
                    797:        return  noErr;
                    798:        
                    799: 
                    800: /////////////////////////////////// ErrorExit ///////////////////////////////////
                    801: 
                    802: ErrorExit:
                    803:        (void)  ReleaseNode (btreePtr, blockPtr);
                    804:        return  err;
                    805: }
                    806: 
                    807: 
                    808: 
                    809: ////////////////////////////////// RotateLeft ///////////////////////////////////
                    810: 
                    811: /*-------------------------------------------------------------------------------
                    812: 
                    813: Routine:       RotateLeft      -       One_line_description.
                    814: 
                    815: Function:      Brief_description_of_the_function_and_any_side_effects
                    816: 
                    817: Algorithm:     if rightIndex > insertIndex, subtract 1 for actual rightIndex
                    818: 
                    819: Input:         btreePtr                        - description
                    820:                        leftNode                        - description
                    821:                        rightNode                       - description
                    822:                        rightInsertIndex        - description
                    823:                        keyPtr                          - description
                    824:                        recPtr                          - description
                    825:                        recSize                         - description
                    826:                        
                    827: Output:                insertIndex
                    828:                        insertNodeNum           - description
                    829:                        recordFit                       - description
                    830:                        recsRotated
                    831:                        
                    832: Result:                noErr           - success
                    833:                        != noErr        - failure
                    834: -------------------------------------------------------------------------------*/
                    835: 
                    836: static OSStatus        RotateLeft              (BTreeControlBlockPtr            btreePtr,
                    837:                                                                 NodeDescPtr                             leftNode,
                    838:                                                                 NodeDescPtr                             rightNode,
                    839:                                                                 UInt16                                          rightInsertIndex,
                    840:                                                                 KeyPtr                                          keyPtr,
                    841:                                                                 UInt8 *                                         recPtr,
                    842:                                                                 UInt16                                          recSize,
                    843:                                                                 UInt16                                         *insertIndex,
                    844:                                                                 UInt32                                         *insertNodeNum,
                    845:                                                                 Boolean                                        *recordFit,
                    846:                                                                 UInt16                                         *recsRotated )
                    847: {
                    848:        OSStatus                        err;
                    849:        SInt32                          insertSize;
                    850:        SInt32                          nodeSize;
                    851:        SInt32                          leftSize, rightSize;
                    852:        SInt32                          moveSize = 0;
                    853:        UInt16                          keyLength;
                    854:        UInt16                          lengthFieldSize;
                    855:        UInt16                          index, moveIndex;
                    856:        Boolean                         didItFit;
                    857: 
                    858:        ///////////////////// Determine If Record Will Fit //////////////////////////
                    859:        
                    860:        keyLength = GetKeyLength(btreePtr, keyPtr, (rightNode->type == kLeafNode));
                    861: 
                    862:        // the key's length field is 8-bits in HFS and 16-bits in HFS+
                    863:        if ( btreePtr->attributes & kBTBigKeysMask )
                    864:                lengthFieldSize = sizeof(UInt16);
                    865:        else
                    866:                lengthFieldSize = sizeof(UInt8);
                    867: 
                    868:        insertSize = keyLength + lengthFieldSize + recSize + sizeof(UInt16);
                    869: 
                    870:        if ( M_IsOdd (insertSize) )
                    871:                ++insertSize;   // add pad byte;
                    872: 
                    873:        nodeSize                = btreePtr->nodeSize;
                    874: 
                    875:        // add size of insert record to right node
                    876:        rightSize               = nodeSize - GetNodeFreeSize (btreePtr, rightNode) + insertSize;
                    877:        leftSize                = nodeSize - GetNodeFreeSize (btreePtr, leftNode);
                    878: 
                    879:        moveIndex       = 0;
                    880: 
                    881:        while ( leftSize < rightSize )
                    882:        {
                    883:                if ( moveIndex < rightInsertIndex )
                    884:                {
                    885:                        moveSize = GetRecordSize (btreePtr, rightNode, moveIndex) + 2;
                    886:                }
                    887:                else if ( moveIndex == rightInsertIndex )
                    888:                {
                    889:                        moveSize = insertSize;
                    890:                }
                    891:                else // ( moveIndex > rightInsertIndex )
                    892:                {
                    893:                        moveSize = GetRecordSize (btreePtr, rightNode, moveIndex - 1) + 2;
                    894:                }
                    895:                
                    896:                leftSize        += moveSize;
                    897:                rightSize       -= moveSize;
                    898:                ++moveIndex;
                    899:        }       
                    900:        
                    901:        if ( leftSize > nodeSize )      // undo last move
                    902:        {
                    903:                leftSize        -= moveSize;
                    904:                rightSize       += moveSize;
                    905:                --moveIndex;
                    906:        }
                    907:        
                    908:        if ( rightSize > nodeSize )     // record won't fit - failure, but not error
                    909:        {
                    910:                *insertIndex    = 0;
                    911:                *insertNodeNum  = 0;
                    912:                *recordFit              = false;
                    913:                *recsRotated    = 0;
                    914:                
                    915:                return  noErr;
                    916:        }
                    917:        
                    918:        // we've found balance point, moveIndex == number of records moved into leftNode
                    919:        
                    920: 
                    921:        //////////////////////////// Rotate Records /////////////////////////////////
                    922: 
                    923:        *recsRotated    = moveIndex;
                    924:        *recordFit              = true;
                    925:        index                   = 0;
                    926: 
                    927:        while ( index < moveIndex )
                    928:        {
                    929:                if ( index == rightInsertIndex )        // insert new record in left node
                    930:                {
                    931:                        UInt16  leftInsertIndex;
                    932:                        
                    933:                        leftInsertIndex = leftNode->numRecords;
                    934: 
                    935:                        didItFit = InsertKeyRecord (btreePtr, leftNode, leftInsertIndex,
                    936:                                                                                keyPtr, keyLength, recPtr, recSize);
                    937:                        if ( !didItFit )
                    938:                        {
                    939:                                Panic ("\pRotateLeft: InsertKeyRecord (left) returned false!");
                    940:                                err = fsBTBadRotateErr;
                    941:                                goto ErrorExit;
                    942:                        }
                    943:                        
                    944:                        *insertIndex = leftInsertIndex;
                    945:                        *insertNodeNum = rightNode->bLink;
                    946:                }
                    947:                else
                    948:                {
                    949:                        didItFit = RotateRecordLeft (btreePtr, leftNode, rightNode);
                    950:                        if ( !didItFit )
                    951:                        {
                    952:                                Panic ("\pRotateLeft: RotateRecordLeft returned false!");
                    953:                                err = fsBTBadRotateErr;
                    954:                                goto ErrorExit;
                    955:                        }
                    956:                }
                    957:                
                    958:                ++index;
                    959:        }
                    960:        
                    961:        if ( moveIndex <= rightInsertIndex )    // then insert new record in right node
                    962:        {
                    963:                rightInsertIndex -= index;                      // adjust for records already rotated
                    964:                
                    965:                didItFit = InsertKeyRecord (btreePtr, rightNode, rightInsertIndex,
                    966:                                                                        keyPtr, keyLength, recPtr, recSize);
                    967:                if ( !didItFit )
                    968:                {
                    969:                        Panic ("\pRotateLeft: InsertKeyRecord (right) returned false!");
                    970:                        err = fsBTBadRotateErr;
                    971:                        goto ErrorExit;
                    972:                }
                    973:        
                    974:                *insertIndex = rightInsertIndex;
                    975:                *insertNodeNum = leftNode->fLink;
                    976:        }
                    977: 
                    978: 
                    979:        return noErr;
                    980: 
                    981: 
                    982:        ////////////////////////////// Error Exit ///////////////////////////////////
                    983: 
                    984: ErrorExit:
                    985: 
                    986:        *insertIndex    = 0;
                    987:        *insertNodeNum  = 0;
                    988:        *recordFit              = false;
                    989:        *recsRotated    = 0;
                    990:        
                    991:        return  err;
                    992: }
                    993: 
                    994: 
                    995: 
                    996: /////////////////////////////////// SplitLeft ///////////////////////////////////
                    997: 
                    998: static OSStatus        SplitLeft               (BTreeControlBlockPtr            btreePtr,
                    999:                                                                 BlockDescriptor                        *leftNode,
                   1000:                                                                 BlockDescriptor                        *rightNode,
                   1001:                                                                 UInt32                                          rightNodeNum,
                   1002:                                                                 UInt16                                          index,
                   1003:                                                                 KeyPtr                                          keyPtr,
                   1004:                                                                 UInt8 *                                         recPtr,
                   1005:                                                                 UInt16                                          recSize,
                   1006:                                                                 UInt16                                         *insertIndex,
                   1007:                                                                 UInt32                                         *insertNodeNum,
                   1008:                                                                 UInt16                                         *recsRotated )
                   1009: {
                   1010:        OSStatus                        err;
                   1011:        NodeDescPtr                     left, right;
                   1012:        UInt32                          newNodeNum;
                   1013:        Boolean                         recordFit;
                   1014:        
                   1015:        
                   1016:        ///////////////////////////// Compare Nodes /////////////////////////////////
                   1017: 
                   1018:        right = rightNode->buffer;
                   1019:        left  = leftNode->buffer;
                   1020:        
                   1021:        PanicIf ( right->bLink != 0 && left == 0, "\p SplitLeft: left sibling missing!?" );
                   1022:        
                   1023:        //�� type should be kLeafNode or kIndexNode
                   1024:        
                   1025:        if ( (right->height == 1) && (right->type != kLeafNode) )
                   1026:                return  fsBTInvalidNodeErr;
                   1027:        
                   1028:        if ( left != nil )
                   1029:        {
                   1030:                if ( left->fLink != rightNodeNum )
                   1031:                        return fsBTInvalidNodeErr;                                                                              //�� E_BadSibling ?
                   1032:        
                   1033:                if ( left->height != right->height )
                   1034:                        return  fsBTInvalidNodeErr;                                                                             //�� E_BadNodeHeight ?
                   1035:                
                   1036:                if ( left->type != right->type )
                   1037:                        return  fsBTInvalidNodeErr;                                                                             //�� E_BadNodeType ?
                   1038:        }
                   1039:        
                   1040: 
                   1041:        ///////////////////////////// Allocate Node /////////////////////////////////
                   1042: 
                   1043:        err = AllocateNode (btreePtr, &newNodeNum);
                   1044:        M_ExitOnError (err);
                   1045:        
                   1046: 
                   1047:        /////////////// Update Forward Link In Original Left Node ///////////////////
                   1048: 
                   1049:        if ( left != nil )
                   1050:        {
                   1051:                left->fLink     = newNodeNum;
                   1052:                err = UpdateNode (btreePtr, leftNode);
                   1053:                M_ExitOnError (err);
                   1054:        }
                   1055: 
                   1056: 
                   1057:        /////////////////////// Initialize New Left Node ////////////////////////////
                   1058: 
                   1059:        err = GetNewNode (btreePtr, newNodeNum, leftNode);
                   1060:        M_ExitOnError (err);
                   1061:        
                   1062:        left            = leftNode->buffer;
                   1063:        left->fLink     = rightNodeNum;
                   1064:        
                   1065: 
                   1066:        // Steal Info From Right Node
                   1067:        
                   1068:        left->bLink  = right->bLink;
                   1069:        left->type   = right->type;
                   1070:        left->height = right->height;
                   1071:        
                   1072:        right->bLink            = newNodeNum;                   // update Right bLink
                   1073: 
                   1074:        if ( (left->type == kLeafNode) && (left->bLink == 0) )
                   1075:        {
                   1076:                // if we're adding a new first leaf node - update BTreeInfoRec
                   1077:                
                   1078:                btreePtr->firstLeafNode = newNodeNum;
                   1079:                M_BTreeHeaderDirty (btreePtr);          //�� AllocateNode should have set the bit already...
                   1080:        }
                   1081: 
                   1082:        ////////////////////////////// Rotate Left //////////////////////////////////
                   1083: 
                   1084:        err = RotateLeft (btreePtr, left, right, index, keyPtr, recPtr, recSize,
                   1085:                                          insertIndex, insertNodeNum, &recordFit, recsRotated);
                   1086:        M_ExitOnError (err);
                   1087:        
                   1088:        return noErr;
                   1089:        
                   1090: ErrorExit:
                   1091:        
                   1092:        (void) ReleaseNode (btreePtr, leftNode);
                   1093:        (void) ReleaseNode (btreePtr, rightNode);
                   1094:        
                   1095:        //�� Free new node if allocated?
                   1096: 
                   1097:        *insertIndex    = 0;
                   1098:        *insertNodeNum  = 0;
                   1099:        *recsRotated    = 0;
                   1100:        
                   1101:        return  err;
                   1102: }
                   1103: 
                   1104: 
                   1105: 
                   1106: /////////////////////////////// RotateRecordLeft ////////////////////////////////
                   1107: 
                   1108: static Boolean RotateRecordLeft (BTreeControlBlockPtr          btreePtr,
                   1109:                                                                 NodeDescPtr                            leftNode,
                   1110:                                                                 NodeDescPtr                            rightNode )
                   1111: {
                   1112:        UInt16          size;
                   1113:        UInt8 *         recPtr;
                   1114:        Boolean         recordFit;
                   1115:        
                   1116:        size    = GetRecordSize (btreePtr, rightNode, 0);
                   1117:        recPtr  = GetRecordAddress (btreePtr, rightNode, 0);
                   1118:        
                   1119:        recordFit = InsertRecord (btreePtr, leftNode, leftNode->numRecords, recPtr, size);
                   1120:        
                   1121:        if ( !recordFit )
                   1122:                return false;
                   1123:        
                   1124:        DeleteRecord (btreePtr, rightNode, 0);
                   1125:        
                   1126:        return true;
                   1127: }
                   1128: 
                   1129: 
                   1130: //////////////////////////////// AddNewRootNode /////////////////////////////////
                   1131: 
                   1132: static OSStatus        AddNewRootNode  (BTreeControlBlockPtr    btreePtr,
                   1133:                                                                 NodeDescPtr                     leftNode,
                   1134:                                                                 NodeDescPtr                     rightNode )
                   1135: {
                   1136:        OSStatus                        err;
                   1137:        BlockDescriptor         rootNode;
                   1138:        UInt32                          rootNum;
                   1139:        KeyPtr                          keyPtr;
                   1140:        Boolean                         didItFit;
                   1141:        UInt16                          keyLength;      
                   1142:        
                   1143:        PanicIf (leftNode == nil, "\pAddNewRootNode: leftNode == nil");
                   1144:        PanicIf (rightNode == nil, "\pAddNewRootNode: rightNode == nil");
                   1145:        
                   1146:        
                   1147:        /////////////////////// Initialize New Root Node ////////////////////////////
                   1148:        
                   1149:        err = AllocateNode (btreePtr, &rootNum);
                   1150:        M_ExitOnError (err);
                   1151:        
                   1152:        err = GetNewNode (btreePtr, rootNum, &rootNode);
                   1153:        M_ExitOnError (err);
                   1154:                
                   1155:        ((NodeDescPtr)rootNode.buffer)->type    = kIndexNode;
                   1156:        ((NodeDescPtr)rootNode.buffer)->height  = ++btreePtr->treeDepth;
                   1157:        
                   1158: 
                   1159:        ///////////////////// Insert Left Node Index Record /////////////////////////   
                   1160: 
                   1161:        keyPtr = (KeyPtr) GetRecordAddress (btreePtr, leftNode, 0);
                   1162:        keyLength = GetKeyLength(btreePtr, keyPtr, false);
                   1163: 
                   1164:        didItFit = InsertKeyRecord ( btreePtr, rootNode.buffer, 0, keyPtr, keyLength,
                   1165:                                                                 (UInt8 *) &rightNode->bLink, 4 );
                   1166: 
                   1167:        PanicIf ( !didItFit, "\pAddNewRootNode:InsertKeyRecord failed for left index record");
                   1168: 
                   1169: 
                   1170:        //////////////////// Insert Right Node Index Record /////////////////////////
                   1171: 
                   1172:        keyPtr = (KeyPtr) GetRecordAddress (btreePtr, rightNode, 0);
                   1173:        keyLength = GetKeyLength(btreePtr, keyPtr, false);
                   1174: 
                   1175:        didItFit = InsertKeyRecord ( btreePtr, rootNode.buffer, 1, keyPtr, keyLength,
                   1176:                                                                 (UInt8 *) &leftNode->fLink, 4 );
                   1177: 
                   1178:        PanicIf ( !didItFit, "\pAddNewRootNode:InsertKeyRecord failed for right index record");
                   1179: 
                   1180:        
                   1181:        /////////////////////////// Release Root Node ///////////////////////////////
                   1182:        
                   1183:        err = UpdateNode (btreePtr, &rootNode);
                   1184:        M_ExitOnError (err);
                   1185:        
                   1186:        // update BTreeInfoRec
                   1187:        
                   1188:        btreePtr->rootNode       = rootNum;
                   1189:        btreePtr->flags         |= kBTHeaderDirty;
                   1190:        
                   1191:        return noErr;
                   1192: 
                   1193: 
                   1194:        ////////////////////////////// Error Exit ///////////////////////////////////
                   1195: 
                   1196: ErrorExit:
                   1197: 
                   1198:        return  err;
                   1199: }
                   1200: 
                   1201: 
                   1202: static UInt16  GetKeyLength ( const BTreeControlBlock *btreePtr, const BTreeKey *key, Boolean forLeafNode )
                   1203: {
                   1204:        UInt16 length;
                   1205: 
                   1206:        if ( forLeafNode || btreePtr->attributes & kBTVariableIndexKeysMask )
                   1207:                length = KeyLength (btreePtr, key);             // just use actual key length
                   1208:        else
                   1209:                length = btreePtr->maxKeyLength;                // fixed sized index key (i.e. HFS)             //�� shouldn't we clear the pad bytes?
                   1210: 
                   1211:        return length;
                   1212: }
                   1213: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.