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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:        File:           BTreeNodeOps.c
                     27: 
                     28:        Contains:       Single-node 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:                (msd)   Mark Day
                     47:                (djb)   Don Brady
                     48: 
                     49:        Change History (most recent first):
                     50: 
                     51:           <Rhap1>       3/26/97        djb             Added PrintNode for debugging.
                     52:           <CS5>          9/4/97        djb             Removed GetRightSiblingNode and GetLeftSiblingNode - they are
                     53:                                                                        now macros. SearchNode is now in BTreeSearchNode.a.
                     54:           <CS4>         8/22/97        djb             Turn off debugging code in CheckKey.
                     55:           <CS3>         7/24/97        djb             Add summary traces for Get/Rel Node. Made GetRecordOffset into a
                     56:                                                                        macro. Only call CheckNode if the node came from disk.
                     57:           <CS2>         7/21/97        msd             Make GetRecordByIndex check its record index input; it now
                     58:                                                                        returns an OSStatus.
                     59:           <CS1>         4/23/97        djb             first checked in
                     60: 
                     61:          <HFS3>         2/19/97        djb             Changes to support big node cache.
                     62:          <HFS2>          1/3/97        djb             Added support for large keys.
                     63:          <HFS1>        12/19/96        djb             first checked in
                     64: 
                     65: 
                     66:        History applicable to original Scarecrow Design:
                     67: 
                     68:                 <6>    10/25/96        ser             Changing for new VFPI
                     69:                 <5>     9/17/96        dkh             Add bounds checking to GetNode. Update GetNode to not assert
                     70:                                                                        that CheckNode failed if the node is all zeroes. This can happen
                     71:                                                                        if the hint case if the fetched node has been deallocated
                     72:                 <4>      3/7/96        dkh             Change GetNewNode() to not use kGetEmptyBlock. Instead use
                     73:                                                                        kGetBlock to fetch a block from the disk itself.  ��� Why?
                     74:                 <3>     1/22/96        dkh             Add #include Memory.h
                     75:                 <2>     1/10/96        msd             Change 64-bit math to use real function names from Math64.i.
                     76:                 <1>    10/18/95        rst             Moved from Scarecrow project.
                     77: 
                     78:                <17>     7/18/95        mbb             Change MoveData & ClearBytes to BlockMoveData & BlockZero.
                     79:                <16>     1/31/95        prp             GetBlockProc interface uses a 64 bit node number.
                     80:                <15>     1/12/95        wjk             Adopt Model FileSystem changes in D5.
                     81:                <14>     9/30/94        prp             Get in sync with D2 interface changes.
                     82:                <13>     7/25/94        wjk             Eliminate usage of BytePtr in favor of UInt8 *.
                     83:                <12>     7/22/94        wjk             Convert to the new set of header files.
                     84:                <11>     12/2/93        wjk             Move from Makefiles to BuildFiles. Fit into the ModernOS and
                     85:                                                                        NRCmds environments.
                     86:                <10>    11/30/93        wjk             Change some Ptr's to BytePtr's in function definitions so they
                     87:                                                                        agree with their prototypes.
                     88:                 <9>     8/31/93        prp             Use U64SetU instead of S64Set.
                     89:                 <8>     5/21/93        gs              Maintain statistical counters on Get/Release node routines.
                     90:                 <7>     5/10/93        gs              Change keySize parameter to keyLength for InsertKeyRecord
                     91:                                                                        routine. Calculate number of bytes in key from keyLength to
                     92:                                                                        account for length and pad bytes. Add GetChildNodeNum routine.
                     93:                 <6>     3/23/93        gs              Add InsertKeyRecord routine.
                     94:                 <5>      2/8/93        gs              Fix bug in SearchNode that caused "off by 1" error when final
                     95:                                                                        compare was searchKey > trialKey. Add UpdateNode.
                     96:                 <4>    12/10/92        gs              Change keyLength field of key to 'length'.
                     97:                 <3>     12/8/92        gs              Incorporate suggestions from preliminary code review.
                     98:                 <2>     12/2/92        gs              Implement routines.
                     99:                 <1>    11/15/92        gs              Define routine interfaces.
                    100: 
                    101: */
                    102: 
                    103: #include "../headers/BTreesPrivate.h"
                    104: #include "../headers/system/HFSInstrumentation.h"
                    105: 
                    106: 
                    107: 
                    108: ///////////////////////// BTree Module Node Operations //////////////////////////
                    109: //
                    110: //     GetNode                         - Call FS Agent to get node
                    111: //     GetNewNode                      - Call FS Agent to get a new node
                    112: //     ReleaseNode                     - Call FS Agent to release node obtained by GetNode.
                    113: //     UpdateNode                      - Mark a node as dirty and call FS Agent to release it.
                    114: //
                    115: //     CheckNode                       - Checks the validity of a node.
                    116: //     ClearNode                       - Clear a node to all zeroes.
                    117: //
                    118: //     InsertRecord            - Inserts a record into a BTree node.
                    119: //     InsertKeyRecord         - Inserts a key and record pair into a BTree node.
                    120: //     DeleteRecord            - Deletes a record from a BTree node.
                    121: //
                    122: //     SearchNode                      - Return index for record that matches key.
                    123: //     LocateRecord            - Return pointer to key and data, and size of data.
                    124: //
                    125: //     GetNodeDataSize         - Return the amount of space used for data in the node.
                    126: //     GetNodeFreeSize         - Return the amount of free space in the node.
                    127: //
                    128: //     GetRecordOffset         - Return the offset for record "index".
                    129: //     GetRecordAddress        - Return address of record "index".
                    130: //     GetOffsetAddress        - Return address of offset for record "index".
                    131: //
                    132: //     InsertOffset            - Inserts a new offset into a node.
                    133: //     DeleteOffset            - Deletes an offset from a node.
                    134: //
                    135: //     MoveRecordsLeft         - Move records left within a node.
                    136: //     MoveRecordsRight        - Move records right within a node.
                    137: //
                    138: /////////////////////////////////////////////////////////////////////////////////
                    139: 
                    140: 
                    141: 
                    142: ////////////////////// Routines Internal To BTreeNodeOps.c //////////////////////
                    143: 
                    144: UInt16         GetRecordOffset         (BTreeControlBlockPtr    btree,
                    145:                                                                 NodeDescPtr                     node,
                    146:                                                                 UInt16                                  index );
                    147: 
                    148: UInt16    *GetOffsetAddress    (BTreeControlBlockPtr   btreePtr,
                    149:                                                                 NodeDescPtr                     node,
                    150:                                                                 UInt16                                 index );
                    151:                                                                 
                    152: void           InsertOffset            (BTreeControlBlockPtr    btreePtr,
                    153:                                                                 NodeDescPtr                     node,
                    154:                                                                 UInt16                                  index,
                    155:                                                                 UInt16                                  delta );
                    156: 
                    157: void           DeleteOffset            (BTreeControlBlockPtr    btreePtr,
                    158:                                                                 NodeDescPtr                     node,
                    159:                                                                 UInt16                                  index );
                    160: 
                    161: 
                    162: /////////////////////////////////////////////////////////////////////////////////
                    163: 
                    164: #define GetRecordOffset(btreePtr,node,index)           (*(short *) ((UInt8 *)(node) + (btreePtr)->nodeSize - ((index) << 1) - kOffsetSize))
                    165: 
                    166: #if TARGET_OS_RHAPSODY && DIAGNOSTIC
                    167:        #ifdef KERNEL
                    168:                #include <sys/systm.h>
                    169:            #define PRINTIT kprintf
                    170:        #else /* !KERNEL */
                    171:            #define PRINTIT printf
                    172:        #endif /* KERNEL */
                    173: 
                    174: static void PrintNode(const NodeDescPtr node, UInt16 nodeSize, UInt32 nodeNumber);
                    175: #endif
                    176: 
                    177: 
                    178: 
                    179: /*-------------------------------------------------------------------------------
                    180: 
                    181: Routine:       GetNode -       Call FS Agent to get node
                    182: 
                    183: Function:      Gets an existing BTree node from FS Agent and verifies it.
                    184: 
                    185: Input:         btreePtr        - pointer to BTree control block
                    186:                        nodeNum         - number of node to request
                    187:                        
                    188: Output:                nodePtr         - pointer to beginning of node (nil if error)
                    189:                        
                    190: Result:
                    191:                        noErr           - success
                    192:                        != noErr        - failure
                    193: -------------------------------------------------------------------------------*/
                    194: 
                    195: OSStatus       GetNode         (BTreeControlBlockPtr    btreePtr,
                    196:                                                 UInt32                                  nodeNum,
                    197:                                                 NodeRec                                *nodePtr )
                    198: {
                    199:        OSStatus                        err;
                    200:        GetBlockProcPtr         getNodeProc;
                    201:        
                    202: 
                    203:        LogStartTime(kTraceGetNode);
                    204: 
                    205:        //�� is nodeNum within proper range?
                    206:        if( nodeNum >= btreePtr->totalNodes )
                    207:        {
                    208:                Panic("\pGetNode:nodeNum >= totalNodes");
                    209:                err = fsBTInvalidNodeErr;
                    210:                goto ErrorExit;
                    211:        }
                    212:        
                    213:        nodePtr->blockSize = btreePtr->nodeSize;        // indicate the size of a node
                    214:        
                    215:        getNodeProc = btreePtr->getBlockProc;
                    216:        err = getNodeProc (btreePtr->fileRefNum,
                    217:                                           nodeNum,
                    218:                                           kGetBlock,
                    219:                                           nodePtr );
                    220: 
                    221:        if (err != noErr)
                    222:        {
                    223:                Panic ("\pGetNode: getNodeProc returned error.");
                    224:                goto ErrorExit;
                    225:        }
                    226:        ++btreePtr->numGetNodes;
                    227:        
                    228:        //
                    229:        // Optimization
                    230:        // Only call CheckNode if the node came from disk.
                    231:        // If it was in the cache, we'll assume its already a valid node.
                    232:        //
                    233:        
                    234:        if ( nodePtr->blockReadFromDisk )       // if we read it from disk then check it
                    235:        {
                    236:                err = CheckNode (btreePtr, nodePtr->buffer);
                    237: 
                    238:                if (err != noErr)
                    239:                {
                    240:                  #if TARGET_OS_RHAPSODY && DIAGNOSTIC
                    241:                        if (((NodeDescPtr)nodePtr->buffer)->numRecords != 0)
                    242:                                PrintNode(nodePtr->buffer, btreePtr->nodeSize, nodeNum);
                    243:                  #endif
                    244: 
                    245:                        if (DEBUG_BUILD)
                    246:                        {
                    247:                                // With the removal of bounds checking in IsItAHint(), it's possible that
                    248:                                // GetNode() will be called to fetch a clear (all zeroes) node. We want
                    249:                                // CheckNode() to fail in this case (it does), however we don't want to assert
                    250:                                // this case because it is not really an "error". Returning an error from GetNode()
                    251:                                // in this case will cause the hint checking code to ignore the hint and revert to
                    252:                                // the full search mode.
                    253:                                
                    254:                                {
                    255:                                        UInt32  *cur;
                    256:                                        UInt32  *lastPlusOne;
                    257:                                        
                    258:                                        cur             = nodePtr->buffer;
                    259:                                        lastPlusOne = (UInt32 *) ((UInt8 *) cur + btreePtr->nodeSize);
                    260:                                        
                    261:                                        while( cur < lastPlusOne )
                    262:                                        {
                    263:                                                if( *cur++ != 0 )
                    264:                                                {
                    265:                                                        Panic ("\pGetNode: CheckNode returned error.");
                    266:                                                        break;
                    267:                                                }
                    268:                                        }
                    269:                                }
                    270:                        }
                    271:                        
                    272:                        (void) ReleaseNode (btreePtr, nodePtr);                 // ignore error
                    273:                        goto ErrorExit;
                    274:                }
                    275:        }
                    276: 
                    277:        LogEndTime(kTraceGetNode, noErr);
                    278: 
                    279:        return noErr;
                    280: 
                    281: ErrorExit:
                    282:        nodePtr->buffer                 = nil;
                    283:        nodePtr->blockHeader    = nil;
                    284:        
                    285:        LogEndTime(kTraceGetNode, err);
                    286: 
                    287:        return  err;
                    288: }
                    289: 
                    290: 
                    291: 
                    292: /*-------------------------------------------------------------------------------
                    293: 
                    294: Routine:       GetNewNode      -       Call FS Agent to get a new node
                    295: 
                    296: Function:      Gets a new BTree node from FS Agent and initializes it to an empty
                    297:                        state.
                    298: 
                    299: Input:         btreePtr                - pointer to BTree control block
                    300:                        nodeNum                 - number of node to request
                    301:                        
                    302: Output:                returnNodePtr   - pointer to beginning of node (nil if error)
                    303:                        
                    304: Result:                noErr           - success
                    305:                        != noErr        - failure
                    306: -------------------------------------------------------------------------------*/
                    307: 
                    308: OSStatus       GetNewNode      (BTreeControlBlockPtr    btreePtr,
                    309:                                                 UInt32                                  nodeNum,
                    310:                                                 NodeRec                                *returnNodePtr )
                    311: {
                    312:        OSStatus                         err;
                    313:        NodeDescPtr                      node;
                    314:        void                            *pos;
                    315:        GetBlockProcPtr          getNodeProc;
                    316:        
                    317: 
                    318:        //////////////////////// get buffer for new node ////////////////////////////
                    319: 
                    320:        returnNodePtr->blockSize = btreePtr->nodeSize;  // indicate the size of a node
                    321: 
                    322:        getNodeProc = btreePtr->getBlockProc;
                    323:        err = getNodeProc (btreePtr->fileRefNum,
                    324:                                           nodeNum,
                    325:                                           kGetBlock+kGetEmptyBlock,
                    326:                                           returnNodePtr );
                    327:                                           
                    328:        if (err != noErr)
                    329:        {
                    330:                Panic ("\pGetNewNode: getNodeProc returned error.");
                    331:                return err;
                    332:        }
                    333:        ++btreePtr->numGetNewNodes;
                    334:        
                    335: 
                    336:        ////////////////////////// initialize the node //////////////////////////////
                    337: 
                    338:        node = returnNodePtr->buffer;
                    339:        
                    340:        ClearNode (btreePtr, node);                                             // clear the node
                    341: 
                    342:        pos = (char *)node + btreePtr->nodeSize - 2;    // find address of last offset
                    343:        *(UInt16 *)pos = sizeof (BTNodeDescriptor);             // set offset to beginning of free space
                    344: 
                    345: 
                    346:        return noErr;
                    347: }
                    348: 
                    349: 
                    350: 
                    351: /*-------------------------------------------------------------------------------
                    352: 
                    353: Routine:       ReleaseNode     -       Call FS Agent to release node obtained by GetNode.
                    354: 
                    355: Function:      Informs the FS Agent that a BTree node may be released.
                    356: 
                    357: Input:         btreePtr                - pointer to BTree control block
                    358:                        nodeNum                 - number of node to release
                    359:                                                
                    360: Result:                noErr           - success
                    361:                        != noErr        - failure
                    362: -------------------------------------------------------------------------------*/
                    363: 
                    364: OSStatus       ReleaseNode     (BTreeControlBlockPtr    btreePtr,
                    365:                                                 NodePtr                                 nodePtr )
                    366: {
                    367:        OSStatus                         err;
                    368:        ReleaseBlockProcPtr      releaseNodeProc;
                    369:        
                    370:        
                    371:        LogStartTime(kTraceReleaseNode);
                    372: 
                    373:        err = noErr;
                    374:        
                    375:        if (nodePtr->buffer != nil)
                    376:        {
                    377:                releaseNodeProc = btreePtr->releaseBlockProc;
                    378:                err = releaseNodeProc (btreePtr->fileRefNum,
                    379:                                                           nodePtr,
                    380:                                                           kReleaseBlock );
                    381:                PanicIf (err, "\pReleaseNode: releaseNodeProc returned error.");
                    382:                ++btreePtr->numReleaseNodes;
                    383:        }
                    384:        
                    385:        nodePtr->buffer                 = nil;
                    386:        nodePtr->blockHeader    = nil;
                    387:        
                    388:        LogEndTime(kTraceReleaseNode, err);
                    389: 
                    390:        return err;
                    391: }
                    392: 
                    393: 
                    394: 
                    395: /*-------------------------------------------------------------------------------
                    396: 
                    397: Routine:       UpdateNode      -       Mark a node as dirty and call FS Agent to release it.
                    398: 
                    399: Function:      Marks a BTree node dirty and informs the FS Agent that it may be released.
                    400: 
                    401:                        //�� have another routine that clears & writes a node, so we can call
                    402:                        CheckNode from this routine.
                    403: 
                    404: Input:         btreePtr                - pointer to BTree control block
                    405:                        nodeNum                 - number of node to release
                    406:                                                
                    407: Result:                noErr           - success
                    408:                        != noErr        - failure
                    409: -------------------------------------------------------------------------------*/
                    410: 
                    411: OSStatus       UpdateNode      (BTreeControlBlockPtr    btreePtr,
                    412:                                                 NodePtr                                 nodePtr )
                    413: {
                    414:        OSStatus                         err;
                    415:        ReleaseBlockProcPtr      releaseNodeProc;
                    416:        
                    417:        
                    418:        err = noErr;
                    419:                
                    420:        if (nodePtr->buffer != nil)                     //�� why call UpdateNode if nil ?!?
                    421:        {
                    422:                if (DEBUG_BUILD)
                    423:                {
                    424:                        if ( btreePtr->attributes & kBTVariableIndexKeysMask )
                    425:                                (void) CheckNode (btreePtr, nodePtr->buffer);
                    426:                }
                    427: 
                    428:                LogStartTime(kTraceReleaseNode);
                    429: 
                    430:                releaseNodeProc = btreePtr->releaseBlockProc;
                    431:                err = releaseNodeProc (btreePtr->fileRefNum,
                    432:                                                           nodePtr,
                    433:                                                           kMarkBlockDirty );
                    434:                                                           
                    435:                LogEndTime(kTraceReleaseNode, err);
                    436: 
                    437:                M_ExitOnError (err);
                    438:                ++btreePtr->numUpdateNodes;
                    439:        }
                    440:        
                    441:        nodePtr->buffer                 = nil;
                    442:        nodePtr->blockHeader    = nil;
                    443: 
                    444:        return  noErr;
                    445: 
                    446: ErrorExit:
                    447:        
                    448:        return  err;
                    449: }
                    450: 
                    451: 
                    452: 
                    453: /*-------------------------------------------------------------------------------
                    454: 
                    455: Routine:       CheckNode       -       Checks the validity of a node.
                    456: 
                    457: Function:      Checks the validity of a node by verifying that the fLink and bLink fields
                    458:                        are within the forks EOF. The node type must be one of the four known
                    459:                        types. The node height must be less than or equal to the tree height. The
                    460:                        node must not have more than the maximum number of records, and the record
                    461:                        offsets must make sense.
                    462: 
                    463: Input:         btreePtr                - pointer to BTree control block
                    464:                        node                    - pointer to node to check
                    465:                                                
                    466: Result:                noErr           - success
                    467:                        fsBTInvalidNodeErr              - failure
                    468: -------------------------------------------------------------------------------*/
                    469: 
                    470: OSStatus       CheckNode       (BTreeControlBlockPtr    btreePtr, NodeDescPtr   node )
                    471: {
                    472:        SInt32          index;
                    473:        SInt32          maxRecords;
                    474:        UInt32          maxNode;
                    475:        UInt16          nodeSize;
                    476:        UInt16          offset;
                    477:        UInt16          prevOffset;
                    478: 
                    479: #if DEBUG_BUILD
                    480:        KeyPtr                          thisKey, lastKey = NULL;
                    481:        KeyCompareProcPtr       compareProc = NULL;
                    482: #endif
                    483: 
                    484:        
                    485:        nodeSize = btreePtr->nodeSize;
                    486: 
                    487:        ///////////////////// are fLink and bLink within EOF ////////////////////////
                    488:        
                    489:        maxNode = (GetFileControlBlock(btreePtr->fileRefNum)->fcbEOF / nodeSize) - 1;
                    490:        
                    491:        if ( (node->fLink > maxNode) || (node->bLink > maxNode) )
                    492:                return fsBTInvalidNodeErr;
                    493:        
                    494:        
                    495:        /////////////// check node type (leaf, index, header, map) //////////////////
                    496:        
                    497:        if ( (node->type < kLeafNode) || (node->type > kMapNode) )
                    498:                return fsBTInvalidNodeErr;
                    499:        
                    500: 
                    501:        ///////////////////// is node height > tree depth? //////////////////////////
                    502: 
                    503:        if ( node->height > btreePtr->treeDepth )
                    504:                return fsBTInvalidNodeErr;
                    505:        
                    506: 
                    507:        //////////////////////// check number of records ////////////////////////////
                    508:                
                    509:        //�� can we calculate a more accurate minimum record size?
                    510:        maxRecords = ( nodeSize - sizeof (BTNodeDescriptor) ) >> 3;
                    511:        
                    512:        if (node->numRecords > maxRecords)
                    513:                return fsBTInvalidNodeErr;
                    514: 
                    515: 
                    516:        ////////////////////////// check record offsets /////////////////////////////
                    517: 
                    518:        index = node->numRecords;                                       // begin with free space offset
                    519:        offset = nodeSize - (index << 1);                               // init offset to max free offset+2
                    520:        
                    521: #if DEBUG_BUILD
                    522:        if ( btreePtr->attributes & kBTVariableIndexKeysMask )
                    523:        {
                    524:                compareProc = btreePtr->keyCompareProc;
                    525:                lastKey = NULL;
                    526:        }
                    527: #endif
                    528: 
                    529:        do {
                    530:                prevOffset = offset;
                    531:                offset = GetRecordOffset (btreePtr, node, index);       
                    532: 
                    533: #if DEBUG_BUILD        
                    534:                if ( btreePtr->attributes & kBTVariableIndexKeysMask    &&
                    535:                         index < node->numRecords                                                       &&
                    536:                         (node->type == kLeafNode || node->type == kIndexNode) )
                    537:                {
                    538:                        thisKey = (KeyPtr) GetRecordAddress (btreePtr, node, index );
                    539:        
                    540:                        if ( (lastKey != NULL) && (compareProc(thisKey, lastKey) >= 0) )
                    541:                        {
                    542:                                Panic ( "\p CheckNode: keys out of order! ");
                    543:                                return fsBTInvalidNodeErr;
                    544:                        }
                    545:                        
                    546:                        lastKey = thisKey;
                    547:                }
                    548: #endif
                    549: 
                    550:                if (offset < sizeof (BTNodeDescriptor) )        // offset < minimum
                    551:                        return fsBTInvalidNodeErr;
                    552:                        
                    553:                if (offset & 1)                                                         // offset is odd
                    554:                        return fsBTInvalidNodeErr;
                    555:                
                    556:                if (offset >= prevOffset)                                       // offset >= previous offset
                    557:                        return fsBTInvalidNodeErr;
                    558:                
                    559:                if (offset >= nodeSize)                                         // offset beyond end of node
                    560:                        return fsBTInvalidNodeErr;
                    561:                
                    562:        } while ( --index >= 0 );
                    563:        
                    564:        
                    565:        return noErr;
                    566: }
                    567: 
                    568: 
                    569: #if TARGET_OS_RHAPSODY && DIAGNOSTIC
                    570: static void PrintNode(const NodeDescPtr node, UInt16 nodeSize, UInt32 nodeNumber)
                    571: {
                    572:        struct row {
                    573:                UInt16  word[8];
                    574:        };
                    575:        struct row      *offset;
                    576:        UInt16  rows;
                    577:        UInt32  *lp;
                    578: 
                    579:        PRINTIT("Dump of B-tree node #%ld ($%08lX)\n", nodeNumber, nodeNumber);
                    580: 
                    581:        rows = nodeSize/16;
                    582:        lp = (UInt32*) node;
                    583:        offset = 0;
                    584:        
                    585:        while (rows-- > 0)
                    586:                PRINTIT("%04X: %08lX %08lX %08lX %08lX\n", (u_int)offset++, *lp++, *lp++, *lp++, *lp++);
                    587: }
                    588: #endif
                    589: 
                    590: 
                    591: /*-------------------------------------------------------------------------------
                    592: 
                    593: Routine:       ClearNode       -       Clear a node to all zeroes.
                    594: 
                    595: Function:      Writes zeroes from beginning of node for nodeSize bytes.
                    596: 
                    597: Input:         btreePtr                - pointer to BTree control block
                    598:                        node                    - pointer to node to clear
                    599:                                                
                    600: Result:                none
                    601: -------------------------------------------------------------------------------*/
                    602: 
                    603: void   ClearNode       (BTreeControlBlockPtr   btreePtr, NodeDescPtr    node )
                    604: {
                    605:        ClearMemory( node, btreePtr->nodeSize );
                    606: }
                    607: 
                    608: /*-------------------------------------------------------------------------------
                    609: 
                    610: Routine:       InsertRecord    -       Inserts a record into a BTree node.
                    611: 
                    612: Function:      
                    613: 
                    614: Note:          Record size must be even!
                    615: 
                    616: Input:         btreePtr                - pointer to BTree control block
                    617:                        node                    - pointer to node to insert the record
                    618:                        index                   - position record is to be inserted
                    619:                        recPtr                  - pointer to record to insert
                    620: 
                    621: Result:                noErr           - success
                    622:                        fsBTFullErr     - record larger than remaining free space.
                    623: -------------------------------------------------------------------------------*/
                    624: 
                    625: Boolean                InsertRecord    (BTreeControlBlockPtr   btreePtr,
                    626:                                                         NodeDescPtr                    node,
                    627:                                                         UInt16                                 index,
                    628:                                                         RecordPtr                              recPtr,
                    629:                                                         UInt16                                 recSize )
                    630: {
                    631:        UInt16          freeSpace;
                    632:        UInt16          indexOffset;
                    633:        UInt16          freeOffset;
                    634:        UInt16          bytesToMove;
                    635:        void       *src;
                    636:        void       *dst;
                    637:        
                    638:        //// will new record fit in node?
                    639: 
                    640:        freeSpace = GetNodeFreeSize (btreePtr, node);
                    641:                                                                                        //�� we could get freeOffset & calc freeSpace
                    642:        if ( freeSpace < recSize + 2)
                    643:        {
                    644:                return false;
                    645:        }
                    646: 
                    647:        
                    648:        //// make hole for new record
                    649: 
                    650:        indexOffset = GetRecordOffset (btreePtr, node, index);
                    651:        freeOffset      = GetRecordOffset (btreePtr, node, node->numRecords);
                    652: 
                    653:        src = ((Ptr) node) + indexOffset;
                    654:        dst = ((Ptr) src)  + recSize;
                    655:        bytesToMove = freeOffset - indexOffset;
                    656:        MoveRecordsRight (src, dst, bytesToMove);
                    657: 
                    658: 
                    659:        //// adjust offsets for moved records
                    660: 
                    661:        InsertOffset (btreePtr, node, index, recSize);
                    662: 
                    663: 
                    664:        //// move in the new record
                    665: 
                    666:        dst = ((Ptr) node) + indexOffset;
                    667:        MoveRecordsLeft (recPtr, dst, recSize);
                    668: 
                    669:        return true;
                    670: }
                    671: 
                    672: 
                    673: 
                    674: /*-------------------------------------------------------------------------------
                    675: 
                    676: Routine:       InsertKeyRecord -       Inserts a record into a BTree node.
                    677: 
                    678: Function:      
                    679: 
                    680: Note:          Record size must be even!
                    681: 
                    682: Input:         btreePtr                - pointer to BTree control block
                    683:                        node                    - pointer to node to insert the record
                    684:                        index                   - position record is to be inserted
                    685:                        keyPtr                  - pointer to key for record to insert
                    686:                        keyLength               - length of key (or maxKeyLength)
                    687:                        recPtr                  - pointer to record to insert
                    688:                        recSize                 - number of bytes to copy for record
                    689: 
                    690: Result:                noErr           - success
                    691:                        fsBTFullErr     - record larger than remaining free space.
                    692: -------------------------------------------------------------------------------*/
                    693: 
                    694: Boolean                InsertKeyRecord         (BTreeControlBlockPtr    btreePtr,
                    695:                                                                 NodeDescPtr                     node,
                    696:                                                                 UInt16                                  index,
                    697:                                                                 KeyPtr                                  keyPtr,
                    698:                                                                 UInt16                                  keyLength,
                    699:                                                                 RecordPtr                               recPtr,
                    700:                                                                 UInt16                                  recSize )
                    701: {
                    702:        UInt16          freeSpace;
                    703:        UInt16          indexOffset;
                    704:        UInt16          freeOffset;
                    705:        UInt16          bytesToMove;
                    706:        UInt8 *         src;
                    707:        UInt8 *         dst;
                    708:        UInt16          keySize;
                    709:        UInt16          rawKeyLength;
                    710:        UInt16          sizeOfLength;
                    711:        
                    712:        //// calculate actual key size
                    713: 
                    714:        if ( btreePtr->attributes & kBTBigKeysMask )
                    715:                keySize = keyLength + sizeof(UInt16);
                    716:        else
                    717:                keySize = keyLength + sizeof(UInt8);
                    718:        
                    719:        if ( M_IsOdd (keySize) )
                    720:                ++keySize;                      // add pad byte
                    721: 
                    722: 
                    723:        //// will new record fit in node?
                    724: 
                    725:        freeSpace = GetNodeFreeSize (btreePtr, node);
                    726:                                                                                        //�� we could get freeOffset & calc freeSpace
                    727:        if ( freeSpace < keySize + recSize + 2)
                    728:        {
                    729:                return false;
                    730:        }
                    731: 
                    732:        
                    733:        //// make hole for new record
                    734: 
                    735:        indexOffset = GetRecordOffset (btreePtr, node, index);
                    736:        freeOffset      = GetRecordOffset (btreePtr, node, node->numRecords);
                    737: 
                    738:        src = ((UInt8 *) node) + indexOffset;
                    739:        dst = ((UInt8 *) src) + keySize + recSize;
                    740:        bytesToMove = freeOffset - indexOffset;
                    741:        MoveRecordsRight (src, dst, bytesToMove);
                    742: 
                    743: 
                    744:        //// adjust offsets for moved records
                    745: 
                    746:        InsertOffset (btreePtr, node, index, keySize + recSize);
                    747:        
                    748: 
                    749:        //// copy record key
                    750: 
                    751:        dst = ((UInt8 *) node) + indexOffset;
                    752: 
                    753:        if ( btreePtr->attributes & kBTBigKeysMask )
                    754:        {
                    755:                *((UInt16*) dst)++ = keyLength;         // use keyLength rather than key.length
                    756:                rawKeyLength = keyPtr->length16;
                    757:                sizeOfLength = 2;
                    758:        }
                    759:        else
                    760:        {
                    761:                *dst++ = keyLength;                                     // use keyLength rather than key.length
                    762:                rawKeyLength = keyPtr->length8;
                    763:                sizeOfLength = 1;
                    764:        }
                    765:        
                    766:        MoveRecordsLeft ( ((UInt8 *) keyPtr) + sizeOfLength, dst, rawKeyLength);        // copy key
                    767: 
                    768:        // any pad bytes?
                    769:        bytesToMove = keySize - rawKeyLength;
                    770:        if (bytesToMove)
                    771:                ClearMemory (dst + rawKeyLength, bytesToMove);  // clear pad bytes in index key
                    772: 
                    773: 
                    774:        //// copy record data
                    775: 
                    776:        dst = ((UInt8 *) node) + indexOffset + keySize;
                    777:        MoveRecordsLeft (recPtr, dst, recSize);
                    778: 
                    779:        return true;
                    780: }
                    781: 
                    782: 
                    783: 
                    784: /*-------------------------------------------------------------------------------
                    785: 
                    786: Routine:       DeleteRecord    -       Deletes a record from a BTree node.
                    787: 
                    788: Function:      
                    789: 
                    790: Input:         btreePtr                - pointer to BTree control block
                    791:                        node                    - pointer to node to insert the record
                    792:                        index                   - position record is to be inserted
                    793: 
                    794: Result:                none
                    795: -------------------------------------------------------------------------------*/
                    796: 
                    797: void           DeleteRecord    (BTreeControlBlockPtr   btreePtr,
                    798:                                                         NodeDescPtr                    node,
                    799:                                                         UInt16                                 index )
                    800: {
                    801:        SInt16          indexOffset;
                    802:        SInt16          nextOffset;
                    803:        SInt16          freeOffset;
                    804:        SInt16          bytesToMove;
                    805:        void       *src;
                    806:        void       *dst;
                    807:        
                    808:        //// compress records
                    809:        indexOffset = GetRecordOffset (btreePtr, node, index);
                    810:        nextOffset      = GetRecordOffset (btreePtr, node, index + 1);
                    811:        freeOffset      = GetRecordOffset (btreePtr, node, node->numRecords);
                    812: 
                    813:        src = ((Ptr) node) + nextOffset;
                    814:        dst = ((Ptr) node) + indexOffset;
                    815:        bytesToMove = freeOffset - nextOffset;
                    816:        MoveRecordsLeft (src, dst, bytesToMove);
                    817: 
                    818:        //// Adjust the offsets
                    819:        DeleteOffset (btreePtr, node, index);
                    820: }
                    821: 
                    822: 
                    823: 
                    824: /*-------------------------------------------------------------------------------
                    825: 
                    826: Routine:       SearchNode      -       Return index for record that matches key.
                    827: 
                    828: Function:      Returns the record index for the record that matches the search key.
                    829:                        If no record was found that matches the search key, the "insert index"
                    830:                        of where the record should go is returned instead.
                    831: 
                    832: Algorithm:     A binary search algorithm is used to find the specified key.
                    833: 
                    834: Input:         btreePtr        - pointer to BTree control block
                    835:                        node            - pointer to node that contains the record
                    836:                        searchKey       - pointer to the key to match
                    837: 
                    838: Output:                index           - pointer to beginning of key for record
                    839: 
                    840: Result:                true    - success (index = record index)
                    841:                        false   - key did not match anything in node (index = insert index)
                    842: -------------------------------------------------------------------------------*/
                    843: #if !TARGET_CPU_68K
                    844: 
                    845: Boolean                SearchNode              (BTreeControlBlockPtr    btreePtr,
                    846:                                                         NodeDescPtr                     node,
                    847:                                                         KeyPtr                                  searchKey,
                    848:                                                         UInt16                                 *returnIndex )
                    849: {
                    850:        SInt32          lowerBound;
                    851:        SInt32          upperBound;
                    852:        SInt32          index;
                    853:        SInt32          result;
                    854:        KeyPtr          trialKey;
                    855: #if !SupportsKeyDescriptors
                    856:        KeyCompareProcPtr       compareProc = btreePtr->keyCompareProc;
                    857: #endif 
                    858: 
                    859:        lowerBound = 0;
                    860:        upperBound = node->numRecords - 1;
                    861:        
                    862:        while (lowerBound <= upperBound)
                    863:        {
                    864:                index = (lowerBound + upperBound) >> 1;         // divide by 2
                    865:                
                    866:                trialKey = (KeyPtr) GetRecordAddress (btreePtr, node, index );
                    867:                
                    868:        #if SupportsKeyDescriptors
                    869:                result = CompareKeys (btreePtr, searchKey, trialKey);
                    870:        #else
                    871:                result = compareProc(searchKey, trialKey);
                    872:        #endif
                    873:                
                    874:                if              (result <  0)           upperBound = index - 1;         // search < trial
                    875:                else if (result >  0)           lowerBound = index + 1;         // search > trial
                    876:                else                                                                                                    // search = trial
                    877:                {
                    878:                        *returnIndex = index;
                    879:                        return true;
                    880:                }
                    881:        }
                    882:        
                    883:        *returnIndex = lowerBound;                              // lowerBound is insert index
                    884:        return false;
                    885: }
                    886: 
                    887: #endif
                    888: 
                    889: 
                    890: /*-------------------------------------------------------------------------------
                    891: 
                    892: Routine:       GetRecordByIndex        -       Return pointer to key and data, and size of data.
                    893: 
                    894: Function:      Returns a pointer to beginning of key for record, a pointer to the
                    895:                        beginning of the data for the record, and the size of the record data
                    896:                        (does not include the size of the key).
                    897: 
                    898: Input:         btreePtr        - pointer to BTree control block
                    899:                        node            - pointer to node that contains the record
                    900:                        index           - index of record to get
                    901: 
                    902: Output:                keyPtr          - pointer to beginning of key for record
                    903:                        dataPtr         - pointer to beginning of data for record
                    904:                        dataSize        - size of the data portion of the record
                    905: 
                    906: Result:                none
                    907: -------------------------------------------------------------------------------*/
                    908: 
                    909: OSStatus       GetRecordByIndex        (BTreeControlBlockPtr    btreePtr,
                    910:                                                                 NodeDescPtr                     node,
                    911:                                                                 UInt16                                  index,
                    912:                                                                 KeyPtr                                 *keyPtr,
                    913:                                                                 UInt8 *                                *dataPtr,
                    914:                                                                 UInt16                                 *dataSize )
                    915: {
                    916:        UInt16          offset;
                    917:        UInt16          nextOffset;
                    918:        UInt16          keySize;
                    919:        
                    920:        //
                    921:        //      Make sure index is valid (in range 0..numRecords-1)
                    922:        //
                    923:        if (index >= node->numRecords)
                    924:                return fsBTRecordNotFoundErr;
                    925: 
                    926:        //// find keyPtr
                    927:        offset          = GetRecordOffset (btreePtr, node, index);
                    928:        *keyPtr         = (KeyPtr) ((Ptr)node + offset);
                    929: 
                    930:        //// find dataPtr
                    931:        keySize = CalcKeySize(btreePtr, *keyPtr);
                    932:        if ( M_IsOdd (keySize) )
                    933:                ++keySize;      // add pad byte
                    934: 
                    935:        offset += keySize;                      // add the key length to find data offset
                    936:        *dataPtr = (UInt8 *) node + offset;
                    937:        
                    938:        //// find dataSize
                    939:        nextOffset      = GetRecordOffset (btreePtr, node, index + 1);
                    940:        *dataSize       = nextOffset - offset;
                    941:        
                    942:        return noErr;
                    943: }
                    944:                                                                 
                    945: 
                    946: 
                    947: /*-------------------------------------------------------------------------------
                    948: 
                    949: Routine:       GetNodeDataSize -       Return the amount of space used for data in the node.
                    950: 
                    951: Function:      Gets the size of the data currently contained in a node, excluding
                    952:                        the node header. (record data + offset overhead)
                    953: 
                    954: Input:         btreePtr                - pointer to BTree control block
                    955:                        node                    - pointer to node that contains the record
                    956: 
                    957: Result:                - number of bytes used for data and offsets in the node.
                    958: -------------------------------------------------------------------------------*/
                    959: 
                    960: UInt16         GetNodeDataSize (BTreeControlBlockPtr   btreePtr, NodeDescPtr    node )
                    961: {
                    962:        UInt16 freeOffset;
                    963:        
                    964:        freeOffset = GetRecordOffset (btreePtr, node, node->numRecords);
                    965:        
                    966:        return  freeOffset + (node->numRecords << 1) - sizeof (BTNodeDescriptor);
                    967: }
                    968: 
                    969: 
                    970: 
                    971: /*-------------------------------------------------------------------------------
                    972: 
                    973: Routine:       GetNodeFreeSize -       Return the amount of free space in the node.
                    974: 
                    975: Function:      
                    976: 
                    977: Input:         btreePtr                - pointer to BTree control block
                    978:                        node                    - pointer to node that contains the record
                    979: 
                    980: Result:                - number of bytes of free space in the node.
                    981: -------------------------------------------------------------------------------*/
                    982: 
                    983: UInt16         GetNodeFreeSize (BTreeControlBlockPtr   btreePtr, NodeDescPtr    node )
                    984: {
                    985:        UInt16  freeOffset;
                    986:        
                    987:        freeOffset = GetRecordOffset (btreePtr, node, node->numRecords);        //�� inline?
                    988:        
                    989:        return btreePtr->nodeSize - freeOffset - (node->numRecords << 1) - kOffsetSize;
                    990: }
                    991: 
                    992: 
                    993: 
                    994: /*-------------------------------------------------------------------------------
                    995: 
                    996: Routine:       GetRecordOffset -       Return the offset for record "index".
                    997: 
                    998: Function:      
                    999: 
                   1000: Input:         btreePtr                - pointer to BTree control block
                   1001:                        node                    - pointer to node that contains the record
                   1002:                        index                   - record to obtain offset for
                   1003: 
                   1004: Result:                - offset (in bytes) from beginning of node of record specified by index
                   1005: -------------------------------------------------------------------------------*/
                   1006: // make this a macro (for inlining)
                   1007: #if 0
                   1008: UInt16         GetRecordOffset (BTreeControlBlockPtr   btreePtr,
                   1009:                                                         NodeDescPtr                    node,
                   1010:                                                         UInt16                                 index )
                   1011: {
                   1012:        void    *pos;
                   1013:        
                   1014:                
                   1015:        pos = (UInt8 *)node + btreePtr->nodeSize - (index << 1) - kOffsetSize;
                   1016:        
                   1017:        return *(short *)pos;
                   1018: }
                   1019: #endif
                   1020: 
                   1021: 
                   1022: 
                   1023: /*-------------------------------------------------------------------------------
                   1024: 
                   1025: Routine:       GetRecordAddress        -       Return address of record "index".
                   1026: 
                   1027: Function:      
                   1028: 
                   1029: Input:         btreePtr                - pointer to BTree control block
                   1030:                        node                    - pointer to node that contains the record
                   1031:                        index                   - record to obtain offset address for
                   1032: 
                   1033: Result:                - pointer to record "index".
                   1034: -------------------------------------------------------------------------------*/
                   1035: // make this a macro (for inlining)
                   1036: #if 0
                   1037: UInt8 *                GetRecordAddress        (BTreeControlBlockPtr   btreePtr,
                   1038:                                                                 NodeDescPtr                    node,
                   1039:                                                                 UInt16                                 index )
                   1040: {
                   1041:        UInt8 *         pos;
                   1042:        
                   1043:        pos = (UInt8 *)node + GetRecordOffset (btreePtr, node, index);
                   1044:        
                   1045:        return pos;
                   1046: }
                   1047: #endif
                   1048: 
                   1049: 
                   1050: 
                   1051: /*-------------------------------------------------------------------------------
                   1052: 
                   1053: Routine:       GetRecordSize   -       Return size of record "index".
                   1054: 
                   1055: Function:      
                   1056: 
                   1057: Note:          This does not work on the FreeSpace index!
                   1058: 
                   1059: Input:         btreePtr                - pointer to BTree control block
                   1060:                        node                    - pointer to node that contains the record
                   1061:                        index                   - record to obtain record size for
                   1062: 
                   1063: Result:                - size of record "index".
                   1064: -------------------------------------------------------------------------------*/
                   1065: 
                   1066: UInt16         GetRecordSize           (BTreeControlBlockPtr   btreePtr,
                   1067:                                                                 NodeDescPtr                    node,
                   1068:                                                                 UInt16                                 index )
                   1069: {
                   1070:        UInt16  *pos;
                   1071:                
                   1072:        pos = (UInt16 *) ((Ptr)node + btreePtr->nodeSize - (index << 1) - kOffsetSize);
                   1073:        
                   1074:        return  *(pos-1) - *pos;
                   1075: }
                   1076: 
                   1077: 
                   1078: 
                   1079: /*-------------------------------------------------------------------------------
                   1080: Routine:       GetOffsetAddress        -       Return address of offset for record "index".
                   1081: 
                   1082: Function:      
                   1083: 
                   1084: Input:         btreePtr                - pointer to BTree control block
                   1085:                        node                    - pointer to node that contains the record
                   1086:                        index                   - record to obtain offset address for
                   1087: 
                   1088: Result:                - pointer to offset for record "index".
                   1089: -------------------------------------------------------------------------------*/
                   1090: 
                   1091: UInt16    *GetOffsetAddress    (BTreeControlBlockPtr   btreePtr,
                   1092:                                                                 NodeDescPtr                    node,
                   1093:                                                                 UInt16                                 index )
                   1094: {
                   1095:        void    *pos;
                   1096:        
                   1097:        pos = (Ptr)node + btreePtr->nodeSize - (index << 1) -2;
                   1098:        
                   1099:        return (UInt16 *)pos;
                   1100: }
                   1101: 
                   1102: 
                   1103: 
                   1104: /*-------------------------------------------------------------------------------
                   1105: Routine:       GetChildNodeNum -       Return child node number from index record "index".
                   1106: 
                   1107: Function:      Returns the first UInt32 stored after the key for record "index".
                   1108: 
                   1109: Assumes:       The node is an Index Node.
                   1110:                        The key.length stored at record "index" is ODD. //�� change for variable length index keys
                   1111: 
                   1112: Input:         btreePtr                - pointer to BTree control block
                   1113:                        node                    - pointer to node that contains the record
                   1114:                        index                   - record to obtain child node number from
                   1115: 
                   1116: Result:                - child node number from record "index".
                   1117: -------------------------------------------------------------------------------*/
                   1118: 
                   1119: UInt32         GetChildNodeNum                 (BTreeControlBlockPtr    btreePtr,
                   1120:                                                                         NodeDescPtr                     nodePtr,
                   1121:                                                                         UInt16                                  index )
                   1122: {
                   1123:        UInt8 *         pos;
                   1124:        
                   1125:        pos = GetRecordAddress (btreePtr, nodePtr, index);
                   1126:        pos += CalcKeySize(btreePtr, (BTreeKey *) pos);         // key.length + size of length field
                   1127:        
                   1128:        return  *(UInt32 *)pos;
                   1129: }
                   1130: 
                   1131: 
                   1132: 
                   1133: /*-------------------------------------------------------------------------------
                   1134: Routine:       InsertOffset    -       Add an offset and adjust existing offsets by delta.
                   1135: 
                   1136: Function:      Add an offset at 'index' by shifting 'index+1' through the last offset
                   1137:                        and adjusting them by 'delta', the size of the record to be inserted.
                   1138:                        The number of records contained in the node is also incremented.
                   1139: 
                   1140: Input:         btreePtr        - pointer to BTree control block
                   1141:                        node            - pointer to node
                   1142:                        index           - index at which to insert record
                   1143:                        delta           - size of record to be inserted
                   1144: 
                   1145: Result:                none
                   1146: -------------------------------------------------------------------------------*/
                   1147: 
                   1148: void           InsertOffset            (BTreeControlBlockPtr    btreePtr,
                   1149:                                                                 NodeDescPtr                     node,
                   1150:                                                                 UInt16                                  index,
                   1151:                                                                 UInt16                                  delta )
                   1152: {
                   1153:        UInt16          *src, *dst;
                   1154:        UInt16           numOffsets;
                   1155:        
                   1156:        src = GetOffsetAddress (btreePtr, node, node->numRecords);      // point to free offset
                   1157:        dst = src - 1;                                                                                          // point to new offset
                   1158:        numOffsets = node->numRecords++ - index;                        // subtract index  & postincrement
                   1159:        
                   1160:        do {
                   1161:                *dst++ = *src++ + delta;                                                                // to tricky?
                   1162:        } while (numOffsets--);
                   1163: }
                   1164: 
                   1165: 
                   1166: 
                   1167: /*-------------------------------------------------------------------------------
                   1168: 
                   1169: Routine:       DeleteOffset    -       Delete an offset.
                   1170: 
                   1171: Function:      Delete the offset at 'index' by shifting 'index+1' through the last offset
                   1172:                        and adjusting them by the size of the record 'index'.
                   1173:                        The number of records contained in the node is also decremented.
                   1174: 
                   1175: Input:         btreePtr        - pointer to BTree control block
                   1176:                        node            - pointer to node
                   1177:                        index           - index at which to delete record
                   1178: 
                   1179: Result:                none
                   1180: -------------------------------------------------------------------------------*/
                   1181: 
                   1182: void           DeleteOffset            (BTreeControlBlockPtr    btreePtr,
                   1183:                                                                 NodeDescPtr                     node,
                   1184:                                                                 UInt16                                  index )
                   1185: {
                   1186:        UInt16          *src, *dst;
                   1187:        UInt16           numOffsets;
                   1188:        UInt16           delta;
                   1189:        
                   1190:        dst                     = GetOffsetAddress (btreePtr, node, index);
                   1191:        src                     = dst - 1;
                   1192:        delta           = *src - *dst;
                   1193:        numOffsets      = --node->numRecords - index;   // predecrement numRecords & subtract index
                   1194:        
                   1195:        while (numOffsets--)
                   1196:        {
                   1197:                *--dst = *--src - delta;                                // work our way left
                   1198:        }
                   1199: }
                   1200: 
                   1201: 
                   1202: 
                   1203: /*-------------------------------------------------------------------------------
                   1204: 
                   1205: Routine:       MoveRecordsLeft -       Move records left within a node.
                   1206: 
                   1207: Function:      Moves a number of bytes from src to dst. Safely handles overlapping
                   1208:                        ranges if the bytes are being moved to the "left". No bytes are moved
                   1209:                        if bytesToMove is zero.
                   1210: 
                   1211: Input:         src                             - pointer to source
                   1212:                        dst                             - pointer to destination
                   1213:                        bytesToMove             - number of bytes to move records
                   1214: 
                   1215: Result:                none
                   1216: -------------------------------------------------------------------------------*/
                   1217: #if 0
                   1218: void           MoveRecordsLeft         (UInt8 *                                 src,
                   1219:                                                                 UInt8 *                                 dst,
                   1220:                                                                 UInt16                                  bytesToMove )
                   1221: {
                   1222:        while (bytesToMove--)
                   1223:                *dst++ = *src++;
                   1224: }
                   1225: #endif                                                  
                   1226: 
                   1227: 
                   1228: /*-------------------------------------------------------------------------------
                   1229: 
                   1230: Routine:       MoveRecordsRight        -       Move records right within a node.
                   1231: 
                   1232: Function:      Moves a number of bytes from src to dst. Safely handles overlapping
                   1233:                        ranges if the bytes are being moved to the "right". No bytes are moved
                   1234:                        if bytesToMove is zero.
                   1235: 
                   1236: Input:         src                             - pointer to source
                   1237:                        dst                             - pointer to destination
                   1238:                        bytesToMove             - number of bytes to move records
                   1239:                        
                   1240: Result:                none
                   1241: -------------------------------------------------------------------------------*/
                   1242: #if 0
                   1243: void           MoveRecordsRight        (UInt8 *                                 src,
                   1244:                                                                 UInt8 *                                 dst,
                   1245:                                                                 UInt16                                  bytesToMove )
                   1246: {
                   1247:        src += bytesToMove;
                   1248:        dst += bytesToMove;
                   1249:        
                   1250:        while (bytesToMove--)
                   1251:                *--dst = *--src;
                   1252: }
                   1253: #endif

unix.superglobalmegacorp.com

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