2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
33 Contains: Single-node operations for the BTree Module.
35 Version: xxx put the technology version here xxx
37 Written by: Gordon Sheridan and Bill Bruffey
39 Copyright: © 1992-1999 by Apple Computer, Inc., all rights reserved.
45 Other Contact: Mark Day
47 Technology: File Systems
54 Change History (most recent first):
56 <MOSXS> 6/1/99 djb Sync up with Mac OS 8.6.
57 <MOSXS> 4/113/99 djb Fix key size checking bug in CheckNode.
58 <MOSXS> 3/19/99 djb Added key size checking to CheckNode.
59 <MOSXS> 3/26/98 djb Added PrintNode for debugging.
60 <CS5> 9/4/97 djb Removed GetRightSiblingNode and GetLeftSiblingNode - they are
61 now macros. SearchNode is now in BTreeSearchNode.a.
62 <CS4> 8/22/97 djb Turn off debugging code in CheckKey.
63 <CS3> 7/24/97 djb Add summary traces for Get/Rel Node. Made GetRecordOffset into a
64 macro. Only call CheckNode if the node came from disk.
65 <CS2> 7/21/97 msd Make GetRecordByIndex check its record index input; it now
67 <CS1> 4/23/97 djb first checked in
69 <HFS3> 2/19/97 djb Changes to support big node cache.
70 <HFS2> 1/3/97 djb Added support for large keys.
71 <HFS1> 12/19/96 djb first checked in
74 History applicable to original Scarecrow Design:
76 <6> 10/25/96 ser Changing for new VFPI
77 <5> 9/17/96 dkh Add bounds checking to GetNode. Update GetNode to not assert
78 that CheckNode failed if the node is all zeroes. This can happen
79 if the hint case if the fetched node has been deallocated
80 <4> 3/7/96 dkh Change GetNewNode() to not use kGetEmptyBlock. Instead use
81 kGetBlock to fetch a block from the disk itself. \80\80\80 Why?
82 <3> 1/22/96 dkh Add #include Memory.h
83 <2> 1/10/96 msd Change 64-bit math to use real function names from Math64.i.
84 <1> 10/18/95 rst Moved from Scarecrow project.
86 <17> 7/18/95 mbb Change MoveData & ClearBytes to BlockMoveData & BlockZero.
87 <16> 1/31/95 prp GetBlockProc interface uses a 64 bit node number.
88 <15> 1/12/95 wjk Adopt Model FileSystem changes in D5.
89 <14> 9/30/94 prp Get in sync with D2 interface changes.
90 <13> 7/25/94 wjk Eliminate usage of BytePtr in favor of UInt8 *.
91 <12> 7/22/94 wjk Convert to the new set of header files.
92 <11> 12/2/93 wjk Move from Makefiles to BuildFiles. Fit into the ModernOS and
94 <10> 11/30/93 wjk Change some Ptr's to BytePtr's in function definitions so they
95 agree with their prototypes.
96 <9> 8/31/93 prp Use U64SetU instead of S64Set.
97 <8> 5/21/93 gs Maintain statistical counters on Get/Release node routines.
98 <7> 5/10/93 gs Change keySize parameter to keyLength for InsertKeyRecord
99 routine. Calculate number of bytes in key from keyLength to
100 account for length and pad bytes. Add GetChildNodeNum routine.
101 <6> 3/23/93 gs Add InsertKeyRecord routine.
102 <5> 2/8/93 gs Fix bug in SearchNode that caused "off by 1" error when final
103 compare was searchKey > trialKey. Add UpdateNode.
104 <4> 12/10/92 gs Change keyLength field of key to 'length'.
105 <3> 12/8/92 gs Incorporate suggestions from preliminary code review.
106 <2> 12/2/92 gs Implement routines.
107 <1> 11/15/92 gs Define routine interfaces.
111 #include "../headers/BTreesPrivate.h"
115 ///////////////////////// BTree Module Node Operations //////////////////////////
117 // GetNode - Call FS Agent to get node
118 // GetNewNode - Call FS Agent to get a new node
119 // ReleaseNode - Call FS Agent to release node obtained by GetNode.
120 // UpdateNode - Mark a node as dirty and call FS Agent to release it.
122 // ClearNode - Clear a node to all zeroes.
124 // InsertRecord - Inserts a record into a BTree node.
125 // InsertKeyRecord - Inserts a key and record pair into a BTree node.
126 // DeleteRecord - Deletes a record from a BTree node.
128 // SearchNode - Return index for record that matches key.
129 // LocateRecord - Return pointer to key and data, and size of data.
131 // GetNodeDataSize - Return the amount of space used for data in the node.
132 // GetNodeFreeSize - Return the amount of free space in the node.
134 // GetRecordOffset - Return the offset for record "index".
135 // GetRecordAddress - Return address of record "index".
136 // GetOffsetAddress - Return address of offset for record "index".
138 // InsertOffset - Inserts a new offset into a node.
139 // DeleteOffset - Deletes an offset from a node.
141 /////////////////////////////////////////////////////////////////////////////////
145 ////////////////////// Routines Internal To BTreeNodeOps.c //////////////////////
147 UInt16
GetRecordOffset (BTreeControlBlockPtr btree
,
151 UInt16
*GetOffsetAddress (BTreeControlBlockPtr btreePtr
,
155 void InsertOffset (BTreeControlBlockPtr btreePtr
,
160 void DeleteOffset (BTreeControlBlockPtr btreePtr
,
165 /////////////////////////////////////////////////////////////////////////////////
167 #define GetRecordOffset(btreePtr,node,index) (*(short *) ((UInt8 *)(node) + (btreePtr)->nodeSize - ((index) << 1) - kOffsetSize))
170 #include <sys/systm.h>
171 #define PRINTIT kprintf
172 #endif /* HFS_DIAGNOSTIC */
174 static void PrintNode(const NodeDescPtr node
, UInt16 nodeSize
, UInt32 nodeNumber
);
178 /*-------------------------------------------------------------------------------
180 Routine: GetNode - Call FS Agent to get node
182 Function: Gets an existing BTree node from FS Agent and verifies it.
184 Input: btreePtr - pointer to BTree control block
185 nodeNum - number of node to request
187 Output: nodePtr - pointer to beginning of node (nil if error)
192 -------------------------------------------------------------------------------*/
194 OSStatus
GetNode (BTreeControlBlockPtr btreePtr
,
199 GetBlockProcPtr getNodeProc
;
202 //\80\80 is nodeNum within proper range?
203 if( nodeNum
>= btreePtr
->totalNodes
)
205 Panic("\pGetNode:nodeNum >= totalNodes");
206 err
= fsBTInvalidNodeErr
;
210 nodePtr
->blockSize
= btreePtr
->nodeSize
; // indicate the size of a node
212 getNodeProc
= btreePtr
->getBlockProc
;
213 err
= getNodeProc (btreePtr
->fileRefNum
,
220 Panic ("\pGetNode: getNodeProc returned error.");
221 // nodePtr->buffer = nil;
224 ++btreePtr
->numGetNodes
;
229 nodePtr
->buffer
= nil
;
230 nodePtr
->blockHeader
= nil
;
237 /*-------------------------------------------------------------------------------
239 Routine: GetNewNode - Call FS Agent to get a new node
241 Function: Gets a new BTree node from FS Agent and initializes it to an empty
244 Input: btreePtr - pointer to BTree control block
245 nodeNum - number of node to request
247 Output: returnNodePtr - pointer to beginning of node (nil if error)
249 Result: noErr - success
251 -------------------------------------------------------------------------------*/
253 OSStatus
GetNewNode (BTreeControlBlockPtr btreePtr
,
255 NodeRec
*returnNodePtr
)
260 GetBlockProcPtr getNodeProc
;
263 //////////////////////// get buffer for new node ////////////////////////////
265 returnNodePtr
->blockSize
= btreePtr
->nodeSize
; // indicate the size of a node
267 getNodeProc
= btreePtr
->getBlockProc
;
268 err
= getNodeProc (btreePtr
->fileRefNum
,
270 kGetBlock
+kGetEmptyBlock
,
275 Panic ("\pGetNewNode: getNodeProc returned error.");
276 // returnNodePtr->buffer = nil;
279 ++btreePtr
->numGetNewNodes
;
282 ////////////////////////// initialize the node //////////////////////////////
284 node
= returnNodePtr
->buffer
;
286 ClearNode (btreePtr
, node
); // clear the node
288 pos
= (char *)node
+ btreePtr
->nodeSize
- 2; // find address of last offset
289 *(UInt16
*)pos
= sizeof (BTNodeDescriptor
); // set offset to beginning of free space
297 /*-------------------------------------------------------------------------------
299 Routine: ReleaseNode - Call FS Agent to release node obtained by GetNode.
301 Function: Informs the FS Agent that a BTree node may be released.
303 Input: btreePtr - pointer to BTree control block
304 nodeNum - number of node to release
306 Result: noErr - success
308 -------------------------------------------------------------------------------*/
310 OSStatus
ReleaseNode (BTreeControlBlockPtr btreePtr
,
314 ReleaseBlockProcPtr releaseNodeProc
;
319 if (nodePtr
->buffer
!= nil
)
321 releaseNodeProc
= btreePtr
->releaseBlockProc
;
322 err
= releaseNodeProc (btreePtr
->fileRefNum
,
325 PanicIf (err
, "\pReleaseNode: releaseNodeProc returned error.");
326 ++btreePtr
->numReleaseNodes
;
329 nodePtr
->buffer
= nil
;
330 nodePtr
->blockHeader
= nil
;
338 /*-------------------------------------------------------------------------------
340 Routine: TrashNode - Call FS Agent to release node obtained by GetNode, and
341 not store it...mark it as bad.
343 Function: Informs the FS Agent that a BTree node may be released and thrown away.
345 Input: btreePtr - pointer to BTree control block
346 nodeNum - number of node to release
348 Result: noErr - success
350 -------------------------------------------------------------------------------*/
352 OSStatus
TrashNode (BTreeControlBlockPtr btreePtr
,
356 ReleaseBlockProcPtr releaseNodeProc
;
361 if (nodePtr
->buffer
!= nil
)
363 releaseNodeProc
= btreePtr
->releaseBlockProc
;
364 err
= releaseNodeProc (btreePtr
->fileRefNum
,
366 kReleaseBlock
| kTrashBlock
);
367 PanicIf (err
, "\TrashNode: releaseNodeProc returned error.");
368 ++btreePtr
->numReleaseNodes
;
371 nodePtr
->buffer
= nil
;
372 nodePtr
->blockHeader
= nil
;
379 /*-------------------------------------------------------------------------------
381 Routine: UpdateNode - Mark a node as dirty and call FS Agent to release it.
383 Function: Marks a BTree node dirty and informs the FS Agent that it may be released.
385 Input: btreePtr - pointer to BTree control block
386 nodeNum - number of node to release
387 transactionID - ID of transaction this node update is a part of
388 flags - special flags to pass to ReleaseNodeProc
390 Result: noErr - success
392 -------------------------------------------------------------------------------*/
394 OSStatus
UpdateNode (BTreeControlBlockPtr btreePtr
,
396 UInt32 transactionID
,
400 ReleaseBlockProcPtr releaseNodeProc
;
405 if (nodePtr
->buffer
!= nil
) // Why call UpdateNode if nil ?!?
407 releaseNodeProc
= btreePtr
->releaseBlockProc
;
408 err
= releaseNodeProc (btreePtr
->fileRefNum
,
410 flags
| kMarkBlockDirty
);
411 ++btreePtr
->numUpdateNodes
;
415 nodePtr
->buffer
= nil
;
416 nodePtr
->blockHeader
= nil
;
428 static void PrintNode(const NodeDescPtr node
, UInt16 nodeSize
, UInt32 nodeNumber
)
437 PRINTIT("Dump of B-tree node #%ld ($%08lX)\n", nodeNumber
, nodeNumber
);
444 PRINTIT("%04X: %08lX %08lX %08lX %08lX\n", (u_int
)offset
++, *lp
++, *lp
++, *lp
++, *lp
++);
449 /*-------------------------------------------------------------------------------
451 Routine: ClearNode - Clear a node to all zeroes.
453 Function: Writes zeroes from beginning of node for nodeSize bytes.
455 Input: btreePtr - pointer to BTree control block
456 node - pointer to node to clear
459 -------------------------------------------------------------------------------*/
461 void ClearNode (BTreeControlBlockPtr btreePtr
, NodeDescPtr node
)
463 ClearMemory( node
, btreePtr
->nodeSize
);
466 /*-------------------------------------------------------------------------------
468 Routine: InsertRecord - Inserts a record into a BTree node.
472 Note: Record size must be even!
474 Input: btreePtr - pointer to BTree control block
475 node - pointer to node to insert the record
476 index - position record is to be inserted
477 recPtr - pointer to record to insert
479 Result: noErr - success
480 fsBTFullErr - record larger than remaining free space.
481 -------------------------------------------------------------------------------*/
483 Boolean
InsertRecord (BTreeControlBlockPtr btreePtr
,
496 //// will new record fit in node?
498 freeSpace
= GetNodeFreeSize (btreePtr
, node
);
499 //\80\80 we could get freeOffset & calc freeSpace
500 if ( freeSpace
< recSize
+ 2)
506 //// make hole for new record
508 indexOffset
= GetRecordOffset (btreePtr
, node
, index
);
509 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
511 src
= ((Ptr
) node
) + indexOffset
;
512 dst
= ((Ptr
) src
) + recSize
;
513 bytesToMove
= freeOffset
- indexOffset
;
515 MoveRecordsRight (src
, dst
, bytesToMove
);
518 //// adjust offsets for moved records
520 InsertOffset (btreePtr
, node
, index
, recSize
);
523 //// move in the new record
525 dst
= ((Ptr
) node
) + indexOffset
;
526 MoveRecordsLeft (recPtr
, dst
, recSize
);
533 /*-------------------------------------------------------------------------------
535 Routine: InsertKeyRecord - Inserts a record into a BTree node.
539 Note: Record size must be even!
541 Input: btreePtr - pointer to BTree control block
542 node - pointer to node to insert the record
543 index - position record is to be inserted
544 keyPtr - pointer to key for record to insert
545 keyLength - length of key (or maxKeyLength)
546 recPtr - pointer to record to insert
547 recSize - number of bytes to copy for record
549 Result: noErr - success
550 fsBTFullErr - record larger than remaining free space.
551 -------------------------------------------------------------------------------*/
553 Boolean
InsertKeyRecord (BTreeControlBlockPtr btreePtr
,
571 //// calculate actual key size
573 if ( btreePtr
->attributes
& kBTBigKeysMask
)
574 keySize
= keyLength
+ sizeof(UInt16
);
576 keySize
= keyLength
+ sizeof(UInt8
);
578 if ( M_IsOdd (keySize
) )
579 ++keySize
; // add pad byte
582 //// will new record fit in node?
584 freeSpace
= GetNodeFreeSize (btreePtr
, node
);
585 //\80\80 we could get freeOffset & calc freeSpace
586 if ( freeSpace
< keySize
+ recSize
+ 2)
592 //// make hole for new record
594 indexOffset
= GetRecordOffset (btreePtr
, node
, index
);
595 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
597 src
= ((UInt8
*) node
) + indexOffset
;
598 dst
= ((UInt8
*) src
) + keySize
+ recSize
;
599 bytesToMove
= freeOffset
- indexOffset
;
601 MoveRecordsRight (src
, dst
, bytesToMove
);
604 //// adjust offsets for moved records
606 InsertOffset (btreePtr
, node
, index
, keySize
+ recSize
);
611 dst
= ((UInt8
*) node
) + indexOffset
;
613 if ( btreePtr
->attributes
& kBTBigKeysMask
)
615 *((UInt16
*) dst
)++ = keyLength
; // use keyLength rather than key.length
616 rawKeyLength
= keyPtr
->length16
;
621 *dst
++ = keyLength
; // use keyLength rather than key.length
622 rawKeyLength
= keyPtr
->length8
;
626 MoveRecordsLeft ( ((UInt8
*) keyPtr
) + sizeOfLength
, dst
, rawKeyLength
); // copy key
629 bytesToMove
= keySize
- rawKeyLength
;
631 ClearMemory (dst
+ rawKeyLength
, bytesToMove
); // clear pad bytes in index key
634 //// copy record data
636 dst
= ((UInt8
*) node
) + indexOffset
+ keySize
;
637 MoveRecordsLeft (recPtr
, dst
, recSize
);
644 /*-------------------------------------------------------------------------------
646 Routine: DeleteRecord - Deletes a record from a BTree node.
650 Input: btreePtr - pointer to BTree control block
651 node - pointer to node to insert the record
652 index - position record is to be inserted
655 -------------------------------------------------------------------------------*/
657 void DeleteRecord (BTreeControlBlockPtr btreePtr
,
668 //// compress records
669 indexOffset
= GetRecordOffset (btreePtr
, node
, index
);
670 nextOffset
= GetRecordOffset (btreePtr
, node
, index
+ 1);
671 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
673 src
= ((Ptr
) node
) + nextOffset
;
674 dst
= ((Ptr
) node
) + indexOffset
;
675 bytesToMove
= freeOffset
- nextOffset
;
677 MoveRecordsLeft (src
, dst
, bytesToMove
);
679 //// Adjust the offsets
680 DeleteOffset (btreePtr
, node
, index
);
682 /* clear out new free space */
683 bytesToMove
= nextOffset
- indexOffset
;
684 ClearMemory(GetRecordAddress(btreePtr
, node
, node
->numRecords
), bytesToMove
);
690 /*-------------------------------------------------------------------------------
692 Routine: SearchNode - Return index for record that matches key.
694 Function: Returns the record index for the record that matches the search key.
695 If no record was found that matches the search key, the "insert index"
696 of where the record should go is returned instead.
698 Algorithm: A binary search algorithm is used to find the specified key.
700 Input: btreePtr - pointer to BTree control block
701 node - pointer to node that contains the record
702 searchKey - pointer to the key to match
704 Output: index - pointer to beginning of key for record
706 Result: true - success (index = record index)
707 false - key did not match anything in node (index = insert index)
708 -------------------------------------------------------------------------------*/
710 SearchNode( BTreeControlBlockPtr btreePtr
,
713 UInt16
*returnIndex
)
721 KeyCompareProcPtr compareProc
= btreePtr
->keyCompareProc
;
724 upperBound
= node
->numRecords
- 1;
725 offset
= (UInt16
*) ((UInt8
*)(node
) + (btreePtr
)->nodeSize
- kOffsetSize
);
727 while (lowerBound
<= upperBound
) {
728 index
= (lowerBound
+ upperBound
) >> 1;
730 trialKey
= (KeyPtr
) ((UInt8
*)node
+ *(offset
- index
));
732 result
= compareProc(searchKey
, trialKey
);
735 upperBound
= index
- 1; /* search < trial */
736 } else if (result
> 0) {
737 lowerBound
= index
+ 1; /* search > trial */
739 *returnIndex
= index
; /* search == trial */
744 *returnIndex
= lowerBound
; /* lowerBound is insert index */
749 /*-------------------------------------------------------------------------------
751 Routine: GetRecordByIndex - Return pointer to key and data, and size of data.
753 Function: Returns a pointer to beginning of key for record, a pointer to the
754 beginning of the data for the record, and the size of the record data
755 (does not include the size of the key).
757 Input: btreePtr - pointer to BTree control block
758 node - pointer to node that contains the record
759 index - index of record to get
761 Output: keyPtr - pointer to beginning of key for record
762 dataPtr - pointer to beginning of data for record
763 dataSize - size of the data portion of the record
766 -------------------------------------------------------------------------------*/
768 OSStatus
GetRecordByIndex (BTreeControlBlockPtr btreePtr
,
780 // Make sure index is valid (in range 0..numRecords-1)
782 if (index
>= node
->numRecords
)
783 return fsBTRecordNotFoundErr
;
786 offset
= GetRecordOffset (btreePtr
, node
, index
);
787 *keyPtr
= (KeyPtr
) ((Ptr
)node
+ offset
);
790 keySize
= CalcKeySize(btreePtr
, *keyPtr
);
791 if ( M_IsOdd (keySize
) )
792 ++keySize
; // add pad byte
794 offset
+= keySize
; // add the key length to find data offset
795 *dataPtr
= (UInt8
*) node
+ offset
;
798 nextOffset
= GetRecordOffset (btreePtr
, node
, index
+ 1);
799 *dataSize
= nextOffset
- offset
;
806 /*-------------------------------------------------------------------------------
808 Routine: GetNodeDataSize - Return the amount of space used for data in the node.
810 Function: Gets the size of the data currently contained in a node, excluding
811 the node header. (record data + offset overhead)
813 Input: btreePtr - pointer to BTree control block
814 node - pointer to node that contains the record
816 Result: - number of bytes used for data and offsets in the node.
817 -------------------------------------------------------------------------------*/
819 UInt16
GetNodeDataSize (BTreeControlBlockPtr btreePtr
, NodeDescPtr node
)
823 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
825 return freeOffset
+ (node
->numRecords
<< 1) - sizeof (BTNodeDescriptor
);
830 /*-------------------------------------------------------------------------------
832 Routine: GetNodeFreeSize - Return the amount of free space in the node.
836 Input: btreePtr - pointer to BTree control block
837 node - pointer to node that contains the record
839 Result: - number of bytes of free space in the node.
840 -------------------------------------------------------------------------------*/
842 UInt16
GetNodeFreeSize (BTreeControlBlockPtr btreePtr
, NodeDescPtr node
)
846 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
); //\80\80 inline?
848 return btreePtr
->nodeSize
- freeOffset
- (node
->numRecords
<< 1) - kOffsetSize
;
853 /*-------------------------------------------------------------------------------
855 Routine: GetRecordOffset - Return the offset for record "index".
859 Input: btreePtr - pointer to BTree control block
860 node - pointer to node that contains the record
861 index - record to obtain offset for
863 Result: - offset (in bytes) from beginning of node of record specified by index
864 -------------------------------------------------------------------------------*/
865 // make this a macro (for inlining)
867 UInt16
GetRecordOffset (BTreeControlBlockPtr btreePtr
,
874 pos
= (UInt8
*)node
+ btreePtr
->nodeSize
- (index
<< 1) - kOffsetSize
;
876 return *(short *)pos
;
882 /*-------------------------------------------------------------------------------
884 Routine: GetRecordAddress - Return address of record "index".
888 Input: btreePtr - pointer to BTree control block
889 node - pointer to node that contains the record
890 index - record to obtain offset address for
892 Result: - pointer to record "index".
893 -------------------------------------------------------------------------------*/
894 // make this a macro (for inlining)
896 UInt8
* GetRecordAddress (BTreeControlBlockPtr btreePtr
,
902 pos
= (UInt8
*)node
+ GetRecordOffset (btreePtr
, node
, index
);
910 /*-------------------------------------------------------------------------------
912 Routine: GetRecordSize - Return size of record "index".
916 Note: This does not work on the FreeSpace index!
918 Input: btreePtr - pointer to BTree control block
919 node - pointer to node that contains the record
920 index - record to obtain record size for
922 Result: - size of record "index".
923 -------------------------------------------------------------------------------*/
925 UInt16
GetRecordSize (BTreeControlBlockPtr btreePtr
,
931 pos
= (UInt16
*) ((Ptr
)node
+ btreePtr
->nodeSize
- (index
<< 1) - kOffsetSize
);
933 return *(pos
-1) - *pos
;
938 /*-------------------------------------------------------------------------------
939 Routine: GetOffsetAddress - Return address of offset for record "index".
943 Input: btreePtr - pointer to BTree control block
944 node - pointer to node that contains the record
945 index - record to obtain offset address for
947 Result: - pointer to offset for record "index".
948 -------------------------------------------------------------------------------*/
950 UInt16
*GetOffsetAddress (BTreeControlBlockPtr btreePtr
,
956 pos
= (Ptr
)node
+ btreePtr
->nodeSize
- (index
<< 1) -2;
958 return (UInt16
*)pos
;
963 /*-------------------------------------------------------------------------------
964 Routine: GetChildNodeNum - Return child node number from index record "index".
966 Function: Returns the first UInt32 stored after the key for record "index".
968 Assumes: The node is an Index Node.
969 The key.length stored at record "index" is ODD. //\80\80 change for variable length index keys
971 Input: btreePtr - pointer to BTree control block
972 node - pointer to node that contains the record
973 index - record to obtain child node number from
975 Result: - child node number from record "index".
976 -------------------------------------------------------------------------------*/
978 UInt32
GetChildNodeNum (BTreeControlBlockPtr btreePtr
,
984 pos
= GetRecordAddress (btreePtr
, nodePtr
, index
);
985 pos
+= CalcKeySize(btreePtr
, (BTreeKey
*) pos
); // key.length + size of length field
987 return *(UInt32
*)pos
;
992 /*-------------------------------------------------------------------------------
993 Routine: InsertOffset - Add an offset and adjust existing offsets by delta.
995 Function: Add an offset at 'index' by shifting 'index+1' through the last offset
996 and adjusting them by 'delta', the size of the record to be inserted.
997 The number of records contained in the node is also incremented.
999 Input: btreePtr - pointer to BTree control block
1000 node - pointer to node
1001 index - index at which to insert record
1002 delta - size of record to be inserted
1005 -------------------------------------------------------------------------------*/
1007 void InsertOffset (BTreeControlBlockPtr btreePtr
,
1015 src
= GetOffsetAddress (btreePtr
, node
, node
->numRecords
); // point to free offset
1016 dst
= src
- 1; // point to new offset
1017 numOffsets
= node
->numRecords
++ - index
; // subtract index & postincrement
1020 *dst
++ = *src
++ + delta
; // to tricky?
1021 } while (numOffsets
--);
1026 /*-------------------------------------------------------------------------------
1028 Routine: DeleteOffset - Delete an offset.
1030 Function: Delete the offset at 'index' by shifting 'index+1' through the last offset
1031 and adjusting them by the size of the record 'index'.
1032 The number of records contained in the node is also decremented.
1034 Input: btreePtr - pointer to BTree control block
1035 node - pointer to node
1036 index - index at which to delete record
1039 -------------------------------------------------------------------------------*/
1041 void DeleteOffset (BTreeControlBlockPtr btreePtr
,
1049 dst
= GetOffsetAddress (btreePtr
, node
, index
);
1051 delta
= *src
- *dst
;
1052 numOffsets
= --node
->numRecords
- index
; // predecrement numRecords & subtract index
1054 while (numOffsets
--)
1056 *--dst
= *--src
- delta
; // work our way left