-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbplustree.c
1652 lines (1473 loc) · 59 KB
/
bplustree.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<fcntl.h>
#include<ctype.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include"bplustree.h"
/*
偏移量的枚举
INVALID_OFFSET非法偏移量
*/
enum {
INVALID_OFFSET = 0xdeadbeef,
};
/*
是否为叶子节点的枚举
叶子节点
非叶子节点
*/
enum {
BPLUS_TREE_LEAF,
BPLUS_TREE_NON_LEAF = 1,
};
/*
兄弟节点的枚举
左兄弟
右兄弟
*/
enum {
LEFT_SIBLING,
RIGHT_SIBLING = 1,
};
/*
内存结构
---------------------------------------------------------------------------------------------------
| | | | | | | | | | | | |
|叶子节点 | node | key | key | key | key | key | data | data | data | data | data |
| | | | | | | | | | | | |
|---------------------------------------------------------------------------------------------------
| | | | | | | | | | | | |
|非叶子节点 | node | key | key | key | key | ptr | ptr | ptr | ptr | ptr | ptr |
| | | | | | | | | | | | |
---------------------------------------------------------------------------------------------------
key和data的个数由_max_entries决定:_max_entries = (_block_size - sizeof(node)) / (sizeof(key_t) + sizeof(long));
一个节点的大小由_block_size决定,容量要包含1个node结构体和3个及以上的key,data
*/
/*16位数据宽度*/
#define ADDR_STR_WIDTH 16
/*B+树节点node末尾的偏移地址,即key的首地址*/
#define offset_ptr(node) ((char *) (node) + sizeof(*node))
/*返回B+树节点末尾地址,强制转换为key_t*,即key的指针*/
#define key(node) ((key_t *)offset_ptr(node))
/*返回B+树节点和key末尾地址,强制转换为long*,即data指针*/
#define data(node) ((long *)(offset_ptr(node) + _max_entries * sizeof(key_t)))
/*返回最后一个key的指针,用于非叶子节点的指向,即第一个ptr*/
#define sub(node) ((off_t *)(offset_ptr(node) + (_max_order - 1) * sizeof(key_t)))
/*
全局静态变量
_block_size--------------------每个节点的大小(容量要包含1个node和3个及以上的key,data)
_max_entries-------------------叶子节点内包含个数最大值
_max_order---------------------非叶子节点内最大关键字个数
*/
static int _block_size;
static int _max_entries;
static int _max_order;
/*
判断是否为叶子节点
*/
static inline int is_leaf(struct bplus_node *node)
{
return node->type == BPLUS_TREE_LEAF;
}
/*
键值二分查找
*/
static int key_binary_search(struct bplus_node *node, key_t target)
{
key_t *arr = key(node);
/*叶子节点:len;非叶子节点:len-1;非叶子节点的key少一个,用于放ptr*/
int len = is_leaf(node) ? node->children : node->children - 1;
int low = -1;
int high = len;
while (low + 1 < high) {
int mid = low + (high - low) / 2;
if (target > arr[mid]) {
low = mid;
} else {
high = mid;
}
}
if (high >= len || arr[high] != target) {
return -high - 1;
} else {
return high;
}
}
/*
查找键值在父节点的第几位
*/
static inline int parent_key_index(struct bplus_node *parent, key_t key)
{
int index = key_binary_search(parent, key);
return index >= 0 ? index : -index - 2;
}
/*
占用缓存区,与cache_defer对应
占用内存,以供使用
缓存不足,assert(0)直接终止程序
*/
static inline struct bplus_node *cache_refer(struct bplus_tree *tree)
{
int i;
for (i = 0; i < MIN_CACHE_NUM; i++) {
if (!tree->used[i]) {
tree->used[i] = 1;
char *buf = tree->caches + _block_size * i;
return (struct bplus_node *) buf;
}
}
assert(0);
}
/*
释放缓冲区,与cache_refer对应
将used重置,能够存放接下来的数据
*/
static inline void cache_defer(struct bplus_tree *tree, struct bplus_node *node)
{
char *buf = (char *) node;
int i = (buf - tree->caches) / _block_size;
tree->used[i] = 0;
}
/*
创建新的节点
*/
static struct bplus_node *node_new(struct bplus_tree *tree)
{
struct bplus_node *node = cache_refer(tree);
node->self = INVALID_OFFSET;
node->parent = INVALID_OFFSET;
node->prev = INVALID_OFFSET;
node->next = INVALID_OFFSET;
node->children = 0;
return node;
}
/*
创建新的非叶子节点
*/
static inline struct bplus_node *non_leaf_new(struct bplus_tree *tree)
{
struct bplus_node *node = node_new(tree);
node->type = BPLUS_TREE_NON_LEAF;
return node;
}
/*
创建新的叶子节点
*/
static inline struct bplus_node *leaf_new(struct bplus_tree *tree)
{
struct bplus_node *node = node_new(tree);
node->type = BPLUS_TREE_LEAF;
return node;
}
/*
根据偏移量从.index获取节点的全部信息,加载到缓冲区
偏移量非法则返回NULL
*/
static struct bplus_node *node_fetch(struct bplus_tree *tree, off_t offset)
{
if (offset == INVALID_OFFSET) {
return NULL;
}
struct bplus_node *node = cache_refer(tree);
int len = pread(tree->fd, node, _block_size, offset);
assert(len == _block_size);
return node;
}
/*
通过节点的偏移量从.index中获取节点的全部信息
*/
static struct bplus_node *node_seek(struct bplus_tree *tree, off_t offset)
{
/*偏移量不合法*/
if (offset == INVALID_OFFSET) {
return NULL;
}
/*偏移量合法*/
int i;
for (i = 0; i < MIN_CACHE_NUM; i++) {
if (!tree->used[i]) {
char *buf = tree->caches + _block_size * i;
int len = pread(tree->fd, buf, _block_size, offset);
assert(len == _block_size);
return (struct bplus_node *) buf;
}
}
assert(0);
}
/*
B+树节点保存
将其保存到index
并将内存内的缓冲区释放
往tree->fd的文件描述符写入
node指向的节点信息和其后面跟随的节点内容
长度为_block_size
偏移量为node->self
*/
static inline void node_flush(struct bplus_tree *tree, struct bplus_node *node)
{
if (node != NULL) {
int len = pwrite(tree->fd, node, _block_size, node->self);
assert(len == _block_size);
cache_defer(tree, node);
}
}
/*
节点加入到树,为新节点分配新的偏移量,即文件大小
判断链表是否为空,判断是否有空闲区块
空闲区块首地址保存在.boot
*/
static off_t new_node_append(struct bplus_tree *tree, struct bplus_node *node)
{
/*.index无空闲区块*/
if (list_empty(&tree->free_blocks)) {
node->self = tree->file_size;
tree->file_size += _block_size;
/*.inedx有空闲区块*/
} else {
struct free_block *block;
block = list_first_entry(&tree->free_blocks, struct free_block, link);
list_del(&block->link);
node->self = block->offset;
free(block);
}
return node->self;
}
/*
从.index删除整个节点,多出一块空闲区块,添加到B+树信息结构体
struct bplus_tree *tree-------------------B+树信息结构体
struct bplus_node *node-------------------要被删除的节点
struct bplus_node *left-------------------左孩子
struct bplus_node *right------------------右孩子
*/
static void node_delete(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *left, struct bplus_node *right)
{
if (left != NULL) {
/*左右孩子均存在*/
if (right != NULL) {
left->next = right->self;
right->prev = left->self;
node_flush(tree, right);
/*左孩子存在,右孩子不存在*/
} else {
left->next = INVALID_OFFSET;
}
node_flush(tree, left);
} else {
/*没有孩子节点*/
if (right != NULL) {
right->prev = INVALID_OFFSET;
node_flush(tree, right);
}
}
assert(node->self != INVALID_OFFSET);
struct free_block *block = malloc(sizeof(*block));
assert(block != NULL);
/*空闲区块指向被删除节点在.index中的偏移量*/
block->offset = node->self;
/*添加空闲区块*/
list_add_tail(&block->link, &tree->free_blocks);
/*释放缓冲区*/
cache_defer(tree, node);
}
/*
更新非叶子节点的指向
struct bplus_tree *tree----------------B+树信息结构体
struct bplus_node *parent--------------父节点
int index------------------------------插入位置
struct bplus_node *sub_node------------要插入的分支
*/
static inline void sub_node_update(struct bplus_tree *tree, struct bplus_node *parent,
int index, struct bplus_node *sub_node)
{
assert(sub_node->self != INVALID_OFFSET);
sub(parent)[index] = sub_node->self;
sub_node->parent = parent->self;
node_flush(tree, sub_node);
}
/*
将分裂的非叶子节点的孩子重定向,并写入.index
struct bplus_tree *tree----------------B+树信息结构体
struct bplus_node *parent--------------分裂的新的非叶子节点
off_t sub_offset-----------------------偏移量,即指向子节点的指针
*/
static inline void sub_node_flush(struct bplus_tree *tree, struct bplus_node *parent, off_t sub_offset)
{
struct bplus_node *sub_node = node_fetch(tree, sub_offset);
assert(sub_node != NULL);
sub_node->parent = parent->self;
node_flush(tree, sub_node);
}
/*
B+树查找
*/
static long bplus_tree_search(struct bplus_tree *tree, key_t key)
{
int ret = -1;
/*返回根节点的结构体*/
struct bplus_node *node = node_seek(tree, tree->root);
while (node != NULL) {
int i = key_binary_search(node, key);
/*到达叶子节点*/
if (is_leaf(node)) {
ret = i >= 0 ? data(node)[i] : -1;
break;
/*未到达叶子节点,循环递归*/
} else {
if (i >= 0) {
node = node_seek(tree, sub(node)[i + 1]);
} else {
i = -i - 1;
node = node_seek(tree, sub(node)[i]);
}
}
}
return ret;
}
/*
左节点添加
设置左右兄弟叶子节点的指向,不存在就设置为非法
struct bplus_tree *tree------------B+树信息结构体
struct bplus_node *node------------B+树要分裂的节点
struct bplus_node *left------------B+树左边的新节点
*/
static void left_node_add(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *left)
{
new_node_append(tree, left);
struct bplus_node *prev = node_fetch(tree, node->prev);
if (prev != NULL) {
prev->next = left->self;
left->prev = prev->self;
node_flush(tree, prev);
} else {
left->prev = INVALID_OFFSET;
}
left->next = node->self;
node->prev = left->self;
}
/*
右节点添加
设置左右兄弟叶子节点的指向,不存在就设置为非法
struct bplus_tree *tree------------B+树信息结构体
struct bplus_node *node------------B+树要分裂的节点
struct bplus_node *right-----------B+树右边的新节点
*/
static void right_node_add(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *right)
{
new_node_append(tree, right);
struct bplus_node *next = node_fetch(tree, node->next);
if (next != NULL) {
next->prev = right->self;
right->next = next->self;
node_flush(tree, next);
} else {
right->next = INVALID_OFFSET;
}
right->prev = node->self;
node->next = right->self;
}
/*非叶子节点插入,声明*/
static key_t non_leaf_insert(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key);
/*
下一层节点满后分裂,建立新的父节点,添加键值
struct bplus_tree *tree-------------B+树信息结构体
struct bplus_node *l_ch-------------B+树左孩子节点
struct bplus_node *r_ch-------------B+树右孩子节点
key_t key---------------------------后继节点的键值
*/
static int parent_node_build(struct bplus_tree *tree, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key)
{
/*左右节点均没有父节点*/
if (l_ch->parent == INVALID_OFFSET && r_ch->parent == INVALID_OFFSET) {
/*左右节点均没有父节点,建立新的父节点*/
struct bplus_node *parent = non_leaf_new(tree);
key(parent)[0] = key;
sub(parent)[0] = l_ch->self;
sub(parent)[1] = r_ch->self;
parent->children = 2;
/*写入新的父节点,升级B+树信息结构体内的root根节点*/
tree->root = new_node_append(tree, parent);
l_ch->parent = parent->self;
r_ch->parent = parent->self;
tree->level++;
/*操作完成,将父节点和子节点记入index*/
node_flush(tree, l_ch);
node_flush(tree, r_ch);
node_flush(tree, parent);
return 0;
/*右节点没有父节点*/
} else if (r_ch->parent == INVALID_OFFSET) {
/*node_fetch(tree, l_ch->parent):从.index文件获取*/
return non_leaf_insert(tree, node_fetch(tree, l_ch->parent), l_ch, r_ch, key);
/*左节点没有父节点*/
} else {
/*node_fetch(tree, r_ch->parent):从.index文件获取*/
return non_leaf_insert(tree, node_fetch(tree, r_ch->parent), l_ch, r_ch, key);
}
}
/*
非叶子节点的分裂插入
insert在spilit左边,insert<spilit
struct bplus_tree *tree------------------B+树信息结构体
struct bplus_node *node------------------原节点
struct bplus_node *left------------------新分裂的节点
struct bplus_node *l_ch------------------左孩子
struct bplus_node *r_ch------------------右孩子
key_t key--------------------------------键值
int insert-------------------------------插入位置
*/
static key_t non_leaf_split_left(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *left, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key, int insert)
{
int i;
key_t split_key;
/*分裂边界spilit=(len+1)/2*/
int split = (_max_order + 1) / 2;
/*左节点添加到树*/
left_node_add(tree, node, left);
/*重新计算左右兄弟节点的孩子*/
int pivot = insert;
left->children = split;
node->children = _max_order - split + 1;
/*将原来的insert~spilit的key和data复制到分裂的左兄弟*/
memmove(&key(left)[0], &key(node)[0], pivot * sizeof(key_t));
memmove(&sub(left)[0], &sub(node)[0], pivot * sizeof(off_t));
/*将原来的insert+1~end的key和data后移1位,方便插入*/
memmove(&key(left)[pivot + 1], &key(node)[pivot], (split - pivot - 1) * sizeof(key_t));
memmove(&sub(left)[pivot + 1], &sub(node)[pivot], (split - pivot - 1) * sizeof(off_t));
/*将分裂的左节点的孩子重定向,写入.index*/
for (i = 0; i < left->children; i++) {
if (i != pivot && i != pivot + 1) {
sub_node_flush(tree, left, sub(left)[i]);
}
}
/*插入新键和子节点,并找到拆分键*/
key(left)[pivot] = key;
/*
插入的非叶子节点有左右两孩子
判断他们在分裂边界的那一边
pivot == split - 1:孩子节点在分裂边界的两边
else:孩子节点均在分裂节点左边
*/
if (pivot == split - 1) {
/*
孩子节点在分裂边界的两边
更新索引,l_ch放到新分裂的非叶子节点
r_ch放到原非叶子节点
*/
sub_node_update(tree, left, pivot, l_ch);
sub_node_update(tree, node, 0, r_ch);
split_key = key;
} else {
/*
两个新的子节点在分裂左节点
更新索引,l_ch和r_ch均放到新分裂的非叶子节点
*/
sub_node_update(tree, left, pivot, l_ch);
sub_node_update(tree, left, pivot + 1, r_ch);
sub(node)[0] = sub(node)[split - 1];
split_key = key(node)[split - 2];
}
/*将原节点分裂边界右边的key和ptr左移*/
memmove(&key(node)[0], &key(node)[split - 1], (node->children - 1) * sizeof(key_t));
memmove(&sub(node)[1], &sub(node)[split], (node->children - 1) * sizeof(off_t));
/*返回前继节点,作为上一层键值*/
return split_key;
}
/*
非叶子节点的分裂插入
insert与spilit重叠,insert==spilit
直接分裂,移动操作减少
struct bplus_tree *tree------------------B+树信息结构体
struct bplus_node *node------------------原节点
struct bplus_node *right-----------------新分裂的节点
struct bplus_node *l_ch------------------左孩子
struct bplus_node *r_ch------------------右孩子
key_t key--------------------------------键值
int insert-------------------------------插入位置
*/
static key_t non_leaf_split_right1(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *right, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key, int insert)
{
int i;
/*分裂边界spilit=(len+1)/2*/
int split = (_max_order + 1) / 2;
/*新分裂的节点添加到树*/
right_node_add(tree, node, right);
/*上一层的键值*/
key_t split_key = key(node)[split - 1];
/*重新计算孩子个数*/
int pivot = 0;
node->children = split;
right->children = _max_order - split + 1;
/*插入key和ptr*/
key(right)[0] = key;
sub_node_update(tree, right, pivot, l_ch);
sub_node_update(tree, right, pivot + 1, r_ch);
/*复制数据到新的分裂节点*/
memmove(&key(right)[pivot + 1], &key(node)[split], (right->children - 2) * sizeof(key_t));
memmove(&sub(right)[pivot + 2], &sub(node)[split + 1], (right->children - 2) * sizeof(off_t));
/*重定向父子结点,写入.index*/
for (i = pivot + 2; i < right->children; i++) {
sub_node_flush(tree, right, sub(right)[i]);
}
/*返回上一层键值*/
return split_key;
}
/*
非叶子节点的分裂插入
insert在spilit右边,insert>spilit
struct bplus_tree *tree------------------B+树信息结构体
struct bplus_node *node------------------原节点
struct bplus_node *right-----------------新分裂的节点
struct bplus_node *l_ch------------------左孩子
struct bplus_node *r_ch------------------右孩子
key_t key--------------------------------键值
int insert-------------------------------插入位置
*/
static key_t non_leaf_split_right2(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *right, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key, int insert)
{
int i;
/*分裂边界spilit=(len+1)/2*/
int split = (_max_order + 1) / 2;
/*右节点添加到树*/
right_node_add(tree, node, right);
/*上一层的键值*/
key_t split_key = key(node)[split];
/*重新计算孩子个数*/
int pivot = insert - split - 1;
node->children = split + 1;
right->children = _max_order - split;
/*复制数据到新的分裂节点*/
memmove(&key(right)[0], &key(node)[split + 1], pivot * sizeof(key_t));
memmove(&sub(right)[0], &sub(node)[split + 1], pivot * sizeof(off_t));
/*插入key和ptr,更新索引*/
key(right)[pivot] = key;
sub_node_update(tree, right, pivot, l_ch);
sub_node_update(tree, right, pivot + 1, r_ch);
/*将原节点insert+1~end的数据移动到新分裂的非叶子节点*/
memmove(&key(right)[pivot + 1], &key(node)[insert], (_max_order - insert - 1) * sizeof(key_t));
memmove(&sub(right)[pivot + 2], &sub(node)[insert + 1], (_max_order - insert - 1) * sizeof(off_t));
/*重定向父子结点,写入.index*/
for (i = 0; i < right->children; i++) {
if (i != pivot && i != pivot + 1) {
sub_node_flush(tree, right, sub(right)[i]);
}
}
/*返回上一层键值*/
return split_key;
}
/*
父节点未满时,非叶子节点的简单插入
struct bplus_tree *tree----------------B+树信息结构体
struct bplus_node *node----------------父节点
struct bplus_node *l_ch----------------左孩子
struct bplus_node *r_ch----------------右孩子
key_t key------------------------------键值
int insert-----------------------------插入位置
*/
static void non_leaf_simple_insert(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key, int insert)
{
/*将insert处原来的值后移*/
memmove(&key(node)[insert + 1], &key(node)[insert], (node->children - 1 - insert) * sizeof(key_t));
memmove(&sub(node)[insert + 2], &sub(node)[insert + 1], (node->children - 1 - insert) * sizeof(off_t));
/*在insert处插入键值,并更新索引*/
key(node)[insert] = key;
sub_node_update(tree, node, insert, l_ch);
sub_node_update(tree, node, insert + 1, r_ch);
node->children++;
}
/*
非叶子节点插入,定义
即生成新的父节点
struct bplus_tree *tree-------------B+树信息结构体
struct bplus_node *node-------------要接入的新的B+树兄弟叶子节点
struct bplus_node *l_ch-------------B+树左孩子节点
struct bplus_node *r_ch-------------B+树右孩子节点
key_t key
*/
static int non_leaf_insert(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *l_ch, struct bplus_node *r_ch, key_t key)
{
/*键值二分查找*/
int insert = key_binary_search(node, key);
assert(insert < 0);
insert = -insert - 1;
/*父节点满,进行分裂*/
if (node->children == _max_order) {
key_t split_key;
/*分裂边界spilit=(len+1)/2*/
int split = (node->children + 1) / 2;
/*生成一个新的分裂的非叶子节点*/
struct bplus_node *sibling = non_leaf_new(tree);
if (insert < split) {
split_key = non_leaf_split_left(tree, node, sibling, l_ch, r_ch, key, insert);
} else if (insert == split) {
split_key = non_leaf_split_right1(tree, node, sibling, l_ch, r_ch, key, insert);
} else {
split_key = non_leaf_split_right2(tree, node, sibling, l_ch, r_ch, key, insert);
}
/*再次建立新的父节点*/
if (insert < split) {
return parent_node_build(tree, sibling, node, split_key);
} else {
return parent_node_build(tree, node, sibling, split_key);
}
/*父节点未满,进行简单的非叶子节点插入,并保存*/
} else {
non_leaf_simple_insert(tree, node, l_ch, r_ch, key, insert);
node_flush(tree, node);
}
return 0;
}
/*
节点分裂插入,插入位置在分裂位置的左边
与leaf_split_right类似
struct bplus_tree *tree-----------B+树信息结构体
struct bplus_node *leaf-----------B+树叶子节点
struct bplus_node *left-----------新的叶子节点
key_t key-------------------------键值
long data-------------------------数据
int insert------------------------插入位置
*/
static key_t leaf_split_left(struct bplus_tree *tree, struct bplus_node *leaf, struct bplus_node *left, key_t key, long data, int insert)
{
/*分裂边界split=(len+1)/2*/
int split = (leaf->children + 1) / 2;
/*节点分裂,设置左右兄弟叶子节点的指向*/
left_node_add(tree, leaf, left);
/*重新设置children的数值*/
int pivot = insert;
left->children = split;
leaf->children = _max_entries - split + 1;
/*
将原叶子节点key[0]-key[insert]的数值复制到左边分裂出的新的叶子节点
将原叶子节点data[0]-data[insert]的数值复制到左边分裂出的新的叶子节点
*/
memmove(&key(left)[0], &key(leaf)[0], pivot * sizeof(key_t));
memmove(&data(left)[0], &data(leaf)[0], pivot * sizeof(long));
/*在insert处插入新的key和data*/
key(left)[pivot] = key;
data(left)[pivot] = data;
/*从原叶子节点将insert到split的值放到新的叶子节点insert+1处*/
memmove(&key(left)[pivot + 1], &key(leaf)[pivot], (split - pivot - 1) * sizeof(key_t));
memmove(&data(left)[pivot + 1], &data(leaf)[pivot], (split - pivot - 1) * sizeof(long));
/*将原叶子节点insert+1~end的key和data复制到原叶子节点key[0]*/
memmove(&key(leaf)[0], &key(leaf)[split - 1], leaf->children * sizeof(key_t));
memmove(&data(leaf)[0], &data(leaf)[split - 1], leaf->children * sizeof(long));
/*返回后继节点的key,即原叶子节点现在的key[0]*/
return key(leaf)[0];
}
/*
节点分裂插入,插入位置在分裂位置的右边
与leaf_split_left类似
struct bplus_tree *tree-----------B+树信息结构体
struct bplus_node *leaf-----------B+树叶子节点
struct bplus_node *right----------新的叶子节点
key_t key-------------------------键值
long data-------------------------数据
int insert------------------------插入位置
*/
static key_t leaf_split_right(struct bplus_tree *tree, struct bplus_node *leaf, struct bplus_node *right, key_t key, long data, int insert)
{
/*分裂边界split=(len+1)/2*/
int split = (leaf->children + 1) / 2;
/*节点分裂,设置左右兄弟叶子节点的指向*/
right_node_add(tree, leaf, right);
/*重新设置children的数值*/
int pivot = insert - split;
leaf->children = split;
right->children = _max_entries - split + 1;
/*将原叶子节点spilt~insert的key和data复制到右边分裂出的新的叶子节点*/
memmove(&key(right)[0], &key(leaf)[split], pivot * sizeof(key_t));
memmove(&data(right)[0], &data(leaf)[split], pivot * sizeof(long));
/*在insert处插入新的key和data*/
key(right)[pivot] = key;
data(right)[pivot] = data;
/*移动剩余的数据*/
memmove(&key(right)[pivot + 1], &key(leaf)[insert], (_max_entries - insert) * sizeof(key_t));
memmove(&data(right)[pivot + 1], &data(leaf)[insert], (_max_entries - insert) * sizeof(long));
/*返回后继节点的key,即分裂的叶子节点的key[0]*/
return key(right)[0];
}
/*
叶子节点在未满时的简单插入
struct bplus_tree *tree--------------------B+树信息结构体
struct bplus_node *leaf--------------------B+树节点结构体,要插入的位置的上一个节点
key_t key----------------------------------键值
long data----------------------------------数据
int intsert--------------------------------要插入的节点位序
两个memmove是将在insert之前的数据往后存放,使得数据能够插入
*/
static void leaf_simple_insert(struct bplus_tree *tree, struct bplus_node *leaf, key_t key, long data, int insert)
{
memmove(&key(leaf)[insert + 1], &key(leaf)[insert], (leaf->children - insert) * sizeof(key_t));
memmove(&data(leaf)[insert + 1], &data(leaf)[insert], (leaf->children - insert) * sizeof(long));
key(leaf)[insert] = key;
data(leaf)[insert] = data;
leaf->children++;
}
/*
插入叶子节点
struct bplus_tree *tree--------------------B+树信息结构体
struct bplus_node *leaf--------------------B+树节点结构体,要插入的位置的上一个节点
key_t key----------------------------------键值
long data----------------------------------数据
*/
static int leaf_insert(struct bplus_tree *tree, struct bplus_node *leaf, key_t key, long data)
{
/*键值二分查找*/
int insert = key_binary_search(leaf, key);
/*已存在键值*/
if (insert >= 0) {
return -1;
}
insert = -insert - 1;
/*从空闲节点缓存中获取*/
int i = ((char *) leaf - tree->caches) / _block_size;
tree->used[i] = 1;
/*叶子节点满*/
if (leaf->children == _max_entries) {
key_t split_key;
/*节点分裂边界split=(len+1)/2*/
int split = (_max_entries + 1) / 2;
struct bplus_node *sibling = leaf_new(tree);
/*
由插入位置决定的兄弟叶复制
insert < split:插入位置在分裂位置的左边
insert >= split:插入位置在分裂位置的右边
返回后继节点,以放入父节点作为键值
*/
if (insert < split) {
split_key = leaf_split_left(tree, leaf, sibling, key, data, insert);
} else {
split_key = leaf_split_right(tree, leaf, sibling, key, data, insert);
}
/*建立新的父节点*/
if (insert < split) {
return parent_node_build(tree, sibling, leaf, split_key);
} else {
return parent_node_build(tree, leaf, sibling, split_key);
}
/*叶子节点未满*/
} else {
leaf_simple_insert(tree, leaf, key, data, insert);
node_flush(tree, leaf);
}
return 0;
}
/*
插入节点
*/
static int bplus_tree_insert(struct bplus_tree *tree, key_t key, long data)
{
struct bplus_node *node = node_seek(tree, tree->root);
while (node != NULL) {
/*到达叶子节点*/
if (is_leaf(node)) {
return leaf_insert(tree, node, key, data);
/*还未到达叶子节点,继续循环递归查找*/
} else {
int i = key_binary_search(node, key);
if (i >= 0) {
node = node_seek(tree, sub(node)[i + 1]);
} else {
i = -i - 1;
node = node_seek(tree, sub(node)[i]);
}
}
}
/*
创建新的叶子节点
在B+树后面跟随赋值key和data
添加key:key(root)[0] = key;
添加data:data(root)[0] = data;
插入树:tree->root = new_node_append(tree, root);
刷新缓冲区:node_flush(tree, root);
*/
struct bplus_node *root = leaf_new(tree);
key(root)[0] = key;
data(root)[0] = data;
root->children = 1;
tree->root = new_node_append(tree, root);
tree->level = 1;
node_flush(tree, root);
return 0;
}
/*
struct bplus_node *l_sib------------------左兄弟
struct bplus_node *r_sib------------------右兄弟
struct bplus_node *parent-----------------父节点
int i-------------------------------------键值在父节点中的位置
*/
static inline int sibling_select(struct bplus_node *l_sib, struct bplus_node *r_sib, struct bplus_node *parent, int i)
{
if (i == -1) {
/*没有左兄弟,选择右兄弟合并*/
return RIGHT_SIBLING;
} else if (i == parent->children - 2) {
/*没有右兄弟,选择左兄弟*/
return LEFT_SIBLING;
} else {
/*有左右兄弟,选择孩子更多的节点*/
return l_sib->children >= r_sib->children ? LEFT_SIBLING : RIGHT_SIBLING;
}
}
/*
非叶子节点从左兄弟拿一个值
*/
static void non_leaf_shift_from_left(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *left, struct bplus_node *parent, int parent_key_index, int remove)
{
memmove(&key(node)[1], &key(node)[0], remove * sizeof(key_t));
memmove(&sub(node)[1], &sub(node)[0], (remove + 1) * sizeof(off_t));
key(node)[0] = key(parent)[parent_key_index];
key(parent)[parent_key_index] = key(left)[left->children - 2];
sub(node)[0] = sub(left)[left->children - 1];
sub_node_flush(tree, node, sub(node)[0]);
left->children--;
}
/*
非叶子节点合并到左兄弟
*/
static void non_leaf_merge_into_left(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *left, struct bplus_node *parent, int parent_key_index, int remove)
{
/*键值下移*/
key(left)[left->children - 1] = key(parent)[parent_key_index];
memmove(&key(left)[left->children], &key(node)[0], remove * sizeof(key_t));
memmove(&sub(left)[left->children], &sub(node)[0], (remove + 1) * sizeof(off_t));
memmove(&key(left)[left->children + remove], &key(node)[remove + 1], (node->children - remove - 2) * sizeof(key_t));
memmove(&sub(left)[left->children + remove + 1], &sub(node)[remove + 2], (node->children - remove - 2) * sizeof(off_t));
int i, j;
for (i = left->children, j = 0; j < node->children - 1; i++, j++) {
sub_node_flush(tree, left, sub(left)[i]);
}
left->children += node->children - 1;
}
/*
非叶子节点从右兄弟拿一个值
*/
static void non_leaf_shift_from_right(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *right, struct bplus_node *parent, int parent_key_index)
{
key(node)[node->children - 1] = key(parent)[parent_key_index];
key(parent)[parent_key_index] = key(right)[0];
sub(node)[node->children] = sub(right)[0];
sub_node_flush(tree, node, sub(node)[node->children]);
node->children++;
memmove(&key(right)[0], &key(right)[1], (right->children - 2) * sizeof(key_t));
memmove(&sub(right)[0], &sub(right)[1], (right->children - 1) * sizeof(off_t));
right->children--;
}
/*
非叶子节点合并到右兄弟
*/
static void non_leaf_merge_from_right(struct bplus_tree *tree, struct bplus_node *node, struct bplus_node *right, struct bplus_node *parent, int parent_key_index)
{
key(node)[node->children - 1] = key(parent)[parent_key_index];
node->children++;
memmove(&key(node)[node->children - 1], &key(right)[0], (right->children - 1) * sizeof(key_t));
memmove(&sub(node)[node->children - 1], &sub(right)[0], right->children * sizeof(off_t));
int i, j;
for (i = node->children - 1, j = 0; j < right->children; i++, j++) {
sub_node_flush(tree, node, sub(node)[i]);
}
node->children += right->children - 1;
}
/*
非叶子节点的简单删除
*/
static inline void non_leaf_simple_remove(struct bplus_tree *tree, struct bplus_node *node, int remove)
{
assert(node->children >= 2);
memmove(&key(node)[remove], &key(node)[remove + 1], (node->children - remove - 2) * sizeof(key_t));