Annotation of XNU/bsd/hfs/hfscommon/BTree/BTreeMiscOps.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:           BTreeMiscOps.c
                     24: 
                     25:        Contains:       Miscellaneous 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:                (DSH)   Deric Horn
                     44:                (msd)   Mark Day
                     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:           <CS2>          9/4/97        djb             Optimize TrySimpleReplace for the case where record size is not
                     51:                                                                        changing.
                     52:           <CS1>         4/23/97        djb             first checked in
                     53: 
                     54:          <HFS7>         3/31/97        djb             Move ClearMemory to Utilities.c.
                     55:          <HFS6>         3/17/97        DSH             Casting for DFA
                     56:          <HFS5>         2/27/97        msd             Remove temporary fix from last revision. BTree EOF's should be
                     57:                                                                        correct now, so check for strict equality.
                     58:          <HFS4>         2/26/97        msd             Fix a casting problem in ClearMemory. TEMPORARY FIX: Made
                     59:                                                                        VerifyHeader more lenient, allowing the EOF to be greater than
                     60:                                                                        the amount actually used by nodes; this should really be fixed
                     61:                                                                        in the formatting code (which needs to compute the real BTree
                     62:                                                                        sizes before writing the volume header).
                     63:          <HFS3>         2/19/97        djb             Added ClearMemory. Changed CalcKeyLength to KeyLength.
                     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:                 <9>    10/25/96        ser             Changing for new VFPI
                     70:                 <8>    10/18/96        ser             Converting over VFPI changes
                     71:                 <7>     9/17/96        dkh             More BTree statistics. Change IsItAHint to not always check to
                     72:                                                                        see if the hint node is allocated.
                     73:                 <6>     9/16/96        dkh             Revised BTree statistics.
                     74:                 <5>     6/20/96        dkh             Radar #1358740. Change from using Pools to debug MemAllocators.
                     75:                 <4>     1/22/96        dkh             Change Pools.i inclusion to PoolsPriv.i
                     76:                 <3>     1/10/96        msd             Change 64-bit math to use real function names from Math64.i.
                     77:                 <2>     12/7/95        dkh             D10E2 build. Changed usage of Ref data type to LogicalAddress.
                     78:                 <1>    10/18/95        rst             Moved from Scarecrow project.
                     79: 
                     80:                <19>     4/26/95        prp             In UpdateHeader, clear the dirty flag after the BTree is updated.
                     81:                <18>     1/12/95        wjk             Adopt Model FileSystem changes in D5.
                     82:                <17>    11/16/94        prp             Add IsItAHint routine and use it whenever hint's node number was
                     83:                                                                        used for testing.
                     84:                <16>     10/5/94        bk              add pools.h include file
                     85:                <15>     9/30/94        prp             Get in sync with D2 interface changes.
                     86:                <14>     7/22/94        wjk             Convert to the new set of header files.
                     87:                <13>     12/2/93        wjk             Move from Makefiles to BuildFiles. Fit into the ModernOS and
                     88:                                                                        NRCmds environments.
                     89:                <12>    11/30/93        wjk             Move from Makefiles to BuildFiles. Fit into the ModernOS and
                     90:                                                                        NRCmds environments.
                     91:                <11>    11/23/93        wjk             Changes required to compile on the RS6000.
                     92:                <10>     8/31/93        prp             Use U64SetU instead of S64Set.
                     93:                 <9>      6/2/93        gs              Update for changes to FSErrors.h and add some comments.
                     94:                 <8>     5/21/93        gs              Modify UpdateHeader to write out attributes. Remove
                     95:                                                                        Get/UpdateNode from TrySimpleReplace.
                     96:                 <7>     5/10/93        gs              Add TrySimpleReplace routine.
                     97:                 <6>     3/23/93        gs              Change MoveData to take void * instead of Ptr. Add UpdateHeader
                     98:                                                                        and ClearBytes routines.
                     99:                 <5>      2/8/93        gs              Add FindIteratorPosition.
                    100:                 <4>    12/10/92        gs              Implement CheckKeyDescriptor and the KeyDescriptor interpreter.
                    101:                 <3>     12/8/92        gs              Add GetKeyDescriptor, VerifyHeader, and Alloc/Dealloc memory
                    102:                                                                        routines.
                    103:                 <2>     12/2/92        gs              Add CompareKeys routine.
                    104:                 <1>    11/15/92        gs              first checked in
                    105: 
                    106: */
                    107: 
                    108: #include "../headers/BTreesPrivate.h"
                    109: 
                    110: 
                    111: ////////////////////////////// Routine Definitions //////////////////////////////
                    112: 
                    113: /*-------------------------------------------------------------------------------
                    114: Routine:       CalcKeyRecordSize       -       Return size of combined key/record structure.
                    115: 
                    116: Function:      Rounds keySize and recSize so they will end on word boundaries.
                    117:                        Does NOT add size of offset.
                    118: 
                    119: Input:         keySize         - length of key (including length field)
                    120:                        recSize         - length of record data
                    121: 
                    122: Output:                none
                    123:                        
                    124: Result:                UInt16          - size of combined key/record that will be inserted in btree
                    125: -------------------------------------------------------------------------------*/
                    126: 
                    127: UInt16         CalcKeyRecordSize               (UInt16                                  keySize,
                    128:                                                                         UInt16                                  recSize )
                    129: {
                    130:        if ( M_IsOdd (keySize) )        keySize += 1;   // pad byte
                    131:        
                    132:        if (M_IsOdd (recSize) )         recSize += 1;   // pad byte
                    133:        
                    134:        return  (keySize + recSize);
                    135: }
                    136: 
                    137: 
                    138: 
                    139: /*-------------------------------------------------------------------------------
                    140: Routine:       VerifyHeader    -       Validate fields of the BTree header record.
                    141: 
                    142: Function:      Examines the fields of the BTree header record to determine if the
                    143:                        fork appears to contain a valid BTree.
                    144:                        
                    145: Input:         forkPtr         - pointer to fork control block
                    146:                        header          - pointer to BTree header
                    147:                        
                    148:                        
                    149: Result:                noErr           - success
                    150:                        != noErr        - failure
                    151: -------------------------------------------------------------------------------*/
                    152: 
                    153: OSStatus       VerifyHeader    (FCB                            *filePtr,
                    154:                                                         BTHeaderRec                     *header )
                    155: {
                    156:        UInt32          forkSize;
                    157:        UInt32          totalNodes;
                    158:        
                    159: 
                    160:        switch (header->nodeSize)                                                       // node size == 512*2^n
                    161:        {
                    162:                case   512:
                    163:                case  1024:
                    164:                case  2048:
                    165:                case  4096:
                    166:                case  8192:
                    167:                case 16384:
                    168:                case 32768:             break;
                    169:                default:                return  fsBTInvalidHeaderErr;                   //�� E_BadNodeType
                    170:        }
                    171:        
                    172:        totalNodes = header->totalNodes;
                    173: 
                    174:        forkSize = totalNodes * header->nodeSize;
                    175:        
                    176:        if ( forkSize != filePtr->fcbEOF )
                    177:                return fsBTInvalidHeaderErr;
                    178:        
                    179:        if ( header->freeNodes >= totalNodes )
                    180:                return fsBTInvalidHeaderErr;
                    181:        
                    182:        if ( header->rootNode >= totalNodes )
                    183:                return fsBTInvalidHeaderErr;
                    184:        
                    185:        if ( header->firstLeafNode >= totalNodes )
                    186:                return fsBTInvalidHeaderErr;
                    187:        
                    188:        if ( header->lastLeafNode >= totalNodes )
                    189:                return fsBTInvalidHeaderErr;
                    190:        
                    191:        if ( header->treeDepth > kMaxTreeDepth )
                    192:                return fsBTInvalidHeaderErr;
                    193: 
                    194: 
                    195:        /////////////////////////// Check BTree Type ////////////////////////////////
                    196:        
                    197:        switch (header->btreeType)
                    198:        {
                    199:                case    0:                                      // HFS Type - no Key Descriptor
                    200:                case    kUserBTreeType:         // with Key Descriptors etc.
                    201:                case    kReservedBTreeType:     // Desktop Mgr BTree ?
                    202:                                                                        break;
                    203: 
                    204:                default:                                        return fsBTUnknownVersionErr;           
                    205:        }
                    206:        
                    207:        return noErr;
                    208: }
                    209: 
                    210: 
                    211: 
                    212: /*-------------------------------------------------------------------------------
                    213: Routine:       UpdateHeader    -       Write BTreeInfoRec fields to Header node.
                    214: 
                    215: Function:      Checks the kBTHeaderDirty flag in the BTreeInfoRec and updates the
                    216:                        header node if necessary.
                    217:                        
                    218: Input:         btreePtr                - pointer to BTreeInfoRec
                    219:                        
                    220:                        
                    221: Result:                noErr           - success
                    222:                        != noErr        - failure
                    223: -------------------------------------------------------------------------------*/
                    224: 
                    225: OSStatus       UpdateHeader    (BTreeControlBlockPtr           btreePtr)
                    226: {
                    227:        OSStatus                                err;
                    228:        BlockDescriptor                 node;
                    229:        BTHeaderRec     *header;        
                    230: 
                    231:        
                    232:        if ((btreePtr->flags & kBTHeaderDirty) == 0)                    // btree info already flushed
                    233:        return  noErr;
                    234:        
                    235:        
                    236:        err = GetNode (btreePtr, kHeaderNodeNum, &node );
                    237:        if (err != noErr)
                    238:                return  err;
                    239:        
                    240:        header = (BTHeaderRec*) ((void *)node.buffer + sizeof(BTNodeDescriptor));
                    241:        
                    242:        header->treeDepth               = btreePtr->treeDepth;
                    243:        header->rootNode                = btreePtr->rootNode;
                    244:        header->leafRecords             = btreePtr->leafRecords;
                    245:        header->firstLeafNode   = btreePtr->firstLeafNode;
                    246:        header->lastLeafNode    = btreePtr->lastLeafNode;
                    247:        header->nodeSize                = btreePtr->nodeSize;                   //�� this shouldn't change
                    248:        header->maxKeyLength    = btreePtr->maxKeyLength;               //�� neither should this
                    249:        header->totalNodes              = btreePtr->totalNodes;
                    250:        header->freeNodes               = btreePtr->freeNodes;
                    251:        header->btreeType               = btreePtr->btreeType;
                    252: 
                    253:        // ignore       header->clumpSize;                                                      //�� rename this field?
                    254: 
                    255:        err = UpdateNode (btreePtr, &node, 0, kLockTransaction);
                    256: 
                    257:        btreePtr->flags &= (~kBTHeaderDirty);
                    258: 
                    259:        return  err;
                    260: }
                    261: 
                    262: 
                    263: 
                    264: /*-------------------------------------------------------------------------------
                    265: Routine:       FindIteratorPosition    -       One_line_description.
                    266: 
                    267: Function:      Brief_description_of_the_function_and_any_side_effects
                    268: 
                    269: Algorithm:     see FSC.BT.BTIterateRecord.PICT
                    270: 
                    271: Note:          //�� document side-effects of bad node hints
                    272: 
                    273: Input:         btreePtr                - description
                    274:                        iterator                - description
                    275:                        
                    276: 
                    277: Output:                iterator                - description
                    278:                        left                    - description
                    279:                        middle                  - description
                    280:                        right                   - description
                    281:                        nodeNum                 - description
                    282:                        returnIndex             - description
                    283:                        foundRecord             - description
                    284:                        
                    285:                        
                    286: Result:                noErr           - success
                    287:                        != noErr        - failure
                    288: -------------------------------------------------------------------------------*/
                    289: 
                    290: OSStatus       FindIteratorPosition    (BTreeControlBlockPtr    btreePtr,
                    291:                                                                         BTreeIteratorPtr                iterator,
                    292:                                                                         BlockDescriptor                *left,
                    293:                                                                         BlockDescriptor                *middle,
                    294:                                                                         BlockDescriptor                *right,
                    295:                                                                         UInt32                                 *returnNodeNum,
                    296:                                                                         UInt16                                 *returnIndex,
                    297:                                                                         Boolean                                *foundRecord )
                    298: {
                    299:        OSStatus                err;
                    300:        Boolean                 foundIt;
                    301:        UInt32                  nodeNum;
                    302:        UInt16                  leftIndex,      index,  rightIndex;
                    303:        Boolean                 validHint;
                    304: 
                    305:        // assume btreePtr valid
                    306:        // assume left, middle, right point to BlockDescriptors
                    307:        // assume nodeNum points to UInt32
                    308:        // assume index points to UInt16
                    309:        // assume foundRecord points to Boolean
                    310:        
                    311:        left->buffer            = nil;
                    312:        middle->buffer          = nil;
                    313:        right->buffer           = nil;
                    314:        
                    315:        foundIt                         = false;
                    316:        
                    317:        if (iterator == nil)                                            // do we have an iterator?
                    318:        {
                    319:                err = fsBTInvalidIteratorErr;
                    320:                goto ErrorExit;
                    321:        }
                    322: 
                    323:        err = IsItAHint (btreePtr, iterator, &validHint);
                    324:        M_ExitOnError (err);
                    325: 
                    326:        nodeNum = iterator->hint.nodeNum;
                    327:        if (! validHint)                                                        // does the hint appear to be valid?
                    328:        {
                    329:                goto SearchTheTree;
                    330:        }
                    331:        
                    332:        err = GetNode (btreePtr, nodeNum, middle);
                    333:        if( err == fsBTInvalidNodeErr ) // returned if nodeNum is out of range
                    334:                goto SearchTheTree;
                    335:                
                    336:        M_ExitOnError (err);
                    337:        
                    338:        if ( ((NodeDescPtr) middle->buffer)->kind != kBTLeafNode ||
                    339:                 ((NodeDescPtr) middle->buffer)->numRecords <= 0 )
                    340:        {       
                    341:                goto SearchTheTree;
                    342:        }
                    343:                
                    344:        ++btreePtr->numValidHints;
                    345:        
                    346:        foundIt = SearchNode (btreePtr, middle->buffer, &iterator->key, &index);
                    347:        if (foundIt == true)
                    348:        {
                    349:                goto SuccessfulExit;
                    350:        }
                    351:        
                    352:        if (index == 0)
                    353:        {
                    354:                if (((NodeDescPtr) middle->buffer)->bLink == 0)         // before 1st btree record
                    355:                {
                    356:                        goto SuccessfulExit;
                    357:                }
                    358:                
                    359:                nodeNum = ((NodeDescPtr) middle->buffer)->bLink;
                    360:                
                    361:                err = GetLeftSiblingNode (btreePtr, middle->buffer, left);
                    362:                M_ExitOnError (err);
                    363:                
                    364:                if ( ((NodeDescPtr) left->buffer)->kind != kBTLeafNode ||
                    365:                         ((NodeDescPtr) left->buffer)->numRecords <= 0 )
                    366:                {       
                    367:                        goto SearchTheTree;
                    368:                }
                    369:                
                    370:                foundIt = SearchNode (btreePtr, left->buffer, &iterator->key, &leftIndex);
                    371:                if (foundIt == true)
                    372:                {
                    373:                        *right                  = *middle;
                    374:                        *middle                 = *left;
                    375:                        left->buffer    = nil;
                    376:                        index                   = leftIndex;
                    377:                        
                    378:                        goto SuccessfulExit;
                    379:                }
                    380:                
                    381:                if (leftIndex == 0)                                                                     // we're lost!
                    382:                {
                    383:                        goto SearchTheTree;
                    384:                }
                    385:                else if (leftIndex >= ((NodeDescPtr) left->buffer)->numRecords)
                    386:                {
                    387:                        nodeNum = ((NodeDescPtr) left->buffer)->fLink;
                    388:                        
                    389:                        PanicIf (index != 0, "\pFindIteratorPosition: index != 0");     //�� just checking...
                    390:                        goto SuccessfulExit;
                    391:                }
                    392:                else
                    393:                {
                    394:                        *right                  = *middle;
                    395:                        *middle                 = *left;
                    396:                        left->buffer    = nil;
                    397:                        index                   = leftIndex;
                    398:                        
                    399:                        goto SuccessfulExit;
                    400:                }
                    401:        }
                    402:        else if (index >= ((NodeDescPtr) middle->buffer)->numRecords)
                    403:        {
                    404:                if (((NodeDescPtr) middle->buffer)->fLink == 0) // beyond last record
                    405:                {
                    406:                        goto SuccessfulExit;
                    407:                }
                    408:                
                    409:                nodeNum = ((NodeDescPtr) middle->buffer)->fLink;
                    410:                
                    411:                err = GetRightSiblingNode (btreePtr, middle->buffer, right);
                    412:                M_ExitOnError (err);
                    413:                
                    414:                if ( ((NodeDescPtr) right->buffer)->kind != kBTLeafNode ||
                    415:                         ((NodeDescPtr) right->buffer)->numRecords <= 0 )
                    416:                {       
                    417:                        goto SearchTheTree;
                    418:                }
                    419: 
                    420:                foundIt = SearchNode (btreePtr, right->buffer, &iterator->key, &rightIndex);
                    421:                if (rightIndex >= ((NodeDescPtr) right->buffer)->numRecords)            // we're lost
                    422:                {
                    423:                        goto SearchTheTree;
                    424:                }
                    425:                else    // we found it, or rightIndex==0, or rightIndex<numRecs
                    426:                {
                    427:                        *left                   = *middle;
                    428:                        *middle                 = *right;
                    429:                        right->buffer   = nil;
                    430:                        index                   = rightIndex;
                    431:                        
                    432:                        goto SuccessfulExit;
                    433:                }
                    434:        }
                    435: 
                    436:        
                    437:        //////////////////////////// Search The Tree ////////////////////////////////   
                    438: 
                    439: SearchTheTree:
                    440:        {
                    441:                TreePathTable   treePathTable;          // so we only use stack space if we need to
                    442: 
                    443:                err = ReleaseNode (btreePtr, left);                     M_ExitOnError (err);
                    444:                err = ReleaseNode (btreePtr, middle);           M_ExitOnError (err);
                    445:                err = ReleaseNode (btreePtr, right);            M_ExitOnError (err);
                    446:        
                    447:                err = SearchTree ( btreePtr, &iterator->key, treePathTable, &nodeNum, middle, &index);
                    448:                switch (err)                            //�� separate find condition from exceptions
                    449:                {
                    450:                        case noErr:                     foundIt = true;                         break;
                    451:                        case fsBTRecordNotFoundErr:                                             break;
                    452:                        default:                                goto ErrorExit;
                    453:                }
                    454:        }
                    455: 
                    456:        /////////////////////////////// Success! ////////////////////////////////////
                    457: 
                    458: SuccessfulExit:
                    459:        
                    460:        *returnNodeNum  = nodeNum;
                    461:        *returnIndex    = index;
                    462:        *foundRecord    = foundIt;
                    463:        
                    464:        return  noErr;
                    465:        
                    466:        
                    467:        ////////////////////////////// Error Exit ///////////////////////////////////
                    468: 
                    469: ErrorExit:
                    470: 
                    471:        (void)  ReleaseNode (btreePtr, left);
                    472:        (void)  ReleaseNode (btreePtr, middle);
                    473:        (void)  ReleaseNode (btreePtr, right);
                    474: 
                    475:        *returnNodeNum  = 0;
                    476:        *returnIndex    = 0;
                    477:        *foundRecord    = false;
                    478: 
                    479:        return  err;
                    480: }
                    481: 
                    482: 
                    483: 
                    484: /////////////////////////////// CheckInsertParams ///////////////////////////////
                    485: 
                    486: OSStatus       CheckInsertParams               (FCB                                            *filePtr,
                    487:                                                                         BTreeIterator                          *iterator,
                    488:                                                                         FSBufferDescriptor                     *record,
                    489:                                                                         UInt16                                          recordLen )
                    490: {
                    491:        BTreeControlBlockPtr    btreePtr;
                    492:        
                    493:        if (filePtr == nil)                                                                     return  paramErr;
                    494: 
                    495:        btreePtr = (BTreeControlBlockPtr) filePtr->fcbBTCBPtr;
                    496:        if (btreePtr == nil)                                                            return  fsBTInvalidFileErr;
                    497:        if (iterator == nil)                                                            return  paramErr;
                    498:        if (record       == nil)                                                                return  paramErr;
                    499:        
                    500:        //      check total key/record size limit
                    501:        if ( CalcKeyRecordSize (CalcKeySize(btreePtr, &iterator->key), recordLen) > (btreePtr->nodeSize >> 1))
                    502:                return  fsBTRecordTooLargeErr;
                    503:        
                    504:        return  noErr;
                    505: }
                    506: 
                    507: 
                    508: 
                    509: /*-------------------------------------------------------------------------------
                    510: Routine:       TrySimpleReplace        -       Attempts a simple insert, set, or replace.
                    511: 
                    512: Function:      If a hint exitst for the iterator, attempt to find the key in the hint
                    513:                        node. If the key is found, an insert operation fails. If the is not
                    514:                        found, a replace operation fails. If the key was not found, and the
                    515:                        insert position is greater than 0 and less than numRecords, the record
                    516:                        is inserted, provided there is enough freeSpace.  If the key was found,
                    517:                        and there is more freeSpace than the difference between the new record
                    518:                        and the old record, the old record is deleted and the new record is
                    519:                        inserted.
                    520: 
                    521: Assumptions:   iterator key has already been checked by CheckKey
                    522: 
                    523: 
                    524: Input:         btreePtr                - description
                    525:                        iterator                - description
                    526:                        record                  - description
                    527:                        recordLen               - description
                    528:                        operation               - description
                    529:                        
                    530: 
                    531: Output:                recordInserted          - description
                    532:                        
                    533:                                                
                    534: Result:                noErr                   - success
                    535:                        E_RecordExits           - insert operation failure
                    536:                        != noErr                - GetNode, ReleaseNode, UpdateNode returned an error
                    537: -------------------------------------------------------------------------------*/
                    538: 
                    539: OSStatus       TrySimpleReplace                (BTreeControlBlockPtr    btreePtr,
                    540:                                                                         NodeDescPtr                     nodePtr,
                    541:                                                                         BTreeIterator                  *iterator,
                    542:                                                                         FSBufferDescriptor             *record,
                    543:                                                                         UInt16                                  recordLen,
                    544:                                                                         Boolean                                *recordInserted )
                    545: {
                    546:        UInt32                          oldSpace;
                    547:        UInt32                          spaceNeeded;
                    548:        UInt16                          index;
                    549:        UInt16                          keySize;
                    550:        Boolean                         foundIt;
                    551:        Boolean                         didItFit;
                    552:        
                    553:        
                    554:        *recordInserted = false;                                                                // we'll assume this won't work...
                    555:        
                    556:        if ( nodePtr->kind != kBTLeafNode )
                    557:                return  noErr;  // we're in the weeds!
                    558: 
                    559:        foundIt = SearchNode (btreePtr, nodePtr, &iterator->key, &index);       
                    560: 
                    561:        if ( foundIt == false )
                    562:                return  noErr;  // we might be lost...
                    563:                
                    564:        keySize = CalcKeySize(btreePtr, &iterator->key);        // includes length field
                    565:        
                    566:        spaceNeeded     = CalcKeyRecordSize (keySize, recordLen);
                    567:        
                    568:        oldSpace = GetRecordSize (btreePtr, nodePtr, index);
                    569:        
                    570:        if ( spaceNeeded == oldSpace )
                    571:        {
                    572:                UInt8 *         dst;
                    573: 
                    574:                dst = GetRecordAddress (btreePtr, nodePtr, index);
                    575: 
                    576:                if ( M_IsOdd (keySize) )
                    577:                        ++keySize;                      // add pad byte
                    578:                
                    579:                dst += keySize;         // skip over key to point at record
                    580: 
                    581:                BlockMoveData(record->bufferAddress, dst, recordLen);   // blast away...
                    582: 
                    583:                *recordInserted = true;
                    584:        }
                    585:        else if ( (GetNodeFreeSize(btreePtr, nodePtr) + oldSpace) >= spaceNeeded)
                    586:        {
                    587:                DeleteRecord (btreePtr, nodePtr, index);
                    588:        
                    589:                didItFit = InsertKeyRecord (btreePtr, nodePtr, index,
                    590:                                                                                &iterator->key, KeyLength(btreePtr, &iterator->key),
                    591:                                                                                record->bufferAddress, recordLen);
                    592:                PanicIf (didItFit == false, "\pTrySimpleInsert: InsertKeyRecord returned false!");
                    593: 
                    594:                *recordInserted = true;
                    595:        }
                    596:        // else not enough space...
                    597: 
                    598:        return  noErr;
                    599: }
                    600: 
                    601: 
                    602: /*-------------------------------------------------------------------------------
                    603: Routine:       IsItAHint       -       checks the hint within a BTreeInterator.
                    604: 
                    605: Function:      checks the hint within a BTreeInterator.  If it is non-zero, it may 
                    606:                        possibly be valid. 
                    607: 
                    608: Input:         btreePtr        - pointer to control block for BTree file
                    609:                        iterator        - pointer to BTreeIterator
                    610:                        
                    611: Output:                answer          - true if the hint looks reasonable
                    612:                                                - false if the hint is 0
                    613:                        
                    614: Result:                noErr                   - success
                    615: -------------------------------------------------------------------------------*/
                    616: 
                    617: 
                    618: OSStatus       IsItAHint       (BTreeControlBlockPtr btreePtr, BTreeIterator *iterator, Boolean *answer)
                    619: {
                    620:        ++btreePtr->numHintChecks;
                    621:        
                    622: #if DEBUG_BUILD
                    623:        if (iterator->hint.nodeNum >= btreePtr->totalNodes)
                    624:        {
                    625:                *answer = false;
                    626:        } else 
                    627: 
                    628: #endif
                    629:        if (iterator->hint.nodeNum == 0)
                    630:        {
                    631:                *answer = false;
                    632:        }
                    633:        else
                    634:        {
                    635:                *answer = true;
                    636:                ++btreePtr->numPossibleHints;
                    637:        }
                    638:        
                    639:        return noErr;
                    640: }

unix.superglobalmegacorp.com

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