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

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

unix.superglobalmegacorp.com

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