Skip to content
This repository was archived by the owner on Dec 21, 2020. It is now read-only.

Commit 16f2ab3

Browse files
committed
btree: delete, search
1 parent aa6dd12 commit 16f2ab3

File tree

4 files changed

+195
-67
lines changed

4 files changed

+195
-67
lines changed

Project/btree.cpp

Lines changed: 157 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,38 @@
1313

1414
uint16_t NodeBlock::size() {
1515
// keep an empty item as temp used when splitting a full block
16+
#ifdef DEBUG_BTREE
1617
return 4;
17-
//return ((BLOCK_SIZE - sizeof(BlockHeader)) / sizeof(KeyValue));
18+
#else
19+
return ((BLOCK_SIZE - sizeof(BlockHeader)) / sizeof(KeyValue));
20+
#endif // DEBUG_BTREE
1821
}
1922

20-
bool NodeBlock::isFull() {
23+
bool NodeBlock::full() {
2124
assert(header.count <= NodeBlock::size());
2225
return header.count == NodeBlock::size();
2326
}
2427

25-
bool NodeBlock::isEmpty() {
28+
bool NodeBlock::empty() {
2629
return header.count == 0;
2730
}
2831

32+
bool NodeBlock::eMin() {
33+
return header.count == size() / 2;
34+
}
35+
36+
bool NodeBlock::geMin() {
37+
return header.count >= size() / 2;
38+
}
39+
2940
uint16_t NodeBlock::find(uint64_t key) {
30-
assert(!isEmpty());
41+
assert(!empty());
3142
// TODO: diff between interior node and leaf
3243
uint16_t i = 0;
33-
if (header.type == BLOCK_TYPE_NODE) i++;
44+
if (!isLeaf()) i++;
3445
uint16_t j = header.count - 1;
3546
if (kv[j].key < key) return header.count;
47+
3648
while (i < j) {
3749
uint16_t mid = (i + j) / 2;
3850
if (kv[mid].key < key)
@@ -43,77 +55,46 @@ uint16_t NodeBlock::find(uint64_t key) {
4355
return j;
4456
}
4557

46-
bool NodeBlock::insert(KeyValue item, uint16_t index) {
58+
void NodeBlock::insert(KeyValue item, uint16_t index) {
4759
assert(index <= header.count);
4860
memmove(&kv[index + 1], &kv[index],
4961
sizeof(KeyValue) * (header.count - index));
5062
kv[index] = item;
5163
header.count++;
52-
return true;
5364
}
5465

55-
void NodeBlock::split(NodeBlock* nextNode, uint32_t index) {
66+
void NodeBlock::split(NodeBlock* nextNode) {
5667
nextNode->header.type = header.type;
5768

5869
// move kv
5970
memcpy(&nextNode->kv[0], &kv[(NodeBlock::size() + 1) / 2], NodeBlock::size() / 2 * sizeof(KeyValue));
6071
this->header.count = (NodeBlock::size() + 1) / 2;
6172
nextNode->header.count = NodeBlock::size() / 2;
6273

63-
if (nextNode->header.type == BLOCK_TYPE_LEAF) {
64-
nextNode->header.next = this->header.next;
65-
this->header.next = index;
66-
}
74+
// chain brother
75+
nextNode->header.next = this->header.next;
76+
this->header.next = nextNode->header.index;
6777
}
6878

69-
//void BTree::setRootIndex(uint32_t index) {
70-
// rootIndex = index;
71-
// storage.setIndexOfRoot(rootIndex);
72-
//}
79+
void NodeBlock::merge(NodeBlock * nextNode) {
80+
memcpy(&kv[0], &nextNode->kv[0], nextNode->header.count);
7381

74-
// 如果没有分裂,返回的value值为0。否则,返回要插入的值
75-
KeyValue BTree::insert(KeyValue kv, NodeBlock* cur) {
76-
assert(cur->header.type == BLOCK_TYPE_LEAF ||
77-
cur->header.type == BLOCK_TYPE_NODE);
78-
79-
KeyValue res;
80-
res.value = 0;
81-
82-
uint16_t i = cur->find(kv.key);
83-
84-
if (cur->header.type == BLOCK_TYPE_LEAF) {
85-
cur->insert(kv, i);
86-
}
87-
else {
88-
if (cur->kv[i].key > kv.key) {
89-
i--;
90-
}
91-
NodeBlock* t = (NodeBlock*)storage.getBlock(cur->kv[i].value);
92-
KeyValue r = insert(kv, t);
93-
if (r.value != 0)
94-
cur->insert(r, cur->find(r.key));
95-
}
96-
if (cur->isFull()) {
97-
uint32_t index = 0;
82+
header.count += nextNode->header.count;
9883

99-
NodeBlock* nextNode = (NodeBlock*)storage.getFreeBlock(&index);
100-
if (nextNode == NULL) {
101-
// TODO: failed to allocate a new block
102-
}
103-
cur->split(nextNode, index);
104-
res = nextNode->kv[0];
105-
res.value = index;
106-
return res;
107-
}
108-
return res;
84+
header.next = nextNode->header.next;
10985
}
11086

111-
int BTree::remove(KeyValue kv, NodeBlock* cur) {
112-
return 0;
87+
bool NodeBlock::isLeaf() {
88+
assert(header.type == BLOCK_TYPE_LEAF ||
89+
header.type == BLOCK_TYPE_NODE);
90+
return header.type == BLOCK_TYPE_LEAF;
11391
}
11492

115-
int BTree::search(KeyValue kv, NodeBlock* cur) {
116-
return 0;
93+
void NodeBlock::remove(uint16_t index) {
94+
assert(index < header.count);
95+
memmove(&kv[index], &kv[index + 1],
96+
sizeof(KeyValue) * (header.count - index - 1));
97+
header.count--;
11798
}
11899

119100
BTree::BTree(StorageManager &s) :root(NULL), storage(s) {
@@ -136,8 +117,9 @@ BTree::BTree(StorageManager &s) :root(NULL), storage(s) {
136117
}
137118

138119

120+
// 如果没有分裂,返回的value值为0。否则,返回要插入的值
139121
int BTree::insert(KeyValue kv) {
140-
if (root->isEmpty()) {
122+
if (root->empty()) {
141123
root->insert(kv, 0);
142124
return 1;
143125
}
@@ -148,7 +130,7 @@ int BTree::insert(KeyValue kv) {
148130
if (newRoot == NULL) {
149131
// TODO: failed to allocate a new block
150132
}
151-
newRoot->header.count = 1;
133+
newRoot->header.count = 2;
152134
newRoot->header.type = BLOCK_TYPE_NODE;
153135
newRoot->kv[1] = r;
154136
newRoot->kv[0].value = root->header.index;
@@ -159,10 +141,127 @@ int BTree::insert(KeyValue kv) {
159141
return 1;
160142
}
161143

144+
KeyValue BTree::insert(KeyValue kv, NodeBlock* cur) {
145+
KeyValue res;
146+
res.value = 0;
147+
148+
uint16_t i = cur->find(kv.key);
149+
150+
if (cur->isLeaf()) {
151+
cur->insert(kv, i);
152+
}
153+
else {
154+
if (cur->kv[i].key > kv.key) {
155+
i--;
156+
}
157+
NodeBlock* t = (NodeBlock*)storage.getBlock(cur->kv[i].value);
158+
KeyValue r = insert(kv, t);
159+
if (r.value != 0)
160+
cur->insert(r, cur->find(r.key));
161+
}
162+
163+
164+
if (cur->full()) {
165+
uint32_t index = 0;
166+
167+
NodeBlock* nextNode = (NodeBlock*)storage.getFreeBlock(&index);
168+
if (nextNode == NULL) {
169+
// TODO: failed to allocate a new block
170+
}
171+
cur->split(nextNode);
172+
res = nextNode->kv[0];
173+
res.value = index;
174+
return res;
175+
}
176+
return res;
177+
}
178+
179+
void BTree::remove(uint64_t key, NodeBlock* cur) {
180+
uint16_t i = cur->find(key);
181+
182+
if (cur->isLeaf()) {
183+
if (cur->kv[i].key > key) return;
184+
else {
185+
cur->remove(i);
186+
}
187+
}
188+
else {
189+
if (cur->kv[i].key > key) {
190+
i--;
191+
}
192+
NodeBlock* s = (NodeBlock*)storage.getBlock(cur->kv[i].value);
193+
remove(key, s);
194+
195+
// update the key in parent
196+
cur->kv[i].key = s->kv[0].key;
197+
198+
if (s->geMin()) return;
199+
200+
// maintain
201+
if (i > 0) {
202+
NodeBlock *left = (NodeBlock*)storage.getBlock(cur->kv[i - 1].value);
203+
if (left->eMin()) {
204+
// merge
205+
left->merge(s);
206+
cur->remove(i);
207+
208+
storage.freeBlock(s->header.index);
209+
}
210+
else {
211+
s->insert(left->kv[left->header.count - 1], 0);
212+
left->remove(left->header.count - 1);
213+
}
214+
}
215+
else {
216+
NodeBlock *right = (NodeBlock*)storage.getBlock(cur->kv[i + 1].value);
217+
if (right->eMin()) {
218+
// merge
219+
s->merge(right);
220+
cur->remove(i + 1);
221+
222+
storage.freeBlock(right->header.index);
223+
}
224+
else {
225+
s->insert(right->kv[0], s->header.count);
226+
right->remove(0);
227+
cur->kv[i + 1].key = right->kv[0].key;
228+
}
229+
}
230+
}
231+
}
232+
233+
162234
int BTree::remove(uint64_t key) {
235+
if (root->empty()) {
236+
return 0;
237+
}
238+
remove(key, root);
239+
if (!root->isLeaf() && root->header.count == 1) {
240+
NodeBlock* s = (NodeBlock*)storage.getBlock(root->kv[0].value);
241+
root = s;
242+
storage.freeBlock(s->header.index);
243+
}
163244
return 0;
164245
}
165246

166-
int BTree::search(uint64_t key, uint32_t* value) {
167-
return 0;
247+
248+
KeyValue BTree::search(uint64_t key, NodeBlock* cur) {
249+
uint16_t i = cur->find(key);
250+
if (cur->isLeaf()) {
251+
if (cur->kv[i].key == key)
252+
return cur->kv[i];
253+
}
254+
else {
255+
if (cur->kv[i].key > key) i--;
256+
NodeBlock* s = (NodeBlock*)storage.getBlock(root->kv[i].value);
257+
return search(key, s);
258+
}
259+
KeyValue res;
260+
res.value = 0;
261+
return res;
262+
}
263+
264+
265+
KeyValue BTree::search(uint64_t key) {
266+
return search(key, root);
168267
}

Project/btree.h

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//
99

1010
#pragma once
11+
#define DEBUG_BTREE
1112

1213
#include <inttypes.h>
1314
#include "block.h"
@@ -30,22 +31,40 @@ struct NodeBlock {
3031
BlockHeader header;
3132

3233
// The first key is empty, if the block is an interior node
34+
#ifdef DEBUG_BTREE
3335
KeyValue kv[4];
36+
#else
37+
KeyValue kv[1];
38+
#endif // DEBUG_BTREE
3439

3540
static uint16_t size();
3641

37-
bool isFull();
42+
bool full();
3843

39-
bool isEmpty();
44+
bool empty();
45+
46+
// equal
47+
bool eMin();
48+
49+
// greater or equal
50+
// no need to maintain
51+
bool geMin();
4052

4153
///
4254
// @brief
43-
// the index of first item whose key is bigger than or equal with `key`
55+
// return the index of first item whose key is not less than `key`
56+
// if keys of all items is less than `key`, return `header.count`
4457
uint16_t find(uint64_t key);
4558

46-
bool insert(KeyValue item, uint16_t index);
59+
void insert(KeyValue item, uint16_t index);
60+
61+
void split(NodeBlock* nextNode);
4762

48-
void split(NodeBlock* nextNode, uint32_t index);
63+
void merge(NodeBlock* nextNode);
64+
65+
bool isLeaf();
66+
67+
void remove(uint16_t index);
4968
};
5069

5170
#pragma pack()
@@ -54,15 +73,15 @@ class BTree {
5473
private:
5574
StorageManager &storage;
5675
NodeBlock* root;
57-
76+
5877
//void setRootIndex(uint32_t index);
5978
KeyValue insert(KeyValue kv, NodeBlock* cur);
60-
int remove(KeyValue kv, NodeBlock* cur);
61-
int search(KeyValue kv, NodeBlock* cur);
79+
void remove(uint64_t key, NodeBlock* cur);
80+
KeyValue search(uint64_t key, NodeBlock* cur);
6281

6382
public:
6483
BTree(StorageManager &s);
6584
int insert(KeyValue kv);
6685
int remove(uint64_t key);
67-
int search(uint64_t key, uint32_t* value);
86+
KeyValue search(uint64_t key);
6887
};

Project/storage.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ void * StorageManager::getFreeBlock(uint32_t *index) {
6161
return b;
6262
}
6363

64+
void StorageManager::freeBlock(uint32_t index) {
65+
RecordBlock *b = (RecordBlock *)readBlock(index);
66+
67+
b->header.next = meta->free;
68+
meta->free = index;
69+
meta->idle++;
70+
}
71+
6472
bool StorageManager::save() {
6573
for (auto &x : buffers) {
6674
if (x.second->header.reserved == 1) {

Project/storage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class StorageManager {
4141

4242
void* getFreeBlock(uint32_t *index);
4343

44+
void freeBlock(uint32_t index);
45+
4446
bool save();
4547

4648
uint32_t getIndexOfRoot();

0 commit comments

Comments
 (0)