2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
25 Contains: Single-node operations for the BTree Module.
27 Version: xxx put the technology version here xxx
29 Written by: Gordon Sheridan and Bill Bruffey
31 Copyright: © 1992-1999 by Apple Computer, Inc., all rights reserved.
37 Other Contact: Mark Day
39 Technology: File Systems
46 Change History (most recent first):
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
59 <CS1> 4/23/97 djb first checked in
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
66 History applicable to original Scarecrow Design:
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. \80\80\80 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.
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
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.
103 #include "../headers/BTreesPrivate.h"
107 ///////////////////////// BTree Module Node Operations //////////////////////////
109 // GetNode - Call FS Agent to get node
110 // GetNewNode - Call FS Agent to get a new node
111 // ReleaseNode - Call FS Agent to release node obtained by GetNode.
112 // UpdateNode - Mark a node as dirty and call FS Agent to release it.
114 // ClearNode - Clear a node to all zeroes.
116 // InsertRecord - Inserts a record into a BTree node.
117 // InsertKeyRecord - Inserts a key and record pair into a BTree node.
118 // DeleteRecord - Deletes a record from a BTree node.
120 // SearchNode - Return index for record that matches key.
121 // LocateRecord - Return pointer to key and data, and size of data.
123 // GetNodeDataSize - Return the amount of space used for data in the node.
124 // GetNodeFreeSize - Return the amount of free space in the node.
126 // GetRecordOffset - Return the offset for record "index".
127 // GetRecordAddress - Return address of record "index".
128 // GetOffsetAddress - Return address of offset for record "index".
130 // InsertOffset - Inserts a new offset into a node.
131 // DeleteOffset - Deletes an offset from a node.
133 /////////////////////////////////////////////////////////////////////////////////
137 ////////////////////// Routines Internal To BTreeNodeOps.c //////////////////////
139 UInt16
GetRecordOffset (BTreeControlBlockPtr btree
,
143 UInt16
*GetOffsetAddress (BTreeControlBlockPtr btreePtr
,
147 void InsertOffset (BTreeControlBlockPtr btreePtr
,
152 void DeleteOffset (BTreeControlBlockPtr btreePtr
,
157 /////////////////////////////////////////////////////////////////////////////////
159 #define GetRecordOffset(btreePtr,node,index) (*(short *) ((UInt8 *)(node) + (btreePtr)->nodeSize - ((index) << 1) - kOffsetSize))
162 #include <sys/systm.h>
163 #define PRINTIT kprintf
164 #endif /* HFS_DIAGNOSTIC */
166 static void PrintNode(const NodeDescPtr node
, UInt16 nodeSize
, UInt32 nodeNumber
);
170 /*-------------------------------------------------------------------------------
172 Routine: GetNode - Call FS Agent to get node
174 Function: Gets an existing BTree node from FS Agent and verifies it.
176 Input: btreePtr - pointer to BTree control block
177 nodeNum - number of node to request
179 Output: nodePtr - pointer to beginning of node (nil if error)
184 -------------------------------------------------------------------------------*/
186 OSStatus
GetNode (BTreeControlBlockPtr btreePtr
,
191 GetBlockProcPtr getNodeProc
;
194 //\80\80 is nodeNum within proper range?
195 if( nodeNum
>= btreePtr
->totalNodes
)
197 Panic("\pGetNode:nodeNum >= totalNodes");
198 err
= fsBTInvalidNodeErr
;
202 nodePtr
->blockSize
= btreePtr
->nodeSize
; // indicate the size of a node
204 getNodeProc
= btreePtr
->getBlockProc
;
205 err
= getNodeProc (btreePtr
->fileRefNum
,
212 Panic ("\pGetNode: getNodeProc returned error.");
213 // nodePtr->buffer = nil;
216 ++btreePtr
->numGetNodes
;
221 nodePtr
->buffer
= nil
;
222 nodePtr
->blockHeader
= nil
;
229 /*-------------------------------------------------------------------------------
231 Routine: GetNewNode - Call FS Agent to get a new node
233 Function: Gets a new BTree node from FS Agent and initializes it to an empty
236 Input: btreePtr - pointer to BTree control block
237 nodeNum - number of node to request
239 Output: returnNodePtr - pointer to beginning of node (nil if error)
241 Result: noErr - success
243 -------------------------------------------------------------------------------*/
245 OSStatus
GetNewNode (BTreeControlBlockPtr btreePtr
,
247 NodeRec
*returnNodePtr
)
252 GetBlockProcPtr getNodeProc
;
255 //////////////////////// get buffer for new node ////////////////////////////
257 returnNodePtr
->blockSize
= btreePtr
->nodeSize
; // indicate the size of a node
259 getNodeProc
= btreePtr
->getBlockProc
;
260 err
= getNodeProc (btreePtr
->fileRefNum
,
262 kGetBlock
+kGetEmptyBlock
,
267 Panic ("\pGetNewNode: getNodeProc returned error.");
268 // returnNodePtr->buffer = nil;
271 ++btreePtr
->numGetNewNodes
;
274 ////////////////////////// initialize the node //////////////////////////////
276 node
= returnNodePtr
->buffer
;
278 ClearNode (btreePtr
, node
); // clear the node
280 pos
= (char *)node
+ btreePtr
->nodeSize
- 2; // find address of last offset
281 *(UInt16
*)pos
= sizeof (BTNodeDescriptor
); // set offset to beginning of free space
289 /*-------------------------------------------------------------------------------
291 Routine: ReleaseNode - Call FS Agent to release node obtained by GetNode.
293 Function: Informs the FS Agent that a BTree node may be released.
295 Input: btreePtr - pointer to BTree control block
296 nodeNum - number of node to release
298 Result: noErr - success
300 -------------------------------------------------------------------------------*/
302 OSStatus
ReleaseNode (BTreeControlBlockPtr btreePtr
,
306 ReleaseBlockProcPtr releaseNodeProc
;
311 if (nodePtr
->buffer
!= nil
)
313 releaseNodeProc
= btreePtr
->releaseBlockProc
;
314 err
= releaseNodeProc (btreePtr
->fileRefNum
,
317 PanicIf (err
, "\pReleaseNode: releaseNodeProc returned error.");
318 ++btreePtr
->numReleaseNodes
;
321 nodePtr
->buffer
= nil
;
322 nodePtr
->blockHeader
= nil
;
330 /*-------------------------------------------------------------------------------
332 Routine: TrashNode - Call FS Agent to release node obtained by GetNode, and
333 not store it...mark it as bad.
335 Function: Informs the FS Agent that a BTree node may be released and thrown away.
337 Input: btreePtr - pointer to BTree control block
338 nodeNum - number of node to release
340 Result: noErr - success
342 -------------------------------------------------------------------------------*/
344 OSStatus
TrashNode (BTreeControlBlockPtr btreePtr
,
348 ReleaseBlockProcPtr releaseNodeProc
;
353 if (nodePtr
->buffer
!= nil
)
355 releaseNodeProc
= btreePtr
->releaseBlockProc
;
356 err
= releaseNodeProc (btreePtr
->fileRefNum
,
358 kReleaseBlock
| kTrashBlock
);
359 PanicIf (err
, "\TrashNode: releaseNodeProc returned error.");
360 ++btreePtr
->numReleaseNodes
;
363 nodePtr
->buffer
= nil
;
364 nodePtr
->blockHeader
= nil
;
371 /*-------------------------------------------------------------------------------
373 Routine: UpdateNode - Mark a node as dirty and call FS Agent to release it.
375 Function: Marks a BTree node dirty and informs the FS Agent that it may be released.
377 Input: btreePtr - pointer to BTree control block
378 nodeNum - number of node to release
379 transactionID - ID of transaction this node update is a part of
380 flags - special flags to pass to ReleaseNodeProc
382 Result: noErr - success
384 -------------------------------------------------------------------------------*/
386 OSStatus
UpdateNode (BTreeControlBlockPtr btreePtr
,
388 UInt32 transactionID
,
392 ReleaseBlockProcPtr releaseNodeProc
;
397 if (nodePtr
->buffer
!= nil
) // Why call UpdateNode if nil ?!?
399 releaseNodeProc
= btreePtr
->releaseBlockProc
;
400 err
= releaseNodeProc (btreePtr
->fileRefNum
,
402 flags
| kMarkBlockDirty
);
403 ++btreePtr
->numUpdateNodes
;
407 nodePtr
->buffer
= nil
;
408 nodePtr
->blockHeader
= nil
;
420 static void PrintNode(const NodeDescPtr node
, UInt16 nodeSize
, UInt32 nodeNumber
)
429 PRINTIT("Dump of B-tree node #%ld ($%08lX)\n", nodeNumber
, nodeNumber
);
436 PRINTIT("%04X: %08lX %08lX %08lX %08lX\n", (u_int
)offset
++, *lp
++, *lp
++, *lp
++, *lp
++);
441 /*-------------------------------------------------------------------------------
443 Routine: ClearNode - Clear a node to all zeroes.
445 Function: Writes zeroes from beginning of node for nodeSize bytes.
447 Input: btreePtr - pointer to BTree control block
448 node - pointer to node to clear
451 -------------------------------------------------------------------------------*/
453 void ClearNode (BTreeControlBlockPtr btreePtr
, NodeDescPtr node
)
455 ClearMemory( node
, btreePtr
->nodeSize
);
458 /*-------------------------------------------------------------------------------
460 Routine: InsertRecord - Inserts a record into a BTree node.
464 Note: Record size must be even!
466 Input: btreePtr - pointer to BTree control block
467 node - pointer to node to insert the record
468 index - position record is to be inserted
469 recPtr - pointer to record to insert
471 Result: noErr - success
472 fsBTFullErr - record larger than remaining free space.
473 -------------------------------------------------------------------------------*/
475 Boolean
InsertRecord (BTreeControlBlockPtr btreePtr
,
488 //// will new record fit in node?
490 freeSpace
= GetNodeFreeSize (btreePtr
, node
);
491 //\80\80 we could get freeOffset & calc freeSpace
492 if ( freeSpace
< recSize
+ 2)
498 //// make hole for new record
500 indexOffset
= GetRecordOffset (btreePtr
, node
, index
);
501 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
503 src
= ((Ptr
) node
) + indexOffset
;
504 dst
= ((Ptr
) src
) + recSize
;
505 bytesToMove
= freeOffset
- indexOffset
;
507 MoveRecordsRight (src
, dst
, bytesToMove
);
510 //// adjust offsets for moved records
512 InsertOffset (btreePtr
, node
, index
, recSize
);
515 //// move in the new record
517 dst
= ((Ptr
) node
) + indexOffset
;
518 MoveRecordsLeft (recPtr
, dst
, recSize
);
525 /*-------------------------------------------------------------------------------
527 Routine: InsertKeyRecord - Inserts a record into a BTree node.
531 Note: Record size must be even!
533 Input: btreePtr - pointer to BTree control block
534 node - pointer to node to insert the record
535 index - position record is to be inserted
536 keyPtr - pointer to key for record to insert
537 keyLength - length of key (or maxKeyLength)
538 recPtr - pointer to record to insert
539 recSize - number of bytes to copy for record
541 Result: noErr - success
542 fsBTFullErr - record larger than remaining free space.
543 -------------------------------------------------------------------------------*/
545 Boolean
InsertKeyRecord (BTreeControlBlockPtr btreePtr
,
563 //// calculate actual key size
565 if ( btreePtr
->attributes
& kBTBigKeysMask
)
566 keySize
= keyLength
+ sizeof(UInt16
);
568 keySize
= keyLength
+ sizeof(UInt8
);
570 if ( M_IsOdd (keySize
) )
571 ++keySize
; // add pad byte
574 //// will new record fit in node?
576 freeSpace
= GetNodeFreeSize (btreePtr
, node
);
577 //\80\80 we could get freeOffset & calc freeSpace
578 if ( freeSpace
< keySize
+ recSize
+ 2)
584 //// make hole for new record
586 indexOffset
= GetRecordOffset (btreePtr
, node
, index
);
587 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
589 src
= ((UInt8
*) node
) + indexOffset
;
590 dst
= ((UInt8
*) src
) + keySize
+ recSize
;
591 bytesToMove
= freeOffset
- indexOffset
;
593 MoveRecordsRight (src
, dst
, bytesToMove
);
596 //// adjust offsets for moved records
598 InsertOffset (btreePtr
, node
, index
, keySize
+ recSize
);
603 dst
= ((UInt8
*) node
) + indexOffset
;
605 if ( btreePtr
->attributes
& kBTBigKeysMask
)
607 *((UInt16
*) dst
)++ = keyLength
; // use keyLength rather than key.length
608 rawKeyLength
= keyPtr
->length16
;
613 *dst
++ = keyLength
; // use keyLength rather than key.length
614 rawKeyLength
= keyPtr
->length8
;
618 MoveRecordsLeft ( ((UInt8
*) keyPtr
) + sizeOfLength
, dst
, rawKeyLength
); // copy key
621 bytesToMove
= keySize
- rawKeyLength
;
623 ClearMemory (dst
+ rawKeyLength
, bytesToMove
); // clear pad bytes in index key
626 //// copy record data
628 dst
= ((UInt8
*) node
) + indexOffset
+ keySize
;
629 MoveRecordsLeft (recPtr
, dst
, recSize
);
636 /*-------------------------------------------------------------------------------
638 Routine: DeleteRecord - Deletes a record from a BTree node.
642 Input: btreePtr - pointer to BTree control block
643 node - pointer to node to insert the record
644 index - position record is to be inserted
647 -------------------------------------------------------------------------------*/
649 void DeleteRecord (BTreeControlBlockPtr btreePtr
,
660 //// compress records
661 indexOffset
= GetRecordOffset (btreePtr
, node
, index
);
662 nextOffset
= GetRecordOffset (btreePtr
, node
, index
+ 1);
663 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
665 src
= ((Ptr
) node
) + nextOffset
;
666 dst
= ((Ptr
) node
) + indexOffset
;
667 bytesToMove
= freeOffset
- nextOffset
;
669 MoveRecordsLeft (src
, dst
, bytesToMove
);
671 //// Adjust the offsets
672 DeleteOffset (btreePtr
, node
, index
);
674 /* clear out new free space */
675 bytesToMove
= nextOffset
- indexOffset
;
676 ClearMemory(GetRecordAddress(btreePtr
, node
, node
->numRecords
), bytesToMove
);
682 /*-------------------------------------------------------------------------------
684 Routine: SearchNode - Return index for record that matches key.
686 Function: Returns the record index for the record that matches the search key.
687 If no record was found that matches the search key, the "insert index"
688 of where the record should go is returned instead.
690 Algorithm: A binary search algorithm is used to find the specified key.
692 Input: btreePtr - pointer to BTree control block
693 node - pointer to node that contains the record
694 searchKey - pointer to the key to match
696 Output: index - pointer to beginning of key for record
698 Result: true - success (index = record index)
699 false - key did not match anything in node (index = insert index)
700 -------------------------------------------------------------------------------*/
702 SearchNode( BTreeControlBlockPtr btreePtr
,
705 UInt16
*returnIndex
)
713 KeyCompareProcPtr compareProc
= btreePtr
->keyCompareProc
;
716 upperBound
= node
->numRecords
- 1;
717 offset
= (UInt16
*) ((UInt8
*)(node
) + (btreePtr
)->nodeSize
- kOffsetSize
);
719 while (lowerBound
<= upperBound
) {
720 index
= (lowerBound
+ upperBound
) >> 1;
722 trialKey
= (KeyPtr
) ((UInt8
*)node
+ *(offset
- index
));
724 result
= compareProc(searchKey
, trialKey
);
727 upperBound
= index
- 1; /* search < trial */
728 } else if (result
> 0) {
729 lowerBound
= index
+ 1; /* search > trial */
731 *returnIndex
= index
; /* search == trial */
736 *returnIndex
= lowerBound
; /* lowerBound is insert index */
741 /*-------------------------------------------------------------------------------
743 Routine: GetRecordByIndex - Return pointer to key and data, and size of data.
745 Function: Returns a pointer to beginning of key for record, a pointer to the
746 beginning of the data for the record, and the size of the record data
747 (does not include the size of the key).
749 Input: btreePtr - pointer to BTree control block
750 node - pointer to node that contains the record
751 index - index of record to get
753 Output: keyPtr - pointer to beginning of key for record
754 dataPtr - pointer to beginning of data for record
755 dataSize - size of the data portion of the record
758 -------------------------------------------------------------------------------*/
760 OSStatus
GetRecordByIndex (BTreeControlBlockPtr btreePtr
,
772 // Make sure index is valid (in range 0..numRecords-1)
774 if (index
>= node
->numRecords
)
775 return fsBTRecordNotFoundErr
;
778 offset
= GetRecordOffset (btreePtr
, node
, index
);
779 *keyPtr
= (KeyPtr
) ((Ptr
)node
+ offset
);
782 keySize
= CalcKeySize(btreePtr
, *keyPtr
);
783 if ( M_IsOdd (keySize
) )
784 ++keySize
; // add pad byte
786 offset
+= keySize
; // add the key length to find data offset
787 *dataPtr
= (UInt8
*) node
+ offset
;
790 nextOffset
= GetRecordOffset (btreePtr
, node
, index
+ 1);
791 *dataSize
= nextOffset
- offset
;
798 /*-------------------------------------------------------------------------------
800 Routine: GetNodeDataSize - Return the amount of space used for data in the node.
802 Function: Gets the size of the data currently contained in a node, excluding
803 the node header. (record data + offset overhead)
805 Input: btreePtr - pointer to BTree control block
806 node - pointer to node that contains the record
808 Result: - number of bytes used for data and offsets in the node.
809 -------------------------------------------------------------------------------*/
811 UInt16
GetNodeDataSize (BTreeControlBlockPtr btreePtr
, NodeDescPtr node
)
815 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
);
817 return freeOffset
+ (node
->numRecords
<< 1) - sizeof (BTNodeDescriptor
);
822 /*-------------------------------------------------------------------------------
824 Routine: GetNodeFreeSize - Return the amount of free space in the node.
828 Input: btreePtr - pointer to BTree control block
829 node - pointer to node that contains the record
831 Result: - number of bytes of free space in the node.
832 -------------------------------------------------------------------------------*/
834 UInt16
GetNodeFreeSize (BTreeControlBlockPtr btreePtr
, NodeDescPtr node
)
838 freeOffset
= GetRecordOffset (btreePtr
, node
, node
->numRecords
); //\80\80 inline?
840 return btreePtr
->nodeSize
- freeOffset
- (node
->numRecords
<< 1) - kOffsetSize
;
845 /*-------------------------------------------------------------------------------
847 Routine: GetRecordOffset - Return the offset for record "index".
851 Input: btreePtr - pointer to BTree control block
852 node - pointer to node that contains the record
853 index - record to obtain offset for
855 Result: - offset (in bytes) from beginning of node of record specified by index
856 -------------------------------------------------------------------------------*/
857 // make this a macro (for inlining)
859 UInt16
GetRecordOffset (BTreeControlBlockPtr btreePtr
,
866 pos
= (UInt8
*)node
+ btreePtr
->nodeSize
- (index
<< 1) - kOffsetSize
;
868 return *(short *)pos
;
874 /*-------------------------------------------------------------------------------
876 Routine: GetRecordAddress - Return address of record "index".
880 Input: btreePtr - pointer to BTree control block
881 node - pointer to node that contains the record
882 index - record to obtain offset address for
884 Result: - pointer to record "index".
885 -------------------------------------------------------------------------------*/
886 // make this a macro (for inlining)
888 UInt8
* GetRecordAddress (BTreeControlBlockPtr btreePtr
,
894 pos
= (UInt8
*)node
+ GetRecordOffset (btreePtr
, node
, index
);
902 /*-------------------------------------------------------------------------------
904 Routine: GetRecordSize - Return size of record "index".
908 Note: This does not work on the FreeSpace index!
910 Input: btreePtr - pointer to BTree control block
911 node - pointer to node that contains the record
912 index - record to obtain record size for
914 Result: - size of record "index".
915 -------------------------------------------------------------------------------*/
917 UInt16
GetRecordSize (BTreeControlBlockPtr btreePtr
,
923 pos
= (UInt16
*) ((Ptr
)node
+ btreePtr
->nodeSize
- (index
<< 1) - kOffsetSize
);
925 return *(pos
-1) - *pos
;
930 /*-------------------------------------------------------------------------------
931 Routine: GetOffsetAddress - Return address of offset for record "index".
935 Input: btreePtr - pointer to BTree control block
936 node - pointer to node that contains the record
937 index - record to obtain offset address for
939 Result: - pointer to offset for record "index".
940 -------------------------------------------------------------------------------*/
942 UInt16
*GetOffsetAddress (BTreeControlBlockPtr btreePtr
,
948 pos
= (Ptr
)node
+ btreePtr
->nodeSize
- (index
<< 1) -2;
950 return (UInt16
*)pos
;
955 /*-------------------------------------------------------------------------------
956 Routine: GetChildNodeNum - Return child node number from index record "index".
958 Function: Returns the first UInt32 stored after the key for record "index".
960 Assumes: The node is an Index Node.
961 The key.length stored at record "index" is ODD. //\80\80 change for variable length index keys
963 Input: btreePtr - pointer to BTree control block
964 node - pointer to node that contains the record
965 index - record to obtain child node number from
967 Result: - child node number from record "index".
968 -------------------------------------------------------------------------------*/
970 UInt32
GetChildNodeNum (BTreeControlBlockPtr btreePtr
,
976 pos
= GetRecordAddress (btreePtr
, nodePtr
, index
);
977 pos
+= CalcKeySize(btreePtr
, (BTreeKey
*) pos
); // key.length + size of length field
979 return *(UInt32
*)pos
;
984 /*-------------------------------------------------------------------------------
985 Routine: InsertOffset - Add an offset and adjust existing offsets by delta.
987 Function: Add an offset at 'index' by shifting 'index+1' through the last offset
988 and adjusting them by 'delta', the size of the record to be inserted.
989 The number of records contained in the node is also incremented.
991 Input: btreePtr - pointer to BTree control block
992 node - pointer to node
993 index - index at which to insert record
994 delta - size of record to be inserted
997 -------------------------------------------------------------------------------*/
999 void InsertOffset (BTreeControlBlockPtr btreePtr
,
1007 src
= GetOffsetAddress (btreePtr
, node
, node
->numRecords
); // point to free offset
1008 dst
= src
- 1; // point to new offset
1009 numOffsets
= node
->numRecords
++ - index
; // subtract index & postincrement
1012 *dst
++ = *src
++ + delta
; // to tricky?
1013 } while (numOffsets
--);
1018 /*-------------------------------------------------------------------------------
1020 Routine: DeleteOffset - Delete an offset.
1022 Function: Delete the offset at 'index' by shifting 'index+1' through the last offset
1023 and adjusting them by the size of the record 'index'.
1024 The number of records contained in the node is also decremented.
1026 Input: btreePtr - pointer to BTree control block
1027 node - pointer to node
1028 index - index at which to delete record
1031 -------------------------------------------------------------------------------*/
1033 void DeleteOffset (BTreeControlBlockPtr btreePtr
,
1041 dst
= GetOffsetAddress (btreePtr
, node
, index
);
1043 delta
= *src
- *dst
;
1044 numOffsets
= --node
->numRecords
- index
; // predecrement numRecords & subtract index
1046 while (numOffsets
--)
1048 *--dst
= *--src
- delta
; // work our way left