3 /* BPlusTree - BFS B+Tree implementation
5 ** Copyright 2001 pinc Software. All Rights Reserved.
6 ** Released under the terms of the MIT license.
20 // ****************** on-disk structures ********************
22 #define BPLUSTREE_NULL -1LL
23 #define BPLUSTREE_FREE -2LL
25 struct __attribute__((packed
)) bplustree_header
29 uint32 max_number_of_levels
;
31 off_t root_node_pointer
;
32 off_t free_node_pointer
;
35 inline bool IsValidLink(off_t link
);
38 #define BPLUSTREE_MAGIC 0x69f6c2e8
39 #define BPLUSTREE_NODE_SIZE 1024
40 #define BPLUSTREE_MAX_KEY_LENGTH 256
41 #define BPLUSTREE_MIN_KEY_LENGTH 1
43 enum bplustree_types
{
44 BPLUSTREE_STRING_TYPE
= 0,
45 BPLUSTREE_INT32_TYPE
= 1,
46 BPLUSTREE_UINT32_TYPE
= 2,
47 BPLUSTREE_INT64_TYPE
= 3,
48 BPLUSTREE_UINT64_TYPE
= 4,
49 BPLUSTREE_FLOAT_TYPE
= 5,
50 BPLUSTREE_DOUBLE_TYPE
= 6
53 struct __attribute((packed
)) bplustree_node
{
58 uint16 all_key_length
;
60 inline uint16
*KeyLengths() const;
61 inline off_t
*Values() const;
62 inline uint8
*Keys() const;
63 inline int32
Used() const;
64 uint8
*KeyAt(int32 index
, uint16
*keyLength
) const;
66 uint8
CountDuplicates(off_t offset
, bool isFragment
) const;
67 off_t
DuplicateAt(off_t offset
, bool isFragment
, int8 index
) const;
69 static inline uint8
LinkType(off_t link
);
70 static inline off_t
FragmentOffset(off_t link
);
73 #define BPLUSTREE_NODE 0
74 #define BPLUSTREE_DUPLICATE_NODE 2
75 #define BPLUSTREE_DUPLICATE_FRAGMENT 3
77 // **************************************
79 enum bplustree_traversing
{
80 BPLUSTREE_FORWARD
= 1,
81 BPLUSTREE_BACKWARD
= -1,
87 template<class T
> class Stack
;
90 class NodeCache
: public Cache
<off_t
> {
92 NodeCache(BPlusTree
*);
94 virtual Cacheable
*NewCacheable(off_t offset
);
95 bplustree_node
*Get(off_t offset
);
96 // void SetOffset(bplustree_node *, off_t offset);
105 BPlusTree(int32 keyType
, int32 nodeSize
= BPLUSTREE_NODE_SIZE
,
106 bool allowDuplicates
= true);
107 BPlusTree(BPositionIO
*stream
, bool allowDuplicates
= true);
111 status_t
SetTo(int32 keyType
,int32 nodeSize
= BPLUSTREE_NODE_SIZE
,bool allowDuplicates
= true);
112 status_t
SetTo(BPositionIO
*stream
,bool allowDuplicates
= true);
114 status_t
InitCheck();
115 status_t
Validate(bool verbose
= false);
117 int32
Type() const { return fHeader
->data_type
; }
120 status_t
Goto(int8 to
);
121 status_t
GetNextEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
);
122 status_t
GetPreviousEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
);
124 status_t
Insert(uint8
*key
, uint16 keyLength
, off_t value
);
126 status_t
Insert(const char *key
, off_t value
);
127 status_t
Insert(int32 key
, off_t value
);
128 status_t
Insert(uint32 key
, off_t value
);
129 status_t
Insert(int64 key
, off_t value
);
130 status_t
Insert(uint64 key
, off_t value
);
131 status_t
Insert(float key
, off_t value
);
132 status_t
Insert(double key
, off_t value
);
134 status_t
Find(uint8
*key
, uint16 keyLength
, off_t
*value
);
136 status_t
WriteTo(BPositionIO
*stream
);
138 void SetHoldChanges(bool hold
);
141 // needed for searching
142 struct node_and_key
{
147 void Initialize(int32 nodeSize
);
149 void SetCurrentNode(bplustree_node
*node
,off_t offset
,int8 to
= BPLUSTREE_BEGIN
);
150 status_t
Traverse(int8 direction
,void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
);
152 int32
CompareKeys(const void *key1
, int keylength1
, const void *key2
, int keylength2
);
153 status_t
FindKey(bplustree_node
*node
, uint8
*key
, uint16 keyLength
, uint16
*index
= NULL
, off_t
*next
= NULL
);
154 status_t
SeekDown(Stack
<node_and_key
> &stack
, uint8
*key
, uint16 keyLength
);
156 status_t
SplitNode(bplustree_node
*node
, off_t nodeOffset
, uint16
*_keyIndex
, uint8
*key
, uint16
*_keyLength
, off_t
*_value
);
158 void InsertKey(bplustree_node
*node
, uint8
*key
, uint16 keyLength
, off_t value
, uint16 index
);
159 status_t
InsertDuplicate(bplustree_node
*node
,uint16 index
);
161 bool CheckNode(bplustree_node
*node
);
164 friend class NodeCache
;
165 bplustree_node
*Node(off_t nodeoffset
,bool check
= true);
168 BPositionIO
*fStream
;
169 bplustree_header
*fHeader
;
171 bool fAllowDuplicates
;
176 off_t fCurrentNodeOffset
; // traverse position
178 off_t fDuplicateNode
;
179 uint16 fDuplicate
, fNumDuplicates
;
185 inline status_t
BPlusTree::Rewind()
187 return Goto(BPLUSTREE_BEGIN
);
190 inline status_t
BPlusTree::GetNextEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
)
192 return Traverse(BPLUSTREE_FORWARD
,key
,keyLength
,maxLength
,value
);
195 inline status_t
BPlusTree::GetPreviousEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
)
197 return Traverse(BPLUSTREE_BACKWARD
,key
,keyLength
,maxLength
,value
);
200 inline status_t
BPlusTree::Insert(const char *key
,off_t value
)
202 if (fHeader
->data_type
!= BPLUSTREE_STRING_TYPE
)
204 return Insert((uint8
*)key
, strlen(key
), value
);
207 inline status_t
BPlusTree::Insert(int32 key
, off_t value
)
209 if (fHeader
->data_type
!= BPLUSTREE_INT32_TYPE
)
211 return Insert((uint8
*)&key
, sizeof(key
), value
);
214 inline status_t
BPlusTree::Insert(uint32 key
, off_t value
)
216 if (fHeader
->data_type
!= BPLUSTREE_UINT32_TYPE
)
218 return Insert((uint8
*)&key
, sizeof(key
), value
);
221 inline status_t
BPlusTree::Insert(int64 key
, off_t value
)
223 if (fHeader
->data_type
!= BPLUSTREE_INT64_TYPE
)
225 return Insert((uint8
*)&key
, sizeof(key
), value
);
228 inline status_t
BPlusTree::Insert(uint64 key
, off_t value
)
230 if (fHeader
->data_type
!= BPLUSTREE_UINT64_TYPE
)
232 return Insert((uint8
*)&key
, sizeof(key
), value
);
235 inline status_t
BPlusTree::Insert(float key
, off_t value
)
237 if (fHeader
->data_type
!= BPLUSTREE_FLOAT_TYPE
)
239 return Insert((uint8
*)&key
, sizeof(key
), value
);
242 inline status_t
BPlusTree::Insert(double key
, off_t value
)
244 if (fHeader
->data_type
!= BPLUSTREE_DOUBLE_TYPE
)
246 return Insert((uint8
*)&key
, sizeof(key
), value
);
250 /************************ bplustree_header inline functions ************************/
254 inline bool bplustree_header::IsValidLink(off_t link
)
256 return link
== BPLUSTREE_NULL
|| (link
> 0 && link
<= maximum_size
- node_size
);
260 /************************ bplustree_node inline functions ************************/
264 inline uint16
*bplustree_node::KeyLengths() const
266 return (uint16
*)(((char *)this) + round_up(sizeof(bplustree_node
) + all_key_length
));
269 inline off_t
*bplustree_node::Values() const
271 return (off_t
*)((char *)KeyLengths() + all_key_count
* sizeof(uint16
));
274 inline uint8
*bplustree_node::Keys() const
276 return (uint8
*)this + sizeof(bplustree_node
);
279 inline int32
bplustree_node::Used() const
281 return round_up(sizeof(bplustree_node
) + all_key_length
) + all_key_count
* (sizeof(uint16
) + sizeof(off_t
));
284 inline uint8
bplustree_node::LinkType(off_t link
)
286 return *(uint64
*)&link
>> 62;
289 inline off_t
bplustree_node::FragmentOffset(off_t link
)
291 return link
& 0x3ffffffffffffc00LL
;
294 #endif /* B_PLUS_TREE_H */