MiniOB 1
MiniOB is one mini database, helping developers to learn how database works.
载入中...
搜索中...
未找到
bplus_tree.h
1/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
2miniob is licensed under Mulan PSL v2.
3You can use this software according to the terms and conditions of the Mulan PSL v2.
4You may obtain a copy of Mulan PSL v2 at:
5 http://license.coscl.org.cn/MulanPSL2
6THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9See the Mulan PSL v2 for more details. */
10
11//
12//
13// Created by Xie Meiyi
14// Rewritten by Longda & Wangyunlai
15//
16//
17
18#pragma once
19
20#include <string.h>
21
22#include "common/lang/comparator.h"
23#include "common/lang/memory.h"
24#include "common/lang/sstream.h"
25#include "common/lang/functional.h"
26#include "common/log/log.h"
27#include "sql/parser/parse_defs.h"
28#include "storage/buffer/disk_buffer_pool.h"
29#include "storage/record/record_manager.h"
30#include "storage/index/latch_memo.h"
31#include "storage/index/bplus_tree_log.h"
32
35
46{
47 READ,
48 INSERT,
49 DELETE,
50};
51
57{
58public:
59 void init(AttrType type, int length)
60 {
61 attr_type_ = type;
62 attr_length_ = length;
63 }
64
65 int attr_length() const { return attr_length_; }
66
67 int operator()(const char *v1, const char *v2) const
68 {
69 // TODO: optimized the comparison
70 Value left;
71 left.set_type(attr_type_);
72 left.set_data(v1, attr_length_);
73 Value right;
74 right.set_type(attr_type_);
75 right.set_data(v2, attr_length_);
76 return DataType::type_instance(attr_type_)->compare(left, right);
77 }
78
79private:
80 AttrType attr_type_;
81 int attr_length_;
82};
83
90{
91public:
92 void init(AttrType type, int length) { attr_comparator_.init(type, length); }
93
94 const AttrComparator &attr_comparator() const { return attr_comparator_; }
95
96 int operator()(const char *v1, const char *v2) const
97 {
98 int result = attr_comparator_(v1, v2);
99 if (result != 0) {
100 return result;
101 }
102
103 const RID *rid1 = (const RID *)(v1 + attr_comparator_.attr_length());
104 const RID *rid2 = (const RID *)(v2 + attr_comparator_.attr_length());
105 return RID::compare(rid1, rid2);
106 }
107
108private:
109 AttrComparator attr_comparator_;
110};
111
117{
118public:
119 void init(AttrType type, int length)
120 {
121 attr_type_ = type;
122 attr_length_ = length;
123 }
124
125 int attr_length() const { return attr_length_; }
126
127 string operator()(const char *v) const
128 {
129 Value value(attr_type_, const_cast<char *>(v), attr_length_);
130 return value.to_string();
131 }
132
133private:
134 AttrType attr_type_;
135 int attr_length_;
136};
137
143{
144public:
145 void init(AttrType type, int length) { attr_printer_.init(type, length); }
146
147 const AttrPrinter &attr_printer() const { return attr_printer_; }
148
149 string operator()(const char *v) const
150 {
151 stringstream ss;
152 ss << "{key:" << attr_printer_(v) << ",";
153
154 const RID *rid = (const RID *)(v + attr_printer_.attr_length());
155 ss << "rid:{" << rid->to_string() << "}}";
156 return ss.str();
157 }
158
159private:
160 AttrPrinter attr_printer_;
161};
162
170{
172 {
173 memset(this, 0, sizeof(IndexFileHeader));
174 root_page = BP_INVALID_PAGE_NUM;
175 }
176 PageNum root_page;
179 int32_t attr_length;
180 int32_t key_length;
181 AttrType attr_type;
182
183 const string to_string() const
184 {
185 stringstream ss;
186
187 ss << "attr_length:" << attr_length << ","
188 << "key_length:" << key_length << ","
189 << "attr_type:" << attr_type_to_string(attr_type) << ","
190 << "root_page:" << root_page << ","
191 << "internal_max_size:" << internal_max_size << ","
192 << "leaf_max_size:" << leaf_max_size << ";";
193
194 return ss.str();
195 }
196};
197
207{
208 static constexpr int HEADER_SIZE = 12;
209
210 bool is_leaf;
212 PageNum parent;
213};
214
229{
230 static constexpr int HEADER_SIZE = IndexNode::HEADER_SIZE + 4;
231
232 PageNum next_brother;
236 char array[0];
237};
238
251{
252 static constexpr int HEADER_SIZE = IndexNode::HEADER_SIZE;
253
257 char array[0];
258};
259
267{
268public:
270 virtual ~IndexNodeHandler() = default;
271
274 void init_empty(bool leaf);
275
277 bool is_leaf() const;
278
280 virtual int key_size() const;
282 virtual int value_size() const;
284 virtual int item_size() const;
285
286 void increase_size(int n);
287 int size() const;
288 int max_size() const;
289 int min_size() const;
290 RC set_parent_page_num(PageNum page_num);
291 PageNum parent_page_num() const;
292 PageNum page_num() const;
293
300 bool is_safe(BplusTreeOperationType op, bool is_root_node);
301
305 bool validate() const;
306
307 Frame *frame() const { return frame_; }
308
309 friend string to_string(const IndexNodeHandler &handler);
310
311 RC recover_insert_items(int index, const char *items, int num);
312 RC recover_remove_items(int index, int num);
313
314protected:
320 virtual char *__item_at(int index) const { return nullptr; }
321 char *__key_at(int index) const { return __item_at(index); }
322 char *__value_at(int index) const { return __item_at(index) + key_size(); };
323
324protected:
326 const IndexFileHeader &header_;
327 Frame *frame_ = nullptr;
328 IndexNode *node_ = nullptr;
329};
330
336{
337public:
339 virtual ~LeafIndexNodeHandler() = default;
340
341 RC init_empty();
342 RC set_next_page(PageNum page_num);
343 PageNum next_page() const;
344
345 char *key_at(int index);
346 char *value_at(int index);
347
352 int lookup(const KeyComparator &comparator, const char *key, bool *found = nullptr) const;
353
354 RC insert(int index, const char *key, const char *value);
355 RC remove(int index);
356 int remove(const char *key, const KeyComparator &comparator);
357 RC move_half_to(LeafIndexNodeHandler &other);
358 RC move_first_to_end(LeafIndexNodeHandler &other);
359 RC move_last_to_front(LeafIndexNodeHandler &other);
363 RC move_to(LeafIndexNodeHandler &other);
364
365 bool validate(const KeyComparator &comparator, DiskBufferPool *bp) const;
366
367 friend string to_string(const LeafIndexNodeHandler &handler, const KeyPrinter &printer);
368
369protected:
370 char *__item_at(int index) const override;
371
372 RC append(const char *items, int num);
373 RC append(const char *item);
374 RC preappend(const char *item);
375
376private:
377 LeafIndexNode *leaf_node_ = nullptr;
378};
379
385{
386public:
388 virtual ~InternalIndexNodeHandler() = default;
389
390 RC init_empty();
391 RC create_new_root(PageNum first_page_num, const char *key, PageNum page_num);
392
393 RC insert(const char *key, PageNum page_num, const KeyComparator &comparator);
394 char *key_at(int index);
395 PageNum value_at(int index);
396
400 int value_index(PageNum page_num);
401 void set_key_at(int index, const char *key);
402 void remove(int index);
403
412 int lookup(
413 const KeyComparator &comparator, const char *key, bool *found = nullptr, int *insert_position = nullptr) const;
414
421 RC move_first_to_end(InternalIndexNodeHandler &other);
422 RC move_last_to_front(InternalIndexNodeHandler &other);
424
425 bool validate(const KeyComparator &comparator, DiskBufferPool *bp) const;
426
427 friend string to_string(const InternalIndexNodeHandler &handler, const KeyPrinter &printer);
428
429private:
430 RC insert_items(int index, const char *items, int num);
431 RC append(const char *items, int num);
432 RC append(const char *item);
433 RC preappend(const char *item);
434
435private:
436 char *__item_at(int index) const override;
437
438 int value_size() const override;
439 int item_size() const override;
440
441private:
442 InternalIndexNode *internal_node_ = nullptr;
443};
444
450{
451public:
462 RC create(LogHandler &log_handler, BufferPoolManager &bpm, const char *file_name, AttrType attr_type, int attr_length,
463 int internal_max_size = -1, int leaf_max_size = -1);
464 RC create(LogHandler &log_handler, DiskBufferPool &buffer_pool, AttrType attr_type, int attr_length,
465 int internal_max_size = -1, int leaf_max_size = -1);
466
473 RC open(LogHandler &log_handler, BufferPoolManager &bpm, const char *file_name);
474 RC open(LogHandler &log_handler, DiskBufferPool &buffer_pool);
475
479 RC close();
480
487 RC insert_entry(const char *user_key, const RID *rid);
488
494 RC delete_entry(const char *user_key, const RID *rid);
495
496 bool is_empty() const;
497
503 RC get_entry(const char *user_key, int key_len, list<RID> &rids);
504
505 RC sync();
506
512 bool validate_tree();
513
514public:
515 const IndexFileHeader &file_header() const { return file_header_; }
516 DiskBufferPool &buffer_pool() const { return *disk_buffer_pool_; }
517 LogHandler &log_handler() const { return *log_handler_; }
518
519public:
524 RC recover_update_root_page(BplusTreeMiniTransaction &mtr, PageNum root_page_num);
530
531public:
535 RC print_tree();
536 RC print_leafs();
537
538private:
542 RC print_leaf(Frame *frame);
543 RC print_internal_node_recursive(Frame *frame);
544
545 bool validate_leaf_link(BplusTreeMiniTransaction &mtr);
546 bool validate_node_recursive(BplusTreeMiniTransaction &mtr, Frame *frame);
547
548protected:
555 RC find_leaf(BplusTreeMiniTransaction &mtr, BplusTreeOperationType op, const char *key, Frame *&frame);
556
561
569 const function<PageNum(InternalIndexNodeHandler &)> &child_page_getter, Frame *&frame);
570
575 BplusTreeMiniTransaction &mtr, BplusTreeOperationType op, PageNum page_num, bool is_root_page, Frame *&frame);
576
580 RC delete_entry_internal(BplusTreeMiniTransaction &mtr, Frame *leaf_frame, const char *key);
581
586 template <typename IndexNodeHandlerType>
587 RC split(BplusTreeMiniTransaction &mtr, Frame *frame, Frame *&new_frame);
588
593 template <typename IndexNodeHandlerType>
595
600 template <typename IndexNodeHandlerType>
601 RC coalesce(BplusTreeMiniTransaction &mtr, Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index);
602
607 template <typename IndexNodeHandlerType>
608 RC redistribute(BplusTreeMiniTransaction &mtr, Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index);
609
613 RC insert_entry_into_parent(BplusTreeMiniTransaction &mtr, Frame *frame, Frame *new_frame, const char *key);
614
618 RC insert_entry_into_leaf_node(BplusTreeMiniTransaction &mtr, Frame *frame, const char *pkey, const RID *rid);
619
623 RC create_new_tree(BplusTreeMiniTransaction &mtr, const char *key, const RID *rid);
624
628 void update_root_page_num_locked(BplusTreeMiniTransaction &mtr, PageNum root_page_num);
629
633 RC adjust_root(BplusTreeMiniTransaction &mtr, Frame *root_frame);
634
635private:
636 common::MemPoolItem::item_unique_ptr make_key(const char *user_key, const RID &rid);
637
638protected:
639 LogHandler *log_handler_ = nullptr;
641 bool header_dirty_ = false;
643
644 // 在调整根节点时,需要加上这个锁。
645 // 这个锁可以使用递归读写锁,但是这里偷懒先不改
646 common::SharedMutex root_lock_;
647
648 KeyComparator key_comparator_;
649 KeyPrinter key_printer_;
650
651 unique_ptr<common::MemPoolItem> mem_pool_item_;
652
653private:
654 friend class BplusTreeScanner;
655 friend class BplusTreeTester;
656};
657
663{
664public:
665 BplusTreeScanner(BplusTreeHandler &tree_handler);
667
678 RC open(const char *left_user_key, int left_len, bool left_inclusive, const char *right_user_key, int right_len,
679 bool right_inclusive);
680
690 RC next_entry(RID &rid);
691
696 RC close();
697
698private:
702 RC fix_user_key(const char *user_key, int key_len, bool want_greater, char **fixed_key, bool *should_inclusive);
703
704 void fetch_item(RID &rid);
705
709 bool touch_end();
710
711private:
712 bool inited_ = false;
713 BplusTreeHandler &tree_handler_;
715
719
720 common::MemPoolItem::item_unique_ptr right_key_;
721 int iter_index_ = -1;
722 bool first_emitted_ = false;
723};
属性比较(BplusTree)
Definition: bplus_tree.h:57
属性打印,调试使用(BplusTree)
Definition: bplus_tree.h:117
B+树的实现
Definition: bplus_tree.h:450
RC close()
Definition: bplus_tree.cpp:966
RC get_entry(const char *user_key, int key_len, list< RID > &rids)
获取指定值的record
Definition: bplus_tree.cpp:1545
RC crabing_protocal_fetch_page(BplusTreeMiniTransaction &mtr, BplusTreeOperationType op, PageNum page_num, bool is_root_page, Frame *&frame)
使用crabing protocol 获取页面
Definition: bplus_tree.cpp:1239
RC delete_entry(const char *user_key, const RID *rid)
从IndexHandle句柄对应的索引中删除一个值为(user_key,rid)的索引项
Definition: bplus_tree.cpp:1785
IndexFileHeader file_header_
是否需要更新头页面
Definition: bplus_tree.h:642
void update_root_page_num_locked(BplusTreeMiniTransaction &mtr, PageNum root_page_num)
更新根节点的页号
Definition: bplus_tree.cpp:1445
RC recover_init_header_page(BplusTreeMiniTransaction &mtr, Frame *frame, const IndexFileHeader &header)
恢复初始化头页面
Definition: bplus_tree.cpp:1431
RC left_most_page(BplusTreeMiniTransaction &mtr, Frame *&frame)
找到最左边的叶子节点
Definition: bplus_tree.cpp:1195
RC recover_update_root_page(BplusTreeMiniTransaction &mtr, PageNum root_page_num)
恢复更新ROOT页面
Definition: bplus_tree.cpp:1425
RC adjust_root(BplusTreeMiniTransaction &mtr, Frame *root_frame)
调整根节点
Definition: bplus_tree.cpp:1568
bool header_dirty_
磁盘缓冲池
Definition: bplus_tree.h:641
RC open(LogHandler &log_handler, BufferPoolManager &bpm, const char *file_name)
打开一个B+树
Definition: bplus_tree.cpp:906
RC create(LogHandler &log_handler, BufferPoolManager &bpm, const char *file_name, AttrType attr_type, int attr_length, int internal_max_size=-1, int leaf_max_size=-1)
创建一个B+树
Definition: bplus_tree.cpp:795
RC find_leaf(BplusTreeMiniTransaction &mtr, BplusTreeOperationType op, const char *key, Frame *&frame)
查找叶子节点
Definition: bplus_tree.cpp:1187
RC redistribute(BplusTreeMiniTransaction &mtr, Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index)
重新分配两个相邻节点
Definition: bplus_tree.cpp:1733
bool validate_tree()
Definition: bplus_tree.cpp:1159
RC coalesce(BplusTreeMiniTransaction &mtr, Frame *neighbor_frame, Frame *frame, Frame *parent_frame, int index)
合并两个相邻节点
Definition: bplus_tree.cpp:1686
DiskBufferPool * disk_buffer_pool_
日志处理器
Definition: bplus_tree.h:640
RC print_leaf(Frame *frame)
Definition: bplus_tree.cpp:976
RC insert_entry_into_parent(BplusTreeMiniTransaction &mtr, Frame *frame, Frame *new_frame, const char *key)
在父节点插入一个元素
Definition: bplus_tree.cpp:1299
RC find_leaf_internal(BplusTreeMiniTransaction &mtr, BplusTreeOperationType op, const function< PageNum(InternalIndexNodeHandler &)> &child_page_getter, Frame *&frame)
查找指定的叶子节点
Definition: bplus_tree.cpp:1201
RC delete_entry_internal(BplusTreeMiniTransaction &mtr, Frame *leaf_frame, const char *key)
从叶子节点中删除指定的键值对
Definition: bplus_tree.cpp:1764
RC coalesce_or_redistribute(BplusTreeMiniTransaction &mtr, Frame *frame)
合并或重新分配
Definition: bplus_tree.cpp:1610
RC insert_entry(const char *user_key, const RID *rid)
此函数向IndexHandle对应的索引中插入一个索引项。
Definition: bplus_tree.cpp:1498
RC insert_entry_into_leaf_node(BplusTreeMiniTransaction &mtr, Frame *frame, const char *pkey, const RID *rid)
在叶子节点插入一个元素
Definition: bplus_tree.cpp:1261
RC split(BplusTreeMiniTransaction &mtr, Frame *frame, Frame *&new_frame)
拆分节点
Definition: bplus_tree.cpp:1401
RC print_tree()
Definition: bplus_tree.cpp:1022
RC create_new_tree(BplusTreeMiniTransaction &mtr, const char *key, const RID *rid)
创建一个新的B+树
Definition: bplus_tree.cpp:1459
B+树使用的事务辅助类
Definition: bplus_tree_log.h:170
B+树的扫描器
Definition: bplus_tree.h:663
Frame * current_frame_
使用左右叶子节点和位置来表示扫描的起始位置和终止位置 起始位置和终止位置都是有效的数据
Definition: bplus_tree.h:718
RC fix_user_key(const char *user_key, int key_len, bool want_greater, char **fixed_key, bool *should_inclusive)
Definition: bplus_tree.cpp:2046
RC open(const char *left_user_key, int left_len, bool left_inclusive, const char *right_user_key, int right_len, bool right_inclusive)
扫描指定范围的数据
Definition: bplus_tree.cpp:1828
bool touch_end()
判断是否到了扫描的结束位置
Definition: bplus_tree.cpp:1972
RC close()
关闭当前扫描器
Definition: bplus_tree.cpp:2039
RC next_entry(RID &rid)
获取下一条记录
Definition: bplus_tree.cpp:1985
BufferPool的管理类
Definition: disk_buffer_pool.h:322
virtual int compare(const Value &left, const Value &right) const
Definition: data_type.h:48
BufferPool的实现
Definition: disk_buffer_pool.h:189
页帧
Definition: frame.h:66
IndexNode 仅作为数据在内存或磁盘中的表示IndexNodeHandler 负责对IndexNode做各种操作。 作为一个类来说,虚函数会影响“结构体”真实的内存布局,所以将数据存储与操作分开
Definition: bplus_tree.h:267
virtual char * __item_at(int index) const
获取指定元素的开始内存位置
Definition: bplus_tree.h:320
virtual int item_size() const
存储的键值对的大小。值是指叶子节点中存放的数据
Definition: bplus_tree.cpp:68
void init_empty(bool leaf)
初始化一个新的页面
Definition: bplus_tree.cpp:52
virtual int value_size() const
存储的值的大小。内部节点和叶子节点是不一样的,但是这里返回的是叶子节点存储的大小
Definition: bplus_tree.cpp:62
bool validate() const
验证当前节点是否有问题
Definition: bplus_tree.cpp:143
bool is_leaf() const
是否叶子节点
Definition: bplus_tree.cpp:51
bool is_safe(BplusTreeOperationType op, bool is_root_node)
判断对指定的操作,是否安全的
Definition: bplus_tree.cpp:103
virtual int key_size() const
存储的键值大小
Definition: bplus_tree.cpp:60
内部节点的操作
Definition: bplus_tree.h:385
int lookup(const KeyComparator &comparator, const char *key, bool *found=nullptr, int *insert_position=nullptr) const
Definition: bplus_tree.cpp:513
RC move_half_to(InternalIndexNodeHandler &other)
move half of the items to the other node ends
Definition: bplus_tree.cpp:492
RC move_to(InternalIndexNodeHandler &other)
把当前节点的所有数据都迁移到另一个节点上
Definition: bplus_tree.cpp:584
char * __item_at(int index) const override
获取指定元素的开始内存位置
Definition: bplus_tree.cpp:677
int value_index(PageNum page_num)
Definition: bplus_tree.cpp:561
RC insert(const char *key, PageNum page_num, const KeyComparator &comparator)
insert one entry
Definition: bplus_tree.cpp:473
int item_size() const override
存储的键值对的大小。值是指叶子节点中存放的数据
Definition: bplus_tree.cpp:681
RC append(const char *items, int num)
Definition: bplus_tree.cpp:665
int value_size() const override
存储的值的大小。内部节点和叶子节点是不一样的,但是这里返回的是叶子节点存储的大小
Definition: bplus_tree.cpp:679
键值比较(BplusTree)
Definition: bplus_tree.h:90
键值打印,调试使用(BplusTree)
Definition: bplus_tree.h:143
叶子节点的操作
Definition: bplus_tree.h:336
int lookup(const KeyComparator &comparator, const char *key, bool *found=nullptr) const
Definition: bplus_tree.cpp:226
char * __item_at(int index) const override
获取指定元素的开始内存位置
Definition: bplus_tree.cpp:346
RC move_to(LeafIndexNodeHandler &other)
Definition: bplus_tree.cpp:310
对外提供服务的CLog模块
Definition: log_handler.h:40
属性的值
Definition: value.h:30
Definition: mutex.h:284
BplusTreeOperationType
B+树的操作类型
Definition: bplus_tree.h:46
the meta information of bplus tree
Definition: bplus_tree.h:170
PageNum root_page
根节点在磁盘中的页号
Definition: bplus_tree.h:176
int32_t leaf_max_size
叶子节点最大的键值对数
Definition: bplus_tree.h:178
AttrType attr_type
键值的类型
Definition: bplus_tree.h:181
int32_t internal_max_size
内部节点最大的键值对数
Definition: bplus_tree.h:177
int32_t attr_length
键值的长度
Definition: bplus_tree.h:179
int32_t key_length
attr length + sizeof(RID)
Definition: bplus_tree.h:180
the common part of page describtion of bplus tree
Definition: bplus_tree.h:207
int key_num
当前是叶子节点还是内部节点
Definition: bplus_tree.h:211
PageNum parent
当前页面上一共有多少个键值对
Definition: bplus_tree.h:212
internal page of bplus tree
Definition: bplus_tree.h:251
char array[0]
Definition: bplus_tree.h:257
leaf page of bplus tree
Definition: bplus_tree.h:229
char array[0]
Definition: bplus_tree.h:236
标识一个记录的位置 一个记录是放在某个文件的某个页面的某个槽位。这里不记录文件信息,记录页面和槽位信息
Definition: record.h:35