3 /* BPlusTree - BFS B+Tree implementation
5 ** Copyright 2001 pinc Software. All Rights Reserved.
19 // ****************** on-disk structures ********************
21 #define BPLUSTREE_NULL -1LL
22 #define BPLUSTREE_FREE -2LL
24 struct __attribute__((packed
)) bplustree_header
28 uint32 max_number_of_levels
;
30 off_t root_node_pointer
;
31 off_t free_node_pointer
;
34 inline bool IsValidLink(off_t link
);
37 #define BPLUSTREE_MAGIC 0x69f6c2e8
38 #define BPLUSTREE_NODE_SIZE 1024
39 #define BPLUSTREE_MAX_KEY_LENGTH 256
40 #define BPLUSTREE_MIN_KEY_LENGTH 1
42 enum bplustree_types
{
43 BPLUSTREE_STRING_TYPE
= 0,
44 BPLUSTREE_INT32_TYPE
= 1,
45 BPLUSTREE_UINT32_TYPE
= 2,
46 BPLUSTREE_INT64_TYPE
= 3,
47 BPLUSTREE_UINT64_TYPE
= 4,
48 BPLUSTREE_FLOAT_TYPE
= 5,
49 BPLUSTREE_DOUBLE_TYPE
= 6
52 struct __attribute((packed
)) bplustree_node
{
57 uint16 all_key_length
;
59 inline uint16
*KeyLengths() const;
60 inline off_t
*Values() const;
61 inline uint8
*Keys() const;
62 inline int32
Used() const;
63 uint8
*KeyAt(int32 index
, uint16
*keyLength
) const;
65 uint8
CountDuplicates(off_t offset
, bool isFragment
) const;
66 off_t
DuplicateAt(off_t offset
, bool isFragment
, int8 index
) const;
68 static inline uint8
LinkType(off_t link
);
69 static inline off_t
FragmentOffset(off_t link
);
72 #define BPLUSTREE_NODE 0
73 #define BPLUSTREE_DUPLICATE_NODE 2
74 #define BPLUSTREE_DUPLICATE_FRAGMENT 3
76 // **************************************
78 enum bplustree_traversing
{
79 BPLUSTREE_FORWARD
= 1,
80 BPLUSTREE_BACKWARD
= -1,
86 template<class T
> class Stack
;
89 class NodeCache
: public Cache
<off_t
> {
91 NodeCache(BPlusTree
*);
93 virtual Cacheable
*NewCacheable(off_t offset
);
94 bplustree_node
*Get(off_t offset
);
95 // void SetOffset(bplustree_node *, off_t offset);
104 BPlusTree(int32 keyType
, int32 nodeSize
= BPLUSTREE_NODE_SIZE
,
105 bool allowDuplicates
= true);
106 BPlusTree(BPositionIO
*stream
, bool allowDuplicates
= true);
110 status_t
SetTo(int32 keyType
,int32 nodeSize
= BPLUSTREE_NODE_SIZE
,bool allowDuplicates
= true);
111 status_t
SetTo(BPositionIO
*stream
,bool allowDuplicates
= true);
113 status_t
InitCheck();
114 status_t
Validate(bool verbose
= false);
116 int32
Type() const { return fHeader
->data_type
; }
119 status_t
Goto(int8 to
);
120 status_t
GetNextEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
);
121 status_t
GetPreviousEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
);
123 status_t
Insert(uint8
*key
, uint16 keyLength
, off_t value
);
125 status_t
Insert(const char *key
, off_t value
);
126 status_t
Insert(int32 key
, off_t value
);
127 status_t
Insert(uint32 key
, off_t value
);
128 status_t
Insert(int64 key
, off_t value
);
129 status_t
Insert(uint64 key
, off_t value
);
130 status_t
Insert(float key
, off_t value
);
131 status_t
Insert(double key
, off_t value
);
133 status_t
Find(uint8
*key
, uint16 keyLength
, off_t
*value
);
135 status_t
WriteTo(BPositionIO
*stream
);
137 void SetHoldChanges(bool hold
);
140 // needed for searching
141 struct node_and_key
{
146 void Initialize(int32 nodeSize
);
148 void SetCurrentNode(bplustree_node
*node
,off_t offset
,int8 to
= BPLUSTREE_BEGIN
);
149 status_t
Traverse(int8 direction
,void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
);
151 int32
CompareKeys(const void *key1
, int keylength1
, const void *key2
, int keylength2
);
152 status_t
FindKey(bplustree_node
*node
, uint8
*key
, uint16 keyLength
, uint16
*index
= NULL
, off_t
*next
= NULL
);
153 status_t
SeekDown(Stack
<node_and_key
> &stack
, uint8
*key
, uint16 keyLength
);
155 status_t
SplitNode(bplustree_node
*node
, off_t nodeOffset
, uint16
*_keyIndex
, uint8
*key
, uint16
*_keyLength
, off_t
*_value
);
157 void InsertKey(bplustree_node
*node
, uint8
*key
, uint16 keyLength
, off_t value
, uint16 index
);
158 status_t
InsertDuplicate(bplustree_node
*node
,uint16 index
);
160 bool CheckNode(bplustree_node
*node
);
163 friend class NodeCache
;
164 bplustree_node
*Node(off_t nodeoffset
,bool check
= true);
167 BPositionIO
*fStream
;
168 bplustree_header
*fHeader
;
170 bool fAllowDuplicates
;
175 off_t fCurrentNodeOffset
; // traverse position
177 off_t fDuplicateNode
;
178 uint16 fDuplicate
, fNumDuplicates
;
184 inline status_t
BPlusTree::Rewind()
186 return Goto(BPLUSTREE_BEGIN
);
189 inline status_t
BPlusTree::GetNextEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
)
191 return Traverse(BPLUSTREE_FORWARD
,key
,keyLength
,maxLength
,value
);
194 inline status_t
BPlusTree::GetPreviousEntry(void *key
,uint16
*keyLength
,uint16 maxLength
,off_t
*value
)
196 return Traverse(BPLUSTREE_BACKWARD
,key
,keyLength
,maxLength
,value
);
199 inline status_t
BPlusTree::Insert(const char *key
,off_t value
)
201 if (fHeader
->data_type
!= BPLUSTREE_STRING_TYPE
)
203 return Insert((uint8
*)key
, strlen(key
), value
);
206 inline status_t
BPlusTree::Insert(int32 key
, off_t value
)
208 if (fHeader
->data_type
!= BPLUSTREE_INT32_TYPE
)
210 return Insert((uint8
*)&key
, sizeof(key
), value
);
213 inline status_t
BPlusTree::Insert(uint32 key
, off_t value
)
215 if (fHeader
->data_type
!= BPLUSTREE_UINT32_TYPE
)
217 return Insert((uint8
*)&key
, sizeof(key
), value
);
220 inline status_t
BPlusTree::Insert(int64 key
, off_t value
)
222 if (fHeader
->data_type
!= BPLUSTREE_INT64_TYPE
)
224 return Insert((uint8
*)&key
, sizeof(key
), value
);
227 inline status_t
BPlusTree::Insert(uint64 key
, off_t value
)
229 if (fHeader
->data_type
!= BPLUSTREE_UINT64_TYPE
)
231 return Insert((uint8
*)&key
, sizeof(key
), value
);
234 inline status_t
BPlusTree::Insert(float key
, off_t value
)
236 if (fHeader
->data_type
!= BPLUSTREE_FLOAT_TYPE
)
238 return Insert((uint8
*)&key
, sizeof(key
), value
);
241 inline status_t
BPlusTree::Insert(double key
, off_t value
)
243 if (fHeader
->data_type
!= BPLUSTREE_DOUBLE_TYPE
)
245 return Insert((uint8
*)&key
, sizeof(key
), value
);
249 /************************ bplustree_header inline functions ************************/
253 inline bool bplustree_header::IsValidLink(off_t link
)
255 return link
== BPLUSTREE_NULL
|| (link
> 0 && link
<= maximum_size
- node_size
);
259 /************************ bplustree_node inline functions ************************/
263 inline uint16
*bplustree_node::KeyLengths() const
265 return (uint16
*)(((char *)this) + round_up(sizeof(bplustree_node
) + all_key_length
));
268 inline off_t
*bplustree_node::Values() const
270 return (off_t
*)((char *)KeyLengths() + all_key_count
* sizeof(uint16
));
273 inline uint8
*bplustree_node::Keys() const
275 return (uint8
*)this + sizeof(bplustree_node
);
278 inline int32
bplustree_node::Used() const
280 return round_up(sizeof(bplustree_node
) + all_key_length
) + all_key_count
* (sizeof(uint16
) + sizeof(off_t
));
283 inline uint8
bplustree_node::LinkType(off_t link
)
285 return *(uint64
*)&link
>> 62;
288 inline off_t
bplustree_node::FragmentOffset(off_t link
)
290 return link
& 0x3ffffffffffffc00LL
;
293 #endif /* B_PLUS_TREE_H */