Annotation of kernel/bsd/hfs/hfscommon/BTree/BTreeTreeOps.c, revision 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.