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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:        File:           BTreeNodeOps.c
                     24: 
                     25:        Contains:       Single-node operations for the BTree Module.
                     26: 
                     27:        Version:        xxx put the technology version here xxx
                     28: 
                     29:        Written by:     Gordon Sheridan and Bill Bruffey
                     30: 
                     31:        Copyright:      � 1992-1999 by Apple Computer, Inc., all rights reserved.
                     32: 
                     33:        File Ownership:
                     34: 
                     35:                DRI:                            Don Brady
                     36: 
                     37:                Other Contact:          Mark Day
                     38: 
                     39:                Technology:                     File Systems
                     40: 
                     41:        Writers:
                     42: 
                     43:                (msd)   Mark Day
                     44:                (djb)   Don Brady
                     45: 
                     46:        Change History (most recent first):
                     47: 
                     48:           <MOSXS>        6/1/99        djb             Sync up with Mac OS 8.6.
                     49:           <MOSXS>      4/113/99        djb             Fix key size checking bug in CheckNode.
                     50:           <MOSXS>       3/19/99        djb             Added key size checking to CheckNode.
                     51:           <MOSXS>       3/26/98        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/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 HFS_DIAGNOSTIC
                    167:                #include <sys/systm.h>
                    168:            #define PRINTIT kprintf
                    169: #endif /* HFS_DIAGNOSTIC */
                    170: 
                    171: static void PrintNode(const NodeDescPtr node, UInt16 nodeSize, UInt32 nodeNumber);
                    172: 
                    173: 
                    174: 
                    175: /*-------------------------------------------------------------------------------
                    176: 
                    177: Routine:       GetNode -       Call FS Agent to get node
                    178: 
                    179: Function:      Gets an existing BTree node from FS Agent and verifies it.
                    180: 
                    181: Input:         btreePtr        - pointer to BTree control block
                    182:                        nodeNum         - number of node to request
                    183:                        
                    184: Output:                nodePtr         - pointer to beginning of node (nil if error)
                    185:                        
                    186: Result:
                    187:                        noErr           - success
                    188:                        != noErr        - failure
                    189: -------------------------------------------------------------------------------*/
                    190: 
                    191: OSStatus       GetNode         (BTreeControlBlockPtr    btreePtr,
                    192:                                                 UInt32                                  nodeNum,
                    193:                                                 NodeRec                                *nodePtr )
                    194: {
                    195:        OSStatus                        err;
                    196:        GetBlockProcPtr         getNodeProc;
                    197:        
                    198: 
                    199:        LogStartTime(kTraceGetNode);
                    200: 
                    201:        //�� is nodeNum within proper range?
                    202:        if( nodeNum >= btreePtr->totalNodes )
                    203:        {
                    204:                Panic("\pGetNode:nodeNum >= totalNodes");
                    205:                err = fsBTInvalidNodeErr;
                    206:                goto ErrorExit;
                    207:        }
                    208:        
                    209:        nodePtr->blockSize = btreePtr->nodeSize;        // indicate the size of a node
                    210:        
                    211:        getNodeProc = btreePtr->getBlockProc;
                    212:        err = getNodeProc (btreePtr->fileRefNum,
                    213:                                           nodeNum,
                    214:                                           kGetBlock,
                    215:                                           nodePtr );
                    216: 
                    217:        if (err != noErr)
                    218:        {
                    219:                Panic ("\pGetNode: getNodeProc returned error.");
                    220:        //      nodePtr->buffer = nil;
                    221:                goto ErrorExit;
                    222:        }
                    223:        ++btreePtr->numGetNodes;
                    224:        
                    225:        //
                    226:        // Optimization
                    227:        // Only call CheckNode if the node came from disk.
                    228:        // If it was in the cache, we'll assume its already a valid node.
                    229:        //
                    230:        
                    231:        if ( nodePtr->blockReadFromDisk )       // if we read it from disk then check it
                    232:        {
                    233:                err = CheckNode (btreePtr, nodePtr->buffer);
                    234: 
                    235:                if (err != noErr)
                    236:                {       
                    237:                
                    238:                VTOVCB(btreePtr->fileRefNum)->vcbFlags |= kHFS_DamagedVolume;
                    239: 
                    240:                  #if HFS_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:        //      returnNodePtr->buffer = nil;
                    332:                return err;
                    333:        }
                    334:        ++btreePtr->numGetNewNodes;
                    335:        
                    336: 
                    337:        ////////////////////////// initialize the node //////////////////////////////
                    338: 
                    339:        node = returnNodePtr->buffer;
                    340:        
                    341:        ClearNode (btreePtr, node);                                             // clear the node
                    342: 
                    343:        pos = (char *)node + btreePtr->nodeSize - 2;    // find address of last offset
                    344:        *(UInt16 *)pos = sizeof (BTNodeDescriptor);             // set offset to beginning of free space
                    345: 
                    346: 
                    347:        return noErr;
                    348: }
                    349: 
                    350: 
                    351: 
                    352: /*-------------------------------------------------------------------------------
                    353: 
                    354: Routine:       ReleaseNode     -       Call FS Agent to release node obtained by GetNode.
                    355: 
                    356: Function:      Informs the FS Agent that a BTree node may be released.
                    357: 
                    358: Input:         btreePtr                - pointer to BTree control block
                    359:                        nodeNum                 - number of node to release
                    360:                                                
                    361: Result:                noErr           - success
                    362:                        != noErr        - failure
                    363: -------------------------------------------------------------------------------*/
                    364: 
                    365: OSStatus       ReleaseNode     (BTreeControlBlockPtr    btreePtr,
                    366:                                                 NodePtr                                 nodePtr )
                    367: {
                    368:        OSStatus                         err;
                    369:        ReleaseBlockProcPtr      releaseNodeProc;
                    370:        
                    371:        
                    372:        LogStartTime(kTraceReleaseNode);
                    373: 
                    374:        err = noErr;
                    375:        
                    376:        if (nodePtr->buffer != nil)
                    377:        {
                    378:                releaseNodeProc = btreePtr->releaseBlockProc;
                    379:                err = releaseNodeProc (btreePtr->fileRefNum,
                    380:                                                           nodePtr,
                    381:                                                           kReleaseBlock );
                    382:                PanicIf (err, "\pReleaseNode: releaseNodeProc returned error.");
                    383:                ++btreePtr->numReleaseNodes;
                    384:        }
                    385: 
                    386:        nodePtr->buffer                 = nil;
                    387:        nodePtr->blockHeader    = nil;
                    388:        
                    389:        LogEndTime(kTraceReleaseNode, err);
                    390: 
                    391:        return err;
                    392: }
                    393: 
                    394: 
                    395: 
                    396: /*-------------------------------------------------------------------------------
                    397: 
                    398: Routine:       UpdateNode      -       Mark a node as dirty and call FS Agent to release it.
                    399: 
                    400: Function:      Marks a BTree node dirty and informs the FS Agent that it may be released.
                    401: 
                    402:                        //�� have another routine that clears & writes a node, so we can call
                    403:                        CheckNode from this routine.
                    404: 
                    405: Input:         btreePtr                - pointer to BTree control block
                    406:                        nodeNum                 - number of node to release
                    407:                        transactionID   - ID of transaction this node update is a part of
                    408:                        flags                   - special flags to pass to ReleaseNodeProc
                    409:                                                
                    410: Result:                noErr           - success
                    411:                        != noErr        - failure
                    412: -------------------------------------------------------------------------------*/
                    413: 
                    414: OSStatus       UpdateNode      (BTreeControlBlockPtr    btreePtr,
                    415:                                                 NodePtr                                 nodePtr,
                    416:                                                 UInt32                                  transactionID,
                    417:                                                 UInt32                                  flags )
                    418: {
                    419:        OSStatus                         err;
                    420:        ReleaseBlockProcPtr      releaseNodeProc;
                    421:        
                    422:        
                    423:        err = noErr;
                    424:                
                    425:        if (nodePtr->buffer != nil)                     //�� why call UpdateNode if nil ?!?
                    426:        {
                    427:                if (DEBUG_BUILD)
                    428:                {
                    429:                        if ( btreePtr->attributes & kBTVariableIndexKeysMask )
                    430:                                (void) CheckNode (btreePtr, nodePtr->buffer);
                    431:                }
                    432: 
                    433:                LogStartTime(kTraceReleaseNode);
                    434: 
                    435:                releaseNodeProc = btreePtr->releaseBlockProc;
                    436:                err = releaseNodeProc (btreePtr->fileRefNum,
                    437:                                                           nodePtr,
                    438:                                                           flags | kMarkBlockDirty );
                    439:                                                           
                    440:                LogEndTime(kTraceReleaseNode, err);
                    441: 
                    442:                M_ExitOnError (err);
                    443:                ++btreePtr->numUpdateNodes;
                    444:        }
                    445:        
                    446:        nodePtr->buffer                 = nil;
                    447:        nodePtr->blockHeader    = nil;
                    448: 
                    449:        return  noErr;
                    450: 
                    451: ErrorExit:
                    452:        
                    453:        return  err;
                    454: }
                    455: 
                    456: 
                    457: 
                    458: /*-------------------------------------------------------------------------------
                    459: 
                    460: Routine:       CheckNode       -       Checks the validity of a node.
                    461: 
                    462: Function:      Checks the validity of a node by verifying that the fLink and bLink fields
                    463:                        are within the forks EOF. The node type must be one of the four known
                    464:                        types. The node height must be less than or equal to the tree height. The
                    465:                        node must not have more than the maximum number of records, and the record
                    466:                        offsets must make sense.
                    467: 
                    468: Input:         btreePtr                - pointer to BTree control block
                    469:                        node                    - pointer to node to check
                    470:                                                
                    471: Result:                noErr           - success
                    472:                        fsBTInvalidNodeErr              - failure
                    473: -------------------------------------------------------------------------------*/
                    474: 
                    475: OSStatus       CheckNode       (BTreeControlBlockPtr    btreePtr, NodeDescPtr   node )
                    476: {
                    477:        SInt32          index;
                    478:        SInt32          maxRecords;
                    479:        UInt32          maxNode;
                    480:        UInt16          nodeSize;
                    481:        UInt16          offset;
                    482:        UInt16          prevOffset;
                    483: 
                    484:        nodeSize = btreePtr->nodeSize;
                    485: 
                    486:        ///////////////////// are fLink and bLink within EOF ////////////////////////
                    487: 
                    488:        maxNode = (GetFileControlBlock(btreePtr->fileRefNum)->fcbEOF / nodeSize) - 1;
                    489: 
                    490:        if ( (node->fLink > maxNode) || (node->bLink > maxNode) )
                    491:                return fsBTInvalidNodeErr;
                    492: 
                    493:        /////////////// check node type (leaf, index, header, map) //////////////////
                    494: 
                    495:        if ( (node->kind < kBTLeafNode) || (node->kind > kBTMapNode) )
                    496:                return fsBTInvalidNodeErr;
                    497: 
                    498:        ///////////////////// is node height > tree depth? //////////////////////////
                    499: 
                    500:        if ( node->height > btreePtr->treeDepth )
                    501:                return fsBTInvalidNodeErr;
                    502: 
                    503:        //////////////////////// check number of records ////////////////////////////
                    504:                
                    505:        //XXX can we calculate a more accurate minimum record size?
                    506:        maxRecords = ( nodeSize - sizeof (BTNodeDescriptor) ) >> 3;
                    507:        
                    508:        if (node->numRecords > maxRecords)
                    509:                return fsBTInvalidNodeErr;
                    510: 
                    511:        ////////////////////////// check record offsets /////////////////////////////
                    512: 
                    513:        index = node->numRecords;               /* start index at free space */
                    514:        prevOffset = nodeSize - (index << 1);   /* use 2 bytes past end of free space */
                    515: 
                    516:        do {
                    517:                offset = GetRecordOffset (btreePtr, node, index);
                    518:                        
                    519:                if (offset & 1)                                                         // offset is odd
                    520:                        return fsBTInvalidNodeErr;
                    521:                
                    522:                if (offset >= prevOffset)                                       // offset >= previous offset
                    523:                        return fsBTInvalidNodeErr;
                    524: 
                    525:                /* reject keys that overflow record slot */
                    526:                if ((node->kind == kBTLeafNode) &&
                    527:                    (index < node->numRecords) &&       /* ignore free space record */
                    528:                    (CalcKeySize(btreePtr, (KeyPtr) ((Ptr)node + offset)) > (prevOffset - offset))) {
                    529:                        return fsBTInvalidNodeErr;
                    530:                }
                    531:                
                    532:                prevOffset = offset;
                    533:        } while ( --index >= 0 );
                    534: 
                    535:        if (offset < sizeof (BTNodeDescriptor) )        // first offset < minimum ?
                    536:                return fsBTInvalidNodeErr;
                    537:        
                    538:        return noErr;
                    539: }
                    540: 
                    541: 
                    542: #if HFS_DIAGNOSTIC
                    543: static void PrintNode(const NodeDescPtr node, UInt16 nodeSize, UInt32 nodeNumber)
                    544: {
                    545:        struct row {
                    546:                UInt16  word[8];
                    547:        };
                    548:        struct row      *offset;
                    549:        UInt16  rows;
                    550:        UInt32  *lp;
                    551: 
                    552:        PRINTIT("Dump of B-tree node #%ld ($%08lX)\n", nodeNumber, nodeNumber);
                    553: 
                    554:        rows = nodeSize/16;
                    555:        lp = (UInt32*) node;
                    556:        offset = 0;
                    557:        
                    558:        while (rows-- > 0)
                    559:                PRINTIT("%04X: %08lX %08lX %08lX %08lX\n", (u_int)offset++, *lp++, *lp++, *lp++, *lp++);
                    560: }
                    561: #endif
                    562: 
                    563: 
                    564: /*-------------------------------------------------------------------------------
                    565: 
                    566: Routine:       ClearNode       -       Clear a node to all zeroes.
                    567: 
                    568: Function:      Writes zeroes from beginning of node for nodeSize bytes.
                    569: 
                    570: Input:         btreePtr                - pointer to BTree control block
                    571:                        node                    - pointer to node to clear
                    572:                                                
                    573: Result:                none
                    574: -------------------------------------------------------------------------------*/
                    575: 
                    576: void   ClearNode       (BTreeControlBlockPtr   btreePtr, NodeDescPtr    node )
                    577: {
                    578:        ClearMemory( node, btreePtr->nodeSize );
                    579: }
                    580: 
                    581: /*-------------------------------------------------------------------------------
                    582: 
                    583: Routine:       InsertRecord    -       Inserts a record into a BTree node.
                    584: 
                    585: Function:      
                    586: 
                    587: Note:          Record size must be even!
                    588: 
                    589: Input:         btreePtr                - pointer to BTree control block
                    590:                        node                    - pointer to node to insert the record
                    591:                        index                   - position record is to be inserted
                    592:                        recPtr                  - pointer to record to insert
                    593: 
                    594: Result:                noErr           - success
                    595:                        fsBTFullErr     - record larger than remaining free space.
                    596: -------------------------------------------------------------------------------*/
                    597: 
                    598: Boolean                InsertRecord    (BTreeControlBlockPtr   btreePtr,
                    599:                                                         NodeDescPtr                    node,
                    600:                                                         UInt16                                 index,
                    601:                                                         RecordPtr                              recPtr,
                    602:                                                         UInt16                                 recSize )
                    603: {
                    604:        UInt16          freeSpace;
                    605:        UInt16          indexOffset;
                    606:        UInt16          freeOffset;
                    607:        UInt16          bytesToMove;
                    608:        void       *src;
                    609:        void       *dst;
                    610:        
                    611:        //// will new record fit in node?
                    612: 
                    613:        freeSpace = GetNodeFreeSize (btreePtr, node);
                    614:                                                                                        //�� we could get freeOffset & calc freeSpace
                    615:        if ( freeSpace < recSize + 2)
                    616:        {
                    617:                return false;
                    618:        }
                    619: 
                    620:        
                    621:        //// make hole for new record
                    622: 
                    623:        indexOffset = GetRecordOffset (btreePtr, node, index);
                    624:        freeOffset      = GetRecordOffset (btreePtr, node, node->numRecords);
                    625: 
                    626:        src = ((Ptr) node) + indexOffset;
                    627:        dst = ((Ptr) src)  + recSize;
                    628:        bytesToMove = freeOffset - indexOffset;
                    629:        MoveRecordsRight (src, dst, bytesToMove);
                    630: 
                    631: 
                    632:        //// adjust offsets for moved records
                    633: 
                    634:        InsertOffset (btreePtr, node, index, recSize);
                    635: 
                    636: 
                    637:        //// move in the new record
                    638: 
                    639:        dst = ((Ptr) node) + indexOffset;
                    640:        MoveRecordsLeft (recPtr, dst, recSize);
                    641: 
                    642:        return true;
                    643: }
                    644: 
                    645: 
                    646: 
                    647: /*-------------------------------------------------------------------------------
                    648: 
                    649: Routine:       InsertKeyRecord -       Inserts a record into a BTree node.
                    650: 
                    651: Function:      
                    652: 
                    653: Note:          Record size must be even!
                    654: 
                    655: Input:         btreePtr                - pointer to BTree control block
                    656:                        node                    - pointer to node to insert the record
                    657:                        index                   - position record is to be inserted
                    658:                        keyPtr                  - pointer to key for record to insert
                    659:                        keyLength               - length of key (or maxKeyLength)
                    660:                        recPtr                  - pointer to record to insert
                    661:                        recSize                 - number of bytes to copy for record
                    662: 
                    663: Result:                noErr           - success
                    664:                        fsBTFullErr     - record larger than remaining free space.
                    665: -------------------------------------------------------------------------------*/
                    666: 
                    667: Boolean                InsertKeyRecord         (BTreeControlBlockPtr    btreePtr,
                    668:                                                                 NodeDescPtr                     node,
                    669:                                                                 UInt16                                  index,
                    670:                                                                 KeyPtr                                  keyPtr,
                    671:                                                                 UInt16                                  keyLength,
                    672:                                                                 RecordPtr                               recPtr,
                    673:                                                                 UInt16                                  recSize )
                    674: {
                    675:        UInt16          freeSpace;
                    676:        UInt16          indexOffset;
                    677:        UInt16          freeOffset;
                    678:        UInt16          bytesToMove;
                    679:        UInt8 *         src;
                    680:        UInt8 *         dst;
                    681:        UInt16          keySize;
                    682:        UInt16          rawKeyLength;
                    683:        UInt16          sizeOfLength;
                    684:        
                    685:        //// calculate actual key size
                    686: 
                    687:        if ( btreePtr->attributes & kBTBigKeysMask )
                    688:                keySize = keyLength + sizeof(UInt16);
                    689:        else
                    690:                keySize = keyLength + sizeof(UInt8);
                    691:        
                    692:        if ( M_IsOdd (keySize) )
                    693:                ++keySize;                      // add pad byte
                    694: 
                    695: 
                    696:        //// will new record fit in node?
                    697: 
                    698:        freeSpace = GetNodeFreeSize (btreePtr, node);
                    699:                                                                                        //�� we could get freeOffset & calc freeSpace
                    700:        if ( freeSpace < keySize + recSize + 2)
                    701:        {
                    702:                return false;
                    703:        }
                    704: 
                    705:        
                    706:        //// make hole for new record
                    707: 
                    708:        indexOffset = GetRecordOffset (btreePtr, node, index);
                    709:        freeOffset      = GetRecordOffset (btreePtr, node, node->numRecords);
                    710: 
                    711:        src = ((UInt8 *) node) + indexOffset;
                    712:        dst = ((UInt8 *) src) + keySize + recSize;
                    713:        bytesToMove = freeOffset - indexOffset;
                    714:        MoveRecordsRight (src, dst, bytesToMove);
                    715: 
                    716: 
                    717:        //// adjust offsets for moved records
                    718: 
                    719:        InsertOffset (btreePtr, node, index, keySize + recSize);
                    720:        
                    721: 
                    722:        //// copy record key
                    723: 
                    724:        dst = ((UInt8 *) node) + indexOffset;
                    725: 
                    726:        if ( btreePtr->attributes & kBTBigKeysMask )
                    727:        {
                    728:                *((UInt16*) dst)++ = keyLength;         // use keyLength rather than key.length
                    729:                rawKeyLength = keyPtr->length16;
                    730:                sizeOfLength = 2;
                    731:        }
                    732:        else
                    733:        {
                    734:                *dst++ = keyLength;                                     // use keyLength rather than key.length
                    735:                rawKeyLength = keyPtr->length8;
                    736:                sizeOfLength = 1;
                    737:        }
                    738:        
                    739:        MoveRecordsLeft ( ((UInt8 *) keyPtr) + sizeOfLength, dst, rawKeyLength);        // copy key
                    740: 
                    741:        // any pad bytes?
                    742:        bytesToMove = keySize - rawKeyLength;
                    743:        if (bytesToMove)
                    744:                ClearMemory (dst + rawKeyLength, bytesToMove);  // clear pad bytes in index key
                    745: 
                    746: 
                    747:        //// copy record data
                    748: 
                    749:        dst = ((UInt8 *) node) + indexOffset + keySize;
                    750:        MoveRecordsLeft (recPtr, dst, recSize);
                    751: 
                    752:        return true;
                    753: }
                    754: 
                    755: 
                    756: 
                    757: /*-------------------------------------------------------------------------------
                    758: 
                    759: Routine:       DeleteRecord    -       Deletes a record from a BTree node.
                    760: 
                    761: Function:      
                    762: 
                    763: Input:         btreePtr                - pointer to BTree control block
                    764:                        node                    - pointer to node to insert the record
                    765:                        index                   - position record is to be inserted
                    766: 
                    767: Result:                none
                    768: -------------------------------------------------------------------------------*/
                    769: 
                    770: void           DeleteRecord    (BTreeControlBlockPtr   btreePtr,
                    771:                                                         NodeDescPtr                    node,
                    772:                                                         UInt16                                 index )
                    773: {
                    774:        SInt16          indexOffset;
                    775:        SInt16          nextOffset;
                    776:        SInt16          freeOffset;
                    777:        SInt16          bytesToMove;
                    778:        void       *src;
                    779:        void       *dst;
                    780:        
                    781:        //// compress records
                    782:        indexOffset = GetRecordOffset (btreePtr, node, index);
                    783:        nextOffset      = GetRecordOffset (btreePtr, node, index + 1);
                    784:        freeOffset      = GetRecordOffset (btreePtr, node, node->numRecords);
                    785: 
                    786:        src = ((Ptr) node) + nextOffset;
                    787:        dst = ((Ptr) node) + indexOffset;
                    788:        bytesToMove = freeOffset - nextOffset;
                    789:        MoveRecordsLeft (src, dst, bytesToMove);
                    790: 
                    791:        //// Adjust the offsets
                    792:        DeleteOffset (btreePtr, node, index);
                    793:        
                    794:        /* clear out new free space */
                    795:        bytesToMove = nextOffset - indexOffset;
                    796:        ClearMemory(GetRecordAddress(btreePtr, node, node->numRecords), bytesToMove);
                    797: 
                    798: }
                    799: 
                    800: 
                    801: 
                    802: /*-------------------------------------------------------------------------------
                    803: 
                    804: Routine:       SearchNode      -       Return index for record that matches key.
                    805: 
                    806: Function:      Returns the record index for the record that matches the search key.
                    807:                        If no record was found that matches the search key, the "insert index"
                    808:                        of where the record should go is returned instead.
                    809: 
                    810: Algorithm:     A binary search algorithm is used to find the specified key.
                    811: 
                    812: Input:         btreePtr        - pointer to BTree control block
                    813:                        node            - pointer to node that contains the record
                    814:                        searchKey       - pointer to the key to match
                    815: 
                    816: Output:                index           - pointer to beginning of key for record
                    817: 
                    818: Result:                true    - success (index = record index)
                    819:                        false   - key did not match anything in node (index = insert index)
                    820: -------------------------------------------------------------------------------*/
                    821: Boolean
                    822: SearchNode( BTreeControlBlockPtr btreePtr,
                    823:            NodeDescPtr node,
                    824:            KeyPtr searchKey,
                    825:            UInt16 *returnIndex )
                    826: {
                    827:        SInt32          lowerBound;
                    828:        SInt32          upperBound;
                    829:        SInt32          index;
                    830:        SInt32          result;
                    831:        KeyPtr          trialKey;
                    832:        UInt16          *offset;
                    833:        KeyCompareProcPtr compareProc = btreePtr->keyCompareProc;
                    834: 
                    835:        lowerBound = 0;
                    836:        upperBound = node->numRecords - 1;
                    837:        offset = (UInt16 *) ((UInt8 *)(node) + (btreePtr)->nodeSize - kOffsetSize);
                    838:        
                    839:        while (lowerBound <= upperBound) {
                    840:                index = (lowerBound + upperBound) >> 1;
                    841: 
                    842:                trialKey = (KeyPtr) ((UInt8 *)node + *(offset - index));
                    843:                
                    844:                result = compareProc(searchKey, trialKey);
                    845: 
                    846:                if (result <  0) {
                    847:                        upperBound = index - 1;   /* search < trial */
                    848:                } else if (result >  0) {
                    849:                        lowerBound = index + 1;   /* search > trial */
                    850:                } else {        
                    851:                        *returnIndex = index;     /* search == trial */
                    852:                        return true;
                    853:                }
                    854:        }
                    855:        
                    856:        *returnIndex = lowerBound;      /* lowerBound is insert index */
                    857:        return false;
                    858: }
                    859: 
                    860: 
                    861: /*-------------------------------------------------------------------------------
                    862: 
                    863: Routine:       GetRecordByIndex        -       Return pointer to key and data, and size of data.
                    864: 
                    865: Function:      Returns a pointer to beginning of key for record, a pointer to the
                    866:                        beginning of the data for the record, and the size of the record data
                    867:                        (does not include the size of the key).
                    868: 
                    869: Input:         btreePtr        - pointer to BTree control block
                    870:                        node            - pointer to node that contains the record
                    871:                        index           - index of record to get
                    872: 
                    873: Output:                keyPtr          - pointer to beginning of key for record
                    874:                        dataPtr         - pointer to beginning of data for record
                    875:                        dataSize        - size of the data portion of the record
                    876: 
                    877: Result:                none
                    878: -------------------------------------------------------------------------------*/
                    879: 
                    880: OSStatus       GetRecordByIndex        (BTreeControlBlockPtr    btreePtr,
                    881:                                                                 NodeDescPtr                     node,
                    882:                                                                 UInt16                                  index,
                    883:                                                                 KeyPtr                                 *keyPtr,
                    884:                                                                 UInt8 *                                *dataPtr,
                    885:                                                                 UInt16                                 *dataSize )
                    886: {
                    887:        UInt16          offset;
                    888:        UInt16          nextOffset;
                    889:        UInt16          keySize;
                    890:        
                    891:        //
                    892:        //      Make sure index is valid (in range 0..numRecords-1)
                    893:        //
                    894:        if (index >= node->numRecords)
                    895:                return fsBTRecordNotFoundErr;
                    896: 
                    897:        //// find keyPtr
                    898:        offset          = GetRecordOffset (btreePtr, node, index);
                    899:        *keyPtr         = (KeyPtr) ((Ptr)node + offset);
                    900: 
                    901:        //// find dataPtr
                    902:        keySize = CalcKeySize(btreePtr, *keyPtr);
                    903:        if ( M_IsOdd (keySize) )
                    904:                ++keySize;      // add pad byte
                    905: 
                    906:        offset += keySize;                      // add the key length to find data offset
                    907:        *dataPtr = (UInt8 *) node + offset;
                    908:        
                    909:        //// find dataSize
                    910:        nextOffset      = GetRecordOffset (btreePtr, node, index + 1);
                    911:        *dataSize       = nextOffset - offset;
                    912:        
                    913:        return noErr;
                    914: }
                    915:                                                                 
                    916: 
                    917: 
                    918: /*-------------------------------------------------------------------------------
                    919: 
                    920: Routine:       GetNodeDataSize -       Return the amount of space used for data in the node.
                    921: 
                    922: Function:      Gets the size of the data currently contained in a node, excluding
                    923:                        the node header. (record data + offset overhead)
                    924: 
                    925: Input:         btreePtr                - pointer to BTree control block
                    926:                        node                    - pointer to node that contains the record
                    927: 
                    928: Result:                - number of bytes used for data and offsets in the node.
                    929: -------------------------------------------------------------------------------*/
                    930: 
                    931: UInt16         GetNodeDataSize (BTreeControlBlockPtr   btreePtr, NodeDescPtr    node )
                    932: {
                    933:        UInt16 freeOffset;
                    934:        
                    935:        freeOffset = GetRecordOffset (btreePtr, node, node->numRecords);
                    936:        
                    937:        return  freeOffset + (node->numRecords << 1) - sizeof (BTNodeDescriptor);
                    938: }
                    939: 
                    940: 
                    941: 
                    942: /*-------------------------------------------------------------------------------
                    943: 
                    944: Routine:       GetNodeFreeSize -       Return the amount of free space in the node.
                    945: 
                    946: Function:      
                    947: 
                    948: Input:         btreePtr                - pointer to BTree control block
                    949:                        node                    - pointer to node that contains the record
                    950: 
                    951: Result:                - number of bytes of free space in the node.
                    952: -------------------------------------------------------------------------------*/
                    953: 
                    954: UInt16         GetNodeFreeSize (BTreeControlBlockPtr   btreePtr, NodeDescPtr    node )
                    955: {
                    956:        UInt16  freeOffset;
                    957:        
                    958:        freeOffset = GetRecordOffset (btreePtr, node, node->numRecords);        //�� inline?
                    959:        
                    960:        return btreePtr->nodeSize - freeOffset - (node->numRecords << 1) - kOffsetSize;
                    961: }
                    962: 
                    963: 
                    964: 
                    965: /*-------------------------------------------------------------------------------
                    966: 
                    967: Routine:       GetRecordOffset -       Return the offset for record "index".
                    968: 
                    969: Function:      
                    970: 
                    971: Input:         btreePtr                - pointer to BTree control block
                    972:                        node                    - pointer to node that contains the record
                    973:                        index                   - record to obtain offset for
                    974: 
                    975: Result:                - offset (in bytes) from beginning of node of record specified by index
                    976: -------------------------------------------------------------------------------*/
                    977: // make this a macro (for inlining)
                    978: #if 0
                    979: UInt16         GetRecordOffset (BTreeControlBlockPtr   btreePtr,
                    980:                                                         NodeDescPtr                    node,
                    981:                                                         UInt16                                 index )
                    982: {
                    983:        void    *pos;
                    984:        
                    985:                
                    986:        pos = (UInt8 *)node + btreePtr->nodeSize - (index << 1) - kOffsetSize;
                    987:        
                    988:        return *(short *)pos;
                    989: }
                    990: #endif
                    991: 
                    992: 
                    993: 
                    994: /*-------------------------------------------------------------------------------
                    995: 
                    996: Routine:       GetRecordAddress        -       Return address of 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 address for
                   1003: 
                   1004: Result:                - pointer to record "index".
                   1005: -------------------------------------------------------------------------------*/
                   1006: // make this a macro (for inlining)
                   1007: #if 0
                   1008: UInt8 *                GetRecordAddress        (BTreeControlBlockPtr   btreePtr,
                   1009:                                                                 NodeDescPtr                    node,
                   1010:                                                                 UInt16                                 index )
                   1011: {
                   1012:        UInt8 *         pos;
                   1013:        
                   1014:        pos = (UInt8 *)node + GetRecordOffset (btreePtr, node, index);
                   1015:        
                   1016:        return pos;
                   1017: }
                   1018: #endif
                   1019: 
                   1020: 
                   1021: 
                   1022: /*-------------------------------------------------------------------------------
                   1023: 
                   1024: Routine:       GetRecordSize   -       Return size of record "index".
                   1025: 
                   1026: Function:      
                   1027: 
                   1028: Note:          This does not work on the FreeSpace index!
                   1029: 
                   1030: Input:         btreePtr                - pointer to BTree control block
                   1031:                        node                    - pointer to node that contains the record
                   1032:                        index                   - record to obtain record size for
                   1033: 
                   1034: Result:                - size of record "index".
                   1035: -------------------------------------------------------------------------------*/
                   1036: 
                   1037: UInt16         GetRecordSize           (BTreeControlBlockPtr   btreePtr,
                   1038:                                                                 NodeDescPtr                    node,
                   1039:                                                                 UInt16                                 index )
                   1040: {
                   1041:        UInt16  *pos;
                   1042:                
                   1043:        pos = (UInt16 *) ((Ptr)node + btreePtr->nodeSize - (index << 1) - kOffsetSize);
                   1044:        
                   1045:        return  *(pos-1) - *pos;
                   1046: }
                   1047: 
                   1048: 
                   1049: 
                   1050: /*-------------------------------------------------------------------------------
                   1051: Routine:       GetOffsetAddress        -       Return address of offset for record "index".
                   1052: 
                   1053: Function:      
                   1054: 
                   1055: Input:         btreePtr                - pointer to BTree control block
                   1056:                        node                    - pointer to node that contains the record
                   1057:                        index                   - record to obtain offset address for
                   1058: 
                   1059: Result:                - pointer to offset for record "index".
                   1060: -------------------------------------------------------------------------------*/
                   1061: 
                   1062: UInt16    *GetOffsetAddress    (BTreeControlBlockPtr   btreePtr,
                   1063:                                                                 NodeDescPtr                    node,
                   1064:                                                                 UInt16                                 index )
                   1065: {
                   1066:        void    *pos;
                   1067:        
                   1068:        pos = (Ptr)node + btreePtr->nodeSize - (index << 1) -2;
                   1069:        
                   1070:        return (UInt16 *)pos;
                   1071: }
                   1072: 
                   1073: 
                   1074: 
                   1075: /*-------------------------------------------------------------------------------
                   1076: Routine:       GetChildNodeNum -       Return child node number from index record "index".
                   1077: 
                   1078: Function:      Returns the first UInt32 stored after the key for record "index".
                   1079: 
                   1080: Assumes:       The node is an Index Node.
                   1081:                        The key.length stored at record "index" is ODD. //�� change for variable length index keys
                   1082: 
                   1083: Input:         btreePtr                - pointer to BTree control block
                   1084:                        node                    - pointer to node that contains the record
                   1085:                        index                   - record to obtain child node number from
                   1086: 
                   1087: Result:                - child node number from record "index".
                   1088: -------------------------------------------------------------------------------*/
                   1089: 
                   1090: UInt32         GetChildNodeNum                 (BTreeControlBlockPtr    btreePtr,
                   1091:                                                                         NodeDescPtr                     nodePtr,
                   1092:                                                                         UInt16                                  index )
                   1093: {
                   1094:        UInt8 *         pos;
                   1095:        
                   1096:        pos = GetRecordAddress (btreePtr, nodePtr, index);
                   1097:        pos += CalcKeySize(btreePtr, (BTreeKey *) pos);         // key.length + size of length field
                   1098:        
                   1099:        return  *(UInt32 *)pos;
                   1100: }
                   1101: 
                   1102: 
                   1103: 
                   1104: /*-------------------------------------------------------------------------------
                   1105: Routine:       InsertOffset    -       Add an offset and adjust existing offsets by delta.
                   1106: 
                   1107: Function:      Add an offset at 'index' by shifting 'index+1' through the last offset
                   1108:                        and adjusting them by 'delta', the size of the record to be inserted.
                   1109:                        The number of records contained in the node is also incremented.
                   1110: 
                   1111: Input:         btreePtr        - pointer to BTree control block
                   1112:                        node            - pointer to node
                   1113:                        index           - index at which to insert record
                   1114:                        delta           - size of record to be inserted
                   1115: 
                   1116: Result:                none
                   1117: -------------------------------------------------------------------------------*/
                   1118: 
                   1119: void           InsertOffset            (BTreeControlBlockPtr    btreePtr,
                   1120:                                                                 NodeDescPtr                     node,
                   1121:                                                                 UInt16                                  index,
                   1122:                                                                 UInt16                                  delta )
                   1123: {
                   1124:        UInt16          *src, *dst;
                   1125:        UInt16           numOffsets;
                   1126:        
                   1127:        src = GetOffsetAddress (btreePtr, node, node->numRecords);      // point to free offset
                   1128:        dst = src - 1;                                                                                          // point to new offset
                   1129:        numOffsets = node->numRecords++ - index;                        // subtract index  & postincrement
                   1130:        
                   1131:        do {
                   1132:                *dst++ = *src++ + delta;                                                                // to tricky?
                   1133:        } while (numOffsets--);
                   1134: }
                   1135: 
                   1136: 
                   1137: 
                   1138: /*-------------------------------------------------------------------------------
                   1139: 
                   1140: Routine:       DeleteOffset    -       Delete an offset.
                   1141: 
                   1142: Function:      Delete the offset at 'index' by shifting 'index+1' through the last offset
                   1143:                        and adjusting them by the size of the record 'index'.
                   1144:                        The number of records contained in the node is also decremented.
                   1145: 
                   1146: Input:         btreePtr        - pointer to BTree control block
                   1147:                        node            - pointer to node
                   1148:                        index           - index at which to delete record
                   1149: 
                   1150: Result:                none
                   1151: -------------------------------------------------------------------------------*/
                   1152: 
                   1153: void           DeleteOffset            (BTreeControlBlockPtr    btreePtr,
                   1154:                                                                 NodeDescPtr                     node,
                   1155:                                                                 UInt16                                  index )
                   1156: {
                   1157:        UInt16          *src, *dst;
                   1158:        UInt16           numOffsets;
                   1159:        UInt16           delta;
                   1160:        
                   1161:        dst                     = GetOffsetAddress (btreePtr, node, index);
                   1162:        src                     = dst - 1;
                   1163:        delta           = *src - *dst;
                   1164:        numOffsets      = --node->numRecords - index;   // predecrement numRecords & subtract index
                   1165:        
                   1166:        while (numOffsets--)
                   1167:        {
                   1168:                *--dst = *--src - delta;                                // work our way left
                   1169:        }
                   1170: }
                   1171: 
                   1172: 
                   1173: 
                   1174: /*-------------------------------------------------------------------------------
                   1175: 
                   1176: Routine:       MoveRecordsLeft -       Move records left within a node.
                   1177: 
                   1178: Function:      Moves a number of bytes from src to dst. Safely handles overlapping
                   1179:                        ranges if the bytes are being moved to the "left". No bytes are moved
                   1180:                        if bytesToMove is zero.
                   1181: 
                   1182: Input:         src                             - pointer to source
                   1183:                        dst                             - pointer to destination
                   1184:                        bytesToMove             - number of bytes to move records
                   1185: 
                   1186: Result:                none
                   1187: -------------------------------------------------------------------------------*/
                   1188: #if BCOPY_BROKEN
                   1189: void           MoveRecordsLeft         (UInt8 *                                 src,
                   1190:                                                                 UInt8 *                                 dst,
                   1191:                                                                 UInt16                                  bytesToMove )
                   1192: {
                   1193:        while (bytesToMove--)
                   1194:                *dst++ = *src++;
                   1195: }
                   1196: #endif                                                  
                   1197: 
                   1198: 
                   1199: /*-------------------------------------------------------------------------------
                   1200: 
                   1201: Routine:       MoveRecordsRight        -       Move records right within a node.
                   1202: 
                   1203: Function:      Moves a number of bytes from src to dst. Safely handles overlapping
                   1204:                        ranges if the bytes are being moved to the "right". No bytes are moved
                   1205:                        if bytesToMove is zero.
                   1206: 
                   1207: Input:         src                             - pointer to source
                   1208:                        dst                             - pointer to destination
                   1209:                        bytesToMove             - number of bytes to move records
                   1210:                        
                   1211: Result:                none
                   1212: -------------------------------------------------------------------------------*/
                   1213: #if BCOPY_BROKEN
                   1214: void           MoveRecordsRight        (UInt8 *                                 src,
                   1215:                                                                 UInt8 *                                 dst,
                   1216:                                                                 UInt16                                  bytesToMove )
                   1217: {
                   1218:        src += bytesToMove;
                   1219:        dst += bytesToMove;
                   1220:        
                   1221:        while (bytesToMove--)
                   1222:                *--dst = *--src;
                   1223: }
                   1224: #endif

unix.superglobalmegacorp.com

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