5 // Created by Yakov Ben Zaken on 20/03/2018.
12 #include "lf_hfs_file_mgr_internal.h"
13 #include "lf_hfs_btrees_internal.h"
16 /////////////////////////////////// Constants ///////////////////////////////////
18 #define kBTreeVersion 1
19 #define kMaxTreeDepth 16
22 #define kHeaderNodeNum 0
23 #define kKeyDescRecord 1
26 // Header Node Record Offsets
28 kHeaderRecOffset
= 0x000E,
29 kKeyDescRecOffset
= 0x0078,
30 kHeaderMapRecOffset
= 0x00F8
33 #define kMinNodeSize 512
35 #define kMinRecordSize 6
36 // where is minimum record size enforced?
38 // miscellaneous BTree constants
49 // illegal string attribute bits set in mask
50 #define kBadStrAttribMask 0xCF
54 //////////////////////////////////// Macros /////////////////////////////////////
56 #define M_NodesInMap(mapSize) ((mapSize) << 3)
58 #define M_ClearBitNum(integer,bitNumber) ((integer) &= (~(1<<(bitNumber))))
59 #define M_SetBitNum(integer,bitNumber) ((integer) |= (1<<(bitNumber)))
60 #define M_IsOdd(integer) (((integer) & 1) != 0)
61 #define M_IsEven(integer) (((integer) & 1) == 0)
63 #define M_MapRecordSize(nodeSize) (nodeSize - sizeof (BTNodeDescriptor) - 6)
64 #define M_HeaderMapRecordSize(nodeSize) (nodeSize - sizeof(BTNodeDescriptor) - sizeof(BTHeaderRec) - 128 - 8)
66 #define M_SWAP_BE16_ClearBitNum(integer,bitNumber) ((integer) &= SWAP_BE16(~(1<<(bitNumber))))
67 #define M_SWAP_BE16_SetBitNum(integer,bitNumber) ((integer) |= SWAP_BE16(1<<(bitNumber)))
69 ///////////////////////////////////// Types /////////////////////////////////////
71 typedef struct BTreeControlBlock
{ // fields specific to BTree CBs
73 u_int8_t keyCompareType
; /* Key string Comparison Type */
76 FileReference fileRefNum
; // refNum of btree file
77 KeyCompareProcPtr keyCompareProc
;
79 u_int32_t leafRecords
;
80 u_int32_t firstLeafNode
;
81 u_int32_t lastLeafNode
;
83 u_int16_t maxKeyLength
;
87 u_int16_t reserved3
; // 4-byte alignment
91 u_int32_t flags
; // dynamic flags
92 u_int32_t attributes
; // persistent flags
94 u_int32_t lastfsync
; /* Last time that this was fsynced */
96 GetBlockProcPtr getBlockProc
;
97 ReleaseBlockProcPtr releaseBlockProc
;
98 SetEndOfForkProcPtr setEndOfForkProc
;
100 // statistical information
101 u_int32_t numGetNodes
;
102 u_int32_t numGetNewNodes
;
103 u_int32_t numReleaseNodes
;
104 u_int32_t numUpdateNodes
;
105 u_int32_t numMapNodesRead
; // map nodes beyond header node
106 u_int32_t numHintChecks
;
107 u_int32_t numPossibleHints
; // Looks like a formated hint
108 u_int32_t numValidHints
; // Hint used to find correct record.
109 u_int32_t reservedNodes
;
110 BTreeIterator iterator
; // useable when holding exclusive b-tree lock
113 void *madeDirtyBy
[2];
115 } BTreeControlBlock
, *BTreeControlBlockPtr
;
117 u_int32_t
CalcKeySize(const BTreeControlBlock
*btcb
, const BTreeKey
*key
);
118 #define CalcKeySize(btcb, key) ( ((btcb)->attributes & kBTBigKeysMask) ? ((key)->length16 + 2) : ((key)->length8 + 1) )
120 u_int32_t
KeyLength(const BTreeControlBlock
*btcb
, const BTreeKey
*key
);
121 #define KeyLength(btcb, key) ( ((btcb)->attributes & kBTBigKeysMask) ? (key)->length16 : (key)->length8 )
126 kBTHeaderDirty
= 0x00000001
129 static inline void M_BTreeHeaderDirty(BTreeControlBlock
*bt
) {
131 bt
->madeDirtyBy
[0] = __builtin_return_address(0);
132 bt
->madeDirtyBy
[1] = __builtin_return_address(1);
134 bt
->flags
|= kBTHeaderDirty
;
137 typedef int8_t *NodeBuffer
;
138 typedef BlockDescriptor NodeRec
, *NodePtr
; //remove this someday...
143 //// Tree Path Table - constructed by SearchTree, used by InsertTree and DeleteTree
146 u_int32_t node
; // node number
148 u_int16_t reserved
; // align size to a power of 2
149 } TreePathRecord
, *TreePathRecordPtr
;
151 typedef TreePathRecord TreePathTable
[kMaxTreeDepth
];
154 //// InsertKey - used by InsertTree, InsertLevel and InsertNode
161 Boolean replacingKey
;
165 typedef struct InsertKey InsertKey
;
168 //// For Notational Convenience
170 typedef BTNodeDescriptor
* NodeDescPtr
;
171 typedef u_int8_t
*RecordPtr
;
172 typedef BTreeKeyPtr KeyPtr
;
175 //////////////////////////////////// Globals ////////////////////////////////////
178 //////////////////////////////////// Macros /////////////////////////////////////
179 // Exit function on error
180 #define M_ExitOnError( result ) do { if ( ( result ) != noErr ) goto ErrorExit; } while(0)
182 // Test for passed condition and return if true
183 #define M_ReturnErrorIf( condition, error ) do { if ( condition ) return( error ); } while(0)
185 //////////////////////////////// Key Operations /////////////////////////////////
187 int32_t CompareKeys (BTreeControlBlockPtr btreePtr
,
191 //////////////////////////////// Map Operations /////////////////////////////////
193 OSStatus
AllocateNode (BTreeControlBlockPtr btreePtr
,
196 OSStatus
FreeNode (BTreeControlBlockPtr btreePtr
,
199 OSStatus
ExtendBTree (BTreeControlBlockPtr btreePtr
,
202 u_int32_t
CalcMapBits (BTreeControlBlockPtr btreePtr
);
205 void BTUpdateReserve (BTreeControlBlockPtr btreePtr
,
208 //////////////////////////////// Misc Operations ////////////////////////////////
210 u_int16_t
CalcKeyRecordSize (u_int16_t keySize
,
213 OSStatus
VerifyHeader (FCB
*filePtr
,
214 BTHeaderRec
*header
);
216 OSStatus
UpdateHeader (BTreeControlBlockPtr btreePtr
,
217 Boolean forceWrite
);
219 OSStatus
FindIteratorPosition (BTreeControlBlockPtr btreePtr
,
220 BTreeIteratorPtr iterator
,
221 BlockDescriptor
*left
,
222 BlockDescriptor
*middle
,
223 BlockDescriptor
*right
,
226 Boolean
*foundRecord
);
228 OSStatus
CheckInsertParams (FCB
*filePtr
,
229 BTreeIterator
*iterator
,
230 FSBufferDescriptor
*record
,
231 u_int16_t recordLen
);
233 OSStatus
TrySimpleReplace (BTreeControlBlockPtr btreePtr
,
235 BTreeIterator
*iterator
,
236 FSBufferDescriptor
*record
,
238 Boolean
*recordInserted
);
240 OSStatus
IsItAHint (BTreeControlBlockPtr btreePtr
,
241 BTreeIterator
*iterator
,
244 extern OSStatus
TreeIsDirty(BTreeControlBlockPtr btreePtr
);
246 //////////////////////////////// Node Operations ////////////////////////////////
250 OSStatus
GetNode (BTreeControlBlockPtr btreePtr
,
253 NodeRec
*returnNodePtr
);
255 /* Flags for GetNode() */
256 #define kGetNodeHint 0x1 /* If set, the node is being looked up using a hint */
258 OSStatus
GetLeftSiblingNode (BTreeControlBlockPtr btreePtr
,
262 #define GetLeftSiblingNode(btree,node,left) GetNode ((btree), ((NodeDescPtr)(node))->bLink, 0, (left))
264 OSStatus
GetRightSiblingNode (BTreeControlBlockPtr btreePtr
,
268 #define GetRightSiblingNode(btree,node,right) GetNode ((btree), ((NodeDescPtr)(node))->fLink, 0, (right))
271 OSStatus
GetNewNode (BTreeControlBlockPtr btreePtr
,
273 NodeRec
*returnNodePtr
);
275 OSStatus
ReleaseNode (BTreeControlBlockPtr btreePtr
,
278 OSStatus
TrashNode (BTreeControlBlockPtr btreePtr
,
281 OSStatus
UpdateNode (BTreeControlBlockPtr btreePtr
,
283 u_int32_t transactionID
,
286 //// Node Buffer Operations
288 void ClearNode (BTreeControlBlockPtr btreePtr
,
291 u_int16_t
GetNodeDataSize (BTreeControlBlockPtr btreePtr
,
294 u_int16_t
GetNodeFreeSize (BTreeControlBlockPtr btreePtr
,
298 //// Record Operations
300 Boolean
InsertRecord (BTreeControlBlockPtr btreePtr
,
306 Boolean
InsertKeyRecord (BTreeControlBlockPtr btreePtr
,
314 void DeleteRecord (BTreeControlBlockPtr btree
,
319 Boolean
SearchNode (BTreeControlBlockPtr btree
,
324 OSStatus
GetRecordByIndex (BTreeControlBlockPtr btree
,
329 u_int16_t
*dataSize
);
331 u_int8_t
* GetRecordAddress (BTreeControlBlockPtr btree
,
335 #define GetRecordAddress(btreePtr,node,index) ((u_int8_t *)(node) + (*(short *) ((u_int8_t *)(node) + (btreePtr)->nodeSize - ((index) << 1) - kOffsetSize)))
338 u_int16_t
GetRecordSize (BTreeControlBlockPtr btree
,
342 u_int32_t
GetChildNodeNum (BTreeControlBlockPtr btreePtr
,
346 void MoveRecordsLeft (u_int8_t
* src
,
348 u_int16_t bytesToMove
);
350 #define MoveRecordsLeft(src,dst,bytes) bcopy((src),(dst),(bytes))
352 void MoveRecordsRight (u_int8_t
* src
,
354 u_int16_t bytesToMove
);
356 #define MoveRecordsRight(src,dst,bytes) bcopy((src),(dst),(bytes))
359 //////////////////////////////// Tree Operations ////////////////////////////////
361 OSStatus
SearchTree (BTreeControlBlockPtr btreePtr
,
363 TreePathTable treePathTable
,
365 BlockDescriptor
*nodePtr
,
368 OSStatus
InsertTree (BTreeControlBlockPtr btreePtr
,
369 TreePathTable treePathTable
,
373 BlockDescriptor
*targetNode
,
376 Boolean replacingKey
,
377 u_int32_t
*insertNode
);
379 OSStatus
DeleteTree (BTreeControlBlockPtr btreePtr
,
380 TreePathTable treePathTable
,
381 BlockDescriptor
*targetNode
,
385 OSStatus
BTFlushPath (FCB
*filePtr
);
387 OSStatus
BTSetLastSync (FCB
*filePtr
,
389 #endif /* lf_hfs_btree_h */