Annotation of kernel/bsd/hfs/hfscommon/BTree/BTreeMiscOps.c, revision 1.1

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

unix.superglobalmegacorp.com

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