cluster.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*************************************************************************
  2. *
  3. * Copyright 2016 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_CLUSTER_HPP
  19. #define REALM_CLUSTER_HPP
  20. #include <realm/keys.hpp>
  21. #include <realm/mixed.hpp>
  22. #include <realm/array.hpp>
  23. #include <realm/array_unsigned.hpp>
  24. #include <realm/data_type.hpp>
  25. #include <realm/column_type_traits.hpp>
  26. namespace realm {
  27. class Spec;
  28. class Table;
  29. class Obj;
  30. class Cluster;
  31. class ClusterNodeInner;
  32. class ClusterTree;
  33. class ColumnAttrMask;
  34. class CascadeState;
  35. struct FieldValue {
  36. FieldValue(ColKey k, Mixed val)
  37. : col_key(k)
  38. , value(val)
  39. {
  40. }
  41. ColKey col_key;
  42. Mixed value;
  43. };
  44. using FieldValues = std::vector<FieldValue>;
  45. class ClusterNode : public Array {
  46. public:
  47. // This structure is used to bring information back to the upper nodes when
  48. // inserting new objects or finding existing ones.
  49. struct State {
  50. int64_t split_key; // When a node is split, this variable holds the value of the
  51. // first key in the new node. (Relative to the key offset)
  52. MemRef mem; // MemRef to the Cluster holding the new/found object
  53. size_t index; // The index within the Cluster at which the object is stored.
  54. };
  55. struct IteratorState {
  56. IteratorState(Cluster& leaf)
  57. : m_current_leaf(leaf)
  58. {
  59. }
  60. IteratorState(const IteratorState&);
  61. void clear();
  62. void init(State&, ObjKey);
  63. Cluster& m_current_leaf;
  64. int64_t m_key_offset = 0;
  65. size_t m_current_index = 0;
  66. };
  67. ClusterNode(uint64_t offset, Allocator& allocator, const ClusterTree& tree_top)
  68. : Array(allocator)
  69. , m_tree_top(tree_top)
  70. , m_keys(allocator)
  71. , m_offset(offset)
  72. {
  73. m_keys.set_parent(this, 0);
  74. }
  75. virtual ~ClusterNode()
  76. {
  77. }
  78. void init_from_parent()
  79. {
  80. ref_type ref = get_ref_from_parent();
  81. char* header = m_alloc.translate(ref);
  82. init(MemRef(header, ref, m_alloc));
  83. }
  84. int64_t get_key_value(size_t ndx) const
  85. {
  86. return m_keys.get(ndx);
  87. }
  88. virtual void update_from_parent() noexcept = 0;
  89. virtual bool is_leaf() const = 0;
  90. virtual int get_sub_tree_depth() const = 0;
  91. virtual size_t node_size() const = 0;
  92. /// Number of elements in this subtree
  93. virtual size_t get_tree_size() const = 0;
  94. /// Last key in this subtree
  95. virtual int64_t get_last_key_value() const = 0;
  96. virtual void ensure_general_form() = 0;
  97. /// Initialize node from 'mem'
  98. virtual void init(MemRef mem) = 0;
  99. /// Descend the tree from the root and copy-on-write the leaf
  100. /// This will update all parents accordingly
  101. virtual MemRef ensure_writeable(ObjKey k) = 0;
  102. /// A leaf cluster has got a new ref. Descend the tree from the root,
  103. /// find the leaf and update the ref in the parent node
  104. virtual void update_ref_in_parent(ObjKey k, ref_type ref) = 0;
  105. /// Init and potentially Insert a column
  106. virtual void insert_column(ColKey col) = 0;
  107. /// Clear and potentially Remove a column
  108. virtual void remove_column(ColKey col) = 0;
  109. /// Return number of columns created. To be used by upgrade logic
  110. virtual size_t nb_columns() const
  111. {
  112. return realm::npos;
  113. }
  114. /// Create a new object identified by 'key' and update 'state' accordingly
  115. /// Return reference to new node created (if any)
  116. virtual ref_type insert(ObjKey k, const FieldValues& init_values, State& state) = 0;
  117. /// Locate object identified by 'key' and update 'state' accordingly
  118. void get(ObjKey key, State& state) const;
  119. /// Locate object identified by 'key' and update 'state' accordingly
  120. /// Returns `false` if the object doesn't not exist.
  121. virtual bool try_get(ObjKey key, State& state) const = 0;
  122. /// Locate object identified by 'ndx' and update 'state' accordingly
  123. virtual ObjKey get(size_t ndx, State& state) const = 0;
  124. /// Return the index at which key is stored
  125. virtual size_t get_ndx(ObjKey key, size_t ndx) const = 0;
  126. /// Erase element identified by 'key'
  127. virtual size_t erase(ObjKey key, CascadeState& state) = 0;
  128. /// Nullify links pointing to element identified by 'key'
  129. virtual void nullify_incoming_links(ObjKey key, CascadeState& state) = 0;
  130. /// Move elements from position 'ndx' to 'new_node'. The new node is supposed
  131. /// to be a sibling positioned right after this one. All key values must
  132. /// be subtracted 'key_adj'
  133. virtual void move(size_t ndx, ClusterNode* new_leaf, int64_t key_adj) = 0;
  134. virtual void dump_objects(int64_t key_offset, std::string lead) const = 0;
  135. ObjKey get_real_key(size_t ndx) const
  136. {
  137. return ObjKey(get_key_value(ndx) + m_offset);
  138. }
  139. const ClusterKeyArray* get_key_array() const
  140. {
  141. return &m_keys;
  142. }
  143. void set_offset(uint64_t offs)
  144. {
  145. m_offset = offs;
  146. }
  147. uint64_t get_offset() const
  148. {
  149. return m_offset;
  150. }
  151. protected:
  152. #if REALM_MAX_BPNODE_SIZE > 256
  153. static constexpr int node_shift_factor = 8;
  154. #else
  155. static constexpr int node_shift_factor = 2;
  156. #endif
  157. static constexpr size_t cluster_node_size = 1 << node_shift_factor;
  158. const ClusterTree& m_tree_top;
  159. ClusterKeyArray m_keys;
  160. uint64_t m_offset;
  161. };
  162. class Cluster : public ClusterNode {
  163. public:
  164. Cluster(uint64_t offset, Allocator& allocator, const ClusterTree& tree_top)
  165. : ClusterNode(offset, allocator, tree_top)
  166. {
  167. }
  168. ~Cluster() override;
  169. static MemRef create_empty_cluster(Allocator& alloc);
  170. void create(); // Note: leaf columns - may include holes
  171. void init(MemRef mem) override;
  172. void update_from_parent() noexcept override;
  173. bool is_writeable() const
  174. {
  175. return !Array::is_read_only();
  176. }
  177. MemRef ensure_writeable(ObjKey k) override;
  178. void update_ref_in_parent(ObjKey, ref_type ref) override;
  179. bool is_leaf() const override
  180. {
  181. return true;
  182. }
  183. int get_sub_tree_depth() const override
  184. {
  185. return 0;
  186. }
  187. static size_t node_size_from_header(Allocator& alloc, const char* header);
  188. size_t node_size() const override
  189. {
  190. if (!is_attached()) {
  191. return 0;
  192. }
  193. return m_keys.is_attached() ? m_keys.size() : get_size_in_compact_form();
  194. }
  195. size_t get_tree_size() const override
  196. {
  197. return node_size();
  198. }
  199. int64_t get_last_key_value() const override
  200. {
  201. auto sz = node_size();
  202. return sz ? get_key_value(sz - 1) : -1;
  203. }
  204. size_t lower_bound_key(ObjKey key) const
  205. {
  206. if (m_keys.is_attached()) {
  207. return m_keys.lower_bound(uint64_t(key.value));
  208. }
  209. else {
  210. size_t sz = size_t(Array::get(0)) >> 1;
  211. if (key.value < 0)
  212. return 0;
  213. if (size_t(key.value) > sz)
  214. return sz;
  215. }
  216. return size_t(key.value);
  217. }
  218. void adjust_keys(int64_t offset)
  219. {
  220. ensure_general_form();
  221. m_keys.adjust(0, m_keys.size(), offset);
  222. }
  223. const Table* get_owning_table() const;
  224. ColKey get_col_key(size_t ndx_in_parent) const;
  225. void ensure_general_form() override;
  226. void insert_column(ColKey col) override; // Does not move columns!
  227. void remove_column(ColKey col) override; // Does not move columns - may leave a 'hole'
  228. size_t nb_columns() const override
  229. {
  230. return size() - s_first_col_index;
  231. }
  232. ref_type insert(ObjKey k, const FieldValues& init_values, State& state) override;
  233. bool try_get(ObjKey k, State& state) const override;
  234. ObjKey get(size_t, State& state) const override;
  235. size_t get_ndx(ObjKey key, size_t ndx) const override;
  236. size_t erase(ObjKey k, CascadeState& state) override;
  237. void nullify_incoming_links(ObjKey key, CascadeState& state) override;
  238. void upgrade_string_to_enum(ColKey col, ArrayString& keys);
  239. void init_leaf(ColKey col, ArrayPayload* leaf) const;
  240. void add_leaf(ColKey col, ref_type ref);
  241. void verify() const;
  242. void dump_objects(int64_t key_offset, std::string lead) const override;
  243. private:
  244. friend class ClusterTree;
  245. friend class TableClusterTree;
  246. static constexpr size_t s_key_ref_or_size_index = 0;
  247. static constexpr size_t s_first_col_index = 1;
  248. size_t get_size_in_compact_form() const
  249. {
  250. return size_t(Array::get(s_key_ref_or_size_index)) >> 1; // Size is stored as tagged value
  251. }
  252. void insert_row(size_t ndx, ObjKey k, const FieldValues& init_values);
  253. void move(size_t ndx, ClusterNode* new_node, int64_t key_adj) override;
  254. template <class T>
  255. void do_create(ColKey col);
  256. template <class T>
  257. void do_insert_column(ColKey col, bool nullable);
  258. template <class T>
  259. void do_insert_row(size_t ndx, ColKey col, Mixed init_val, bool nullable);
  260. template <class T>
  261. void do_move(size_t ndx, ColKey col, Cluster* to);
  262. template <class T>
  263. void do_erase(size_t ndx, ColKey col);
  264. void remove_backlinks(ObjKey origin_key, ColKey col, const std::vector<ObjKey>& keys, CascadeState& state) const;
  265. void remove_backlinks(ObjKey origin_key, ColKey col, const std::vector<ObjLink>& links,
  266. CascadeState& state) const;
  267. void do_erase_key(size_t ndx, ColKey col, CascadeState& state);
  268. void do_insert_key(size_t ndx, ColKey col, Mixed init_val, ObjKey origin_key);
  269. void do_insert_link(size_t ndx, ColKey col, Mixed init_val, ObjKey origin_key);
  270. template <class T>
  271. void set_spec(T&, ColKey::Idx) const;
  272. template <class ArrayType>
  273. void verify(ref_type ref, size_t index, util::Optional<size_t>& sz) const;
  274. };
  275. }
  276. #endif /* SRC_REALM_CLUSTER_HPP_ */