bplustree.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /*************************************************************************
  2. *
  3. * Copyright 2018 Realm Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. **************************************************************************/
  18. #ifndef REALM_BPLUSTREE_HPP
  19. #define REALM_BPLUSTREE_HPP
  20. #include <realm/column_type_traits.hpp>
  21. #include <realm/decimal128.hpp>
  22. #include <realm/timestamp.hpp>
  23. #include <realm/object_id.hpp>
  24. #include <realm/util/function_ref.hpp>
  25. namespace realm {
  26. class BPlusTreeBase;
  27. class BPlusTreeInner;
  28. /*****************************************************************************/
  29. /* BPlusTreeNode */
  30. /* Base class for all nodes in the BPlusTree. Provides an abstract interface */
  31. /* that can be used by the BPlusTreeBase class to manipulate the tree. */
  32. /*****************************************************************************/
  33. class BPlusTreeNode {
  34. public:
  35. struct State {
  36. int64_t split_offset;
  37. size_t split_size;
  38. };
  39. // Insert an element at 'insert_pos'. May cause node to be split
  40. using InsertFunc = util::FunctionRef<size_t(BPlusTreeNode*, size_t insert_pos)>;
  41. // Access element at 'ndx'. Insertion/deletion not allowed
  42. using AccessFunc = util::FunctionRef<void(BPlusTreeNode*, size_t ndx)>;
  43. // Erase element at erase_pos. May cause nodes to be merged
  44. using EraseFunc = util::FunctionRef<size_t(BPlusTreeNode*, size_t erase_pos)>;
  45. // Function to be called for all leaves in the tree until the function
  46. // returns 'true'. 'offset' gives index of the first element in the leaf.
  47. using TraverseFunc = util::FunctionRef<bool(BPlusTreeNode*, size_t offset)>;
  48. BPlusTreeNode(BPlusTreeBase* tree)
  49. : m_tree(tree)
  50. {
  51. }
  52. void change_owner(BPlusTreeBase* tree)
  53. {
  54. m_tree = tree;
  55. }
  56. bool get_context_flag() const noexcept;
  57. void set_context_flag(bool) noexcept;
  58. virtual ~BPlusTreeNode();
  59. virtual bool is_leaf() const = 0;
  60. virtual bool is_compact() const = 0;
  61. virtual ref_type get_ref() const = 0;
  62. virtual void init_from_ref(ref_type ref) noexcept = 0;
  63. virtual void bp_set_parent(ArrayParent* parent, size_t ndx_in_parent) = 0;
  64. virtual void update_parent() = 0;
  65. // Number of elements in this node
  66. virtual size_t get_node_size() const = 0;
  67. // Size of subtree
  68. virtual size_t get_tree_size() const = 0;
  69. virtual ref_type bptree_insert(size_t n, State& state, InsertFunc) = 0;
  70. virtual void bptree_access(size_t n, AccessFunc) = 0;
  71. virtual size_t bptree_erase(size_t n, EraseFunc) = 0;
  72. virtual bool bptree_traverse(TraverseFunc) = 0;
  73. // Move elements over in new node, starting with element at position 'ndx'.
  74. // If this is an inner node, the index offsets should be adjusted with 'adj'
  75. virtual void move(BPlusTreeNode* new_node, size_t ndx, int64_t offset_adj) = 0;
  76. virtual void verify() const = 0;
  77. protected:
  78. BPlusTreeBase* m_tree;
  79. };
  80. /*****************************************************************************/
  81. /* BPlusTreeLeaf */
  82. /* Base class for all leaf nodes. */
  83. /*****************************************************************************/
  84. class BPlusTreeLeaf : public BPlusTreeNode {
  85. public:
  86. using BPlusTreeNode::BPlusTreeNode;
  87. bool is_leaf() const override
  88. {
  89. return true;
  90. }
  91. bool is_compact() const override
  92. {
  93. return true;
  94. }
  95. ref_type bptree_insert(size_t n, State& state, InsertFunc) override;
  96. void bptree_access(size_t n, AccessFunc) override;
  97. size_t bptree_erase(size_t n, EraseFunc) override;
  98. bool bptree_traverse(TraverseFunc) override;
  99. };
  100. /*****************************************************************************/
  101. /* BPlusTreeBase */
  102. /* Base class for the actual tree classes. */
  103. /*****************************************************************************/
  104. class BPlusTreeBase {
  105. public:
  106. BPlusTreeBase(Allocator& alloc)
  107. : m_alloc(alloc)
  108. {
  109. invalidate_leaf_cache();
  110. }
  111. virtual ~BPlusTreeBase();
  112. Allocator& get_alloc() const
  113. {
  114. return m_alloc;
  115. }
  116. bool is_attached() const
  117. {
  118. return bool(m_root);
  119. }
  120. bool get_context_flag() const noexcept
  121. {
  122. return m_root->get_context_flag();
  123. }
  124. void set_context_flag(bool cf) noexcept
  125. {
  126. m_root->set_context_flag(cf);
  127. }
  128. size_t size() const
  129. {
  130. return m_size;
  131. }
  132. bool is_empty() const
  133. {
  134. return m_size == 0;
  135. }
  136. ref_type get_ref() const
  137. {
  138. REALM_ASSERT(is_attached());
  139. return m_root->get_ref();
  140. }
  141. void init_from_ref(ref_type ref)
  142. {
  143. auto new_root = create_root_from_ref(ref);
  144. new_root->bp_set_parent(m_parent, m_ndx_in_parent);
  145. m_root = std::move(new_root);
  146. invalidate_leaf_cache();
  147. m_size = m_root->get_tree_size();
  148. }
  149. bool init_from_parent()
  150. {
  151. ref_type ref = m_parent->get_child_ref(m_ndx_in_parent);
  152. if (!ref) {
  153. return false;
  154. }
  155. auto new_root = create_root_from_ref(ref);
  156. new_root->bp_set_parent(m_parent, m_ndx_in_parent);
  157. m_root = std::move(new_root);
  158. invalidate_leaf_cache();
  159. m_size = m_root->get_tree_size();
  160. return true;
  161. }
  162. void set_parent(ArrayParent* parent, size_t ndx_in_parent)
  163. {
  164. m_parent = parent;
  165. m_ndx_in_parent = ndx_in_parent;
  166. if (is_attached())
  167. m_root->bp_set_parent(parent, ndx_in_parent);
  168. }
  169. void create();
  170. void destroy();
  171. void verify() const
  172. {
  173. m_root->verify();
  174. }
  175. protected:
  176. template <class U>
  177. struct LeafTypeTrait {
  178. using type = typename ColumnTypeTraits<U>::cluster_leaf_type;
  179. };
  180. friend class BPlusTreeInner;
  181. friend class BPlusTreeLeaf;
  182. std::unique_ptr<BPlusTreeNode> m_root;
  183. Allocator& m_alloc;
  184. ArrayParent* m_parent = nullptr;
  185. size_t m_ndx_in_parent = 0;
  186. size_t m_size = 0;
  187. size_t m_cached_leaf_begin;
  188. size_t m_cached_leaf_end;
  189. void set_leaf_bounds(size_t b, size_t e)
  190. {
  191. m_cached_leaf_begin = b;
  192. m_cached_leaf_end = e;
  193. }
  194. void invalidate_leaf_cache()
  195. {
  196. m_cached_leaf_begin = size_t(-1);
  197. m_cached_leaf_end = size_t(-1);
  198. }
  199. void adjust_leaf_bounds(int incr)
  200. {
  201. m_cached_leaf_end += incr;
  202. }
  203. void bptree_insert(size_t n, BPlusTreeNode::InsertFunc func);
  204. void bptree_erase(size_t n, BPlusTreeNode::EraseFunc func);
  205. // Create an un-attached leaf node
  206. virtual std::unique_ptr<BPlusTreeLeaf> create_leaf_node() = 0;
  207. // Create a leaf node and initialize it with 'ref'
  208. virtual std::unique_ptr<BPlusTreeLeaf> init_leaf_node(ref_type ref) = 0;
  209. // Initialize the leaf cache with 'mem'
  210. virtual BPlusTreeLeaf* cache_leaf(MemRef mem) = 0;
  211. virtual void replace_root(std::unique_ptr<BPlusTreeNode> new_root);
  212. std::unique_ptr<BPlusTreeNode> create_root_from_ref(ref_type ref);
  213. };
  214. template <>
  215. struct BPlusTreeBase::LeafTypeTrait<ObjKey> {
  216. using type = ArrayKeyNonNullable;
  217. };
  218. /*****************************************************************************/
  219. /* BPlusTree */
  220. /* Actual implementation of the BPlusTree to hold elements of type T. */
  221. /*****************************************************************************/
  222. template <class T>
  223. class BPlusTree : public BPlusTreeBase {
  224. public:
  225. using LeafArray = typename LeafTypeTrait<T>::type;
  226. /**
  227. * Actual class for the leaves. Maps the abstract interface defined
  228. * in BPlusTreeNode onto the specific array class
  229. **/
  230. class LeafNode : public BPlusTreeLeaf, public LeafArray {
  231. public:
  232. LeafNode(BPlusTreeBase* tree)
  233. : BPlusTreeLeaf(tree)
  234. , LeafArray(tree->get_alloc())
  235. {
  236. }
  237. void init_from_ref(ref_type ref) noexcept override
  238. {
  239. LeafArray::init_from_ref(ref);
  240. }
  241. ref_type get_ref() const override
  242. {
  243. return LeafArray::get_ref();
  244. }
  245. void bp_set_parent(realm::ArrayParent* p, size_t n) override
  246. {
  247. LeafArray::set_parent(p, n);
  248. }
  249. void update_parent() override
  250. {
  251. LeafArray::update_parent();
  252. }
  253. size_t get_node_size() const override
  254. {
  255. return LeafArray::size();
  256. }
  257. size_t get_tree_size() const override
  258. {
  259. return LeafArray::size();
  260. }
  261. void move(BPlusTreeNode* new_node, size_t ndx, int64_t) override
  262. {
  263. LeafNode* dst(static_cast<LeafNode*>(new_node));
  264. LeafArray::move(*dst, ndx);
  265. }
  266. void verify() const override
  267. {
  268. LeafArray::verify();
  269. }
  270. };
  271. BPlusTree(Allocator& alloc)
  272. : BPlusTreeBase(alloc)
  273. , m_leaf_cache(this)
  274. {
  275. }
  276. /************ Tree manipulation functions ************/
  277. static T default_value(bool nullable = false)
  278. {
  279. return LeafArray::default_value(nullable);
  280. }
  281. void add(T value)
  282. {
  283. insert(npos, value);
  284. }
  285. void insert(size_t n, T value)
  286. {
  287. auto func = [value](BPlusTreeNode* node, size_t ndx) {
  288. LeafNode* leaf = static_cast<LeafNode*>(node);
  289. leaf->LeafArray::insert(ndx, value);
  290. return leaf->size();
  291. };
  292. bptree_insert(n, func);
  293. m_size++;
  294. }
  295. inline T get(size_t n) const
  296. {
  297. // Fast path
  298. if (m_cached_leaf_begin <= n && n < m_cached_leaf_end) {
  299. return m_leaf_cache.get(n - m_cached_leaf_begin);
  300. }
  301. else {
  302. // Slow path
  303. return get_uncached(n);
  304. }
  305. }
  306. REALM_NOINLINE T get_uncached(size_t n) const
  307. {
  308. T value;
  309. auto func = [&value](BPlusTreeNode* node, size_t ndx) {
  310. LeafNode* leaf = static_cast<LeafNode*>(node);
  311. value = leaf->get(ndx);
  312. };
  313. m_root->bptree_access(n, func);
  314. return value;
  315. }
  316. std::vector<T> get_all() const
  317. {
  318. std::vector<T> all_values;
  319. all_values.reserve(m_size);
  320. auto func = [&all_values](BPlusTreeNode* node, size_t) {
  321. LeafNode* leaf = static_cast<LeafNode*>(node);
  322. size_t sz = leaf->size();
  323. for (size_t i = 0; i < sz; i++) {
  324. all_values.push_back(leaf->get(i));
  325. }
  326. return false;
  327. };
  328. m_root->bptree_traverse(func);
  329. return all_values;
  330. }
  331. void set(size_t n, T value)
  332. {
  333. auto func = [value](BPlusTreeNode* node, size_t ndx) {
  334. LeafNode* leaf = static_cast<LeafNode*>(node);
  335. leaf->set(ndx, value);
  336. };
  337. m_root->bptree_access(n, func);
  338. }
  339. void swap(size_t ndx1, size_t ndx2)
  340. {
  341. if constexpr (std::is_same_v<T, StringData> || std::is_same_v<T, BinaryData>) {
  342. struct SwapBuffer {
  343. std::string val;
  344. bool n;
  345. SwapBuffer(T v)
  346. : val(v.data(), v.size())
  347. , n(v.is_null())
  348. {
  349. }
  350. T get()
  351. {
  352. return n ? T() : T(val);
  353. }
  354. };
  355. SwapBuffer tmp1{get(ndx1)};
  356. SwapBuffer tmp2{get(ndx2)};
  357. set(ndx1, tmp2.get());
  358. set(ndx2, tmp1.get());
  359. }
  360. else {
  361. T tmp = get(ndx1);
  362. set(ndx1, get(ndx2));
  363. set(ndx2, tmp);
  364. }
  365. }
  366. void erase(size_t n)
  367. {
  368. auto func = [](BPlusTreeNode* node, size_t ndx) {
  369. LeafNode* leaf = static_cast<LeafNode*>(node);
  370. leaf->LeafArray::erase(ndx);
  371. return leaf->size();
  372. };
  373. bptree_erase(n, func);
  374. m_size--;
  375. }
  376. void clear()
  377. {
  378. if (m_root->is_leaf()) {
  379. LeafNode* leaf = static_cast<LeafNode*>(m_root.get());
  380. leaf->clear();
  381. }
  382. else {
  383. destroy();
  384. create();
  385. if (m_parent) {
  386. m_parent->update_child_ref(m_ndx_in_parent, get_ref());
  387. }
  388. }
  389. m_size = 0;
  390. }
  391. void traverse(BPlusTreeNode::TraverseFunc func) const
  392. {
  393. if (m_root) {
  394. m_root->bptree_traverse(func);
  395. }
  396. }
  397. size_t find_first(T value) const noexcept
  398. {
  399. size_t result = realm::npos;
  400. auto func = [&result, value](BPlusTreeNode* node, size_t offset) {
  401. LeafNode* leaf = static_cast<LeafNode*>(node);
  402. size_t sz = leaf->size();
  403. auto i = leaf->find_first(value, 0, sz);
  404. if (i < sz) {
  405. result = i + offset;
  406. return true;
  407. }
  408. return false;
  409. };
  410. m_root->bptree_traverse(func);
  411. return result;
  412. }
  413. template <typename Func>
  414. void find_all(T value, Func&& callback) const noexcept
  415. {
  416. auto func = [&callback, value](BPlusTreeNode* node, size_t offset) {
  417. LeafNode* leaf = static_cast<LeafNode*>(node);
  418. size_t i = -1, sz = leaf->size();
  419. while ((i = leaf->find_first(value, i + 1, sz)) < sz) {
  420. callback(i + offset);
  421. }
  422. return false;
  423. };
  424. m_root->bptree_traverse(func);
  425. }
  426. void dump_values(std::ostream& o, int level) const
  427. {
  428. std::string indent(" ", level * 2);
  429. auto func = [&o, indent](BPlusTreeNode* node, size_t) {
  430. LeafNode* leaf = static_cast<LeafNode*>(node);
  431. size_t sz = leaf->size();
  432. for (size_t i = 0; i < sz; i++) {
  433. o << indent << leaf->get(i) << std::endl;
  434. }
  435. return false;
  436. };
  437. m_root->bptree_traverse(func);
  438. }
  439. protected:
  440. LeafNode m_leaf_cache;
  441. /******** Implementation of abstract interface *******/
  442. std::unique_ptr<BPlusTreeLeaf> create_leaf_node() override
  443. {
  444. std::unique_ptr<BPlusTreeLeaf> leaf = std::make_unique<LeafNode>(this);
  445. static_cast<LeafNode*>(leaf.get())->create();
  446. return leaf;
  447. }
  448. std::unique_ptr<BPlusTreeLeaf> init_leaf_node(ref_type ref) override
  449. {
  450. std::unique_ptr<BPlusTreeLeaf> leaf = std::make_unique<LeafNode>(this);
  451. leaf->init_from_ref(ref);
  452. return leaf;
  453. }
  454. BPlusTreeLeaf* cache_leaf(MemRef mem) override
  455. {
  456. m_leaf_cache.init_from_mem(mem);
  457. return &m_leaf_cache;
  458. }
  459. void replace_root(std::unique_ptr<BPlusTreeNode> new_root) override
  460. {
  461. // Only copy context flag over in a linklist.
  462. // The flag is in use in other list types
  463. if constexpr (std::is_same_v<T, ObjKey>) {
  464. auto cf = m_root ? m_root->get_context_flag() : false;
  465. BPlusTreeBase::replace_root(std::move(new_root));
  466. m_root->set_context_flag(cf);
  467. }
  468. else {
  469. BPlusTreeBase::replace_root(std::move(new_root));
  470. }
  471. }
  472. template <class R>
  473. friend R bptree_sum(const BPlusTree<T>& tree);
  474. };
  475. template <class T>
  476. inline bool bptree_aggregate_not_null(T)
  477. {
  478. return true;
  479. }
  480. template <class R, class T>
  481. inline R bptree_aggregate_value(T val)
  482. {
  483. return val;
  484. }
  485. template <class T>
  486. inline bool bptree_aggregate_not_null(util::Optional<T> val)
  487. {
  488. return !!val;
  489. }
  490. template <>
  491. inline bool bptree_aggregate_not_null(Timestamp val)
  492. {
  493. return !val.is_null();
  494. }
  495. inline bool bptree_aggregate_not_null(StringData val)
  496. {
  497. return !val.is_null();
  498. }
  499. inline bool bptree_aggregate_not_null(BinaryData val)
  500. {
  501. return !val.is_null();
  502. }
  503. template <>
  504. inline bool bptree_aggregate_not_null(float val)
  505. {
  506. return !null::is_null_float(val);
  507. }
  508. template <>
  509. inline bool bptree_aggregate_not_null(double val)
  510. {
  511. return !null::is_null_float(val);
  512. }
  513. template <>
  514. inline bool bptree_aggregate_not_null(Decimal128 val)
  515. {
  516. return !val.is_null();
  517. }
  518. template <class T>
  519. inline T bptree_aggregate_value(util::Optional<T> val)
  520. {
  521. return *val;
  522. }
  523. template <class T>
  524. ColumnSumType<T> bptree_sum(const BPlusTree<T>& tree, size_t* return_cnt = nullptr)
  525. {
  526. using ResultType = typename AggregateResultType<T, act_Sum>::result_type;
  527. ResultType result{};
  528. size_t cnt = 0;
  529. auto func = [&result, &cnt](BPlusTreeNode* node, size_t) {
  530. auto leaf = static_cast<typename BPlusTree<T>::LeafNode*>(node);
  531. size_t sz = leaf->size();
  532. for (size_t i = 0; i < sz; i++) {
  533. auto val = leaf->get(i);
  534. if (bptree_aggregate_not_null(val)) {
  535. result += bptree_aggregate_value<ResultType>(val);
  536. cnt++;
  537. }
  538. }
  539. return false;
  540. };
  541. tree.traverse(func);
  542. if (return_cnt)
  543. *return_cnt = cnt;
  544. return result;
  545. }
  546. template <class T>
  547. ColumnMinMaxType<T> bptree_maximum(const BPlusTree<T>& tree, size_t* return_ndx = nullptr)
  548. {
  549. using ResultType = typename AggregateResultType<T, act_Max>::result_type;
  550. ResultType max = std::numeric_limits<ResultType>::lowest();
  551. if (tree.size() == 0) {
  552. return max;
  553. }
  554. auto func = [&max, return_ndx](BPlusTreeNode* node, size_t offset) {
  555. auto leaf = static_cast<typename BPlusTree<T>::LeafNode*>(node);
  556. size_t sz = leaf->size();
  557. for (size_t i = 0; i < sz; i++) {
  558. auto val_or_null = leaf->get(i);
  559. if (bptree_aggregate_not_null(val_or_null)) {
  560. auto val = bptree_aggregate_value<ResultType>(val_or_null);
  561. if (val > max) {
  562. max = val;
  563. if (return_ndx) {
  564. *return_ndx = i + offset;
  565. }
  566. }
  567. }
  568. }
  569. return false;
  570. };
  571. tree.traverse(func);
  572. return max;
  573. }
  574. template <class T>
  575. ColumnMinMaxType<T> bptree_minimum(const BPlusTree<T>& tree, size_t* return_ndx = nullptr)
  576. {
  577. using ResultType = typename AggregateResultType<T, act_Max>::result_type;
  578. ResultType min = std::numeric_limits<ResultType>::max();
  579. if (tree.size() == 0) {
  580. return min;
  581. }
  582. auto func = [&min, return_ndx](BPlusTreeNode* node, size_t offset) {
  583. auto leaf = static_cast<typename BPlusTree<T>::LeafNode*>(node);
  584. size_t sz = leaf->size();
  585. for (size_t i = 0; i < sz; i++) {
  586. auto val_or_null = leaf->get(i);
  587. if (bptree_aggregate_not_null(val_or_null)) {
  588. auto val = bptree_aggregate_value<ResultType>(val_or_null);
  589. if (val < min) {
  590. min = val;
  591. if (return_ndx) {
  592. *return_ndx = i + offset;
  593. }
  594. }
  595. }
  596. }
  597. return false;
  598. };
  599. tree.traverse(func);
  600. return min;
  601. }
  602. template <class T>
  603. ColumnAverageType<T> bptree_average(const BPlusTree<T>& tree, size_t* return_cnt = nullptr)
  604. {
  605. size_t cnt;
  606. auto sum = bptree_sum(tree, &cnt);
  607. ColumnAverageType<T> avg{};
  608. if (cnt != 0)
  609. avg = ColumnAverageType<T>(sum) / cnt;
  610. if (return_cnt)
  611. *return_cnt = cnt;
  612. return avg;
  613. }
  614. } // namespace realm
  615. #endif /* REALM_BPLUSTREE_HPP */