TPIE

2362a60
external_store.h
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2014 The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 
20 #ifndef _TPIE_BTREE_EXTERNAL_STORE_H_
21 #define _TPIE_BTREE_EXTERNAL_STORE_H_
22 
23 #include <tpie/portability.h>
24 #include <tpie/btree/base.h>
25 #include <tpie/tpie_assert.h>
26 #include <tpie/blocks/block_collection_cache.h>
27 #include <tpie/btree/external_store_base.h>
28 #include <memory>
29 
30 #include <cstddef>
31 
32 namespace tpie {
33 namespace bbits {
34 
42 template <typename T,
43  typename A,
44  std::size_t fanout_a,
45  std::size_t fanout_b,
46  std::size_t bs>
47 class external_store : public external_store_base {
48 public:
52  typedef T value_type;
53 
57  typedef A augment_type;
58 
59  typedef size_t size_type;
60 
61  static constexpr memory_size_type cacheSize() {return 32;}
62  static constexpr memory_size_type blockSize() {return bs?bs:7000;}
63 
65  blocks::block_handle handle;
66  A augment;
67  };
68 
69  struct internal {
70  internal(blocks::block * b) {
71  count = reinterpret_cast<memory_size_type *>(b->get());
72  values = reinterpret_cast<internal_content *>(b->get() + sizeof(memory_size_type));
73  }
74 
75  memory_size_type * count;
76  internal_content * values;
77  };
78 
79  struct leaf {
80  leaf(blocks::block * b) {
81  count = reinterpret_cast<memory_size_type *>(b->get());
82  values = reinterpret_cast<T *>(b->get() + sizeof(memory_size_type));
83  }
84 
85  memory_size_type * count;
86  T * values;
87  };
88 
89  struct internal_type {
90  internal_type() {}
91  internal_type(blocks::block_handle handle) : handle(handle) {}
92 
93  blocks::block_handle handle;
94 
95  bool operator==(const internal_type & other) const {
96  return handle == other.handle;
97  }
98  };
99 
100  struct leaf_type {
101  leaf_type() {}
102  leaf_type(blocks::block_handle handle) : handle(handle) {}
103 
104  blocks::block_handle handle;
105 
106  bool operator==(const leaf_type & other) const {
107  return handle == other.handle;
108  }
109  };
110 
114  explicit external_store(const std::string & path, bool /*write_only*/=false) //TODO maybe use this?
115  : external_store_base(path)
116  {
117  m_collection = std::make_shared<blocks::block_collection_cache>(
118  path, blockSize(), cacheSize(), true);
119  }
120 
121  external_store(external_store&& other) noexcept = default;
122 
123  ~external_store() {
124  m_collection.reset();
125  }
126 
127  static constexpr size_t min_internal_size() {
128  return fanout_a?fanout_a:(max_internal_size() + 3) / 4;
129  }
130 
131  static constexpr size_t max_internal_size() {
132  return fanout_b?fanout_b:(blockSize() - sizeof(memory_size_type)) / sizeof(internal_content);
133  }
134 
135  static constexpr size_t min_leaf_size() {
136  return fanout_a?fanout_a:(max_leaf_size() + 3) / 4;
137  }
138 
139  static constexpr size_t max_leaf_size() {
140  return fanout_b?fanout_b:(blockSize() - sizeof(memory_size_type)) / sizeof(T);
141  }
142 
143  void move(internal_type src, size_t src_i,
144  internal_type dst, size_t dst_i) {
145  blocks::block * srcBlock = m_collection->read_block(src.handle);
146  blocks::block * dstBlock = m_collection->read_block(dst.handle);
147 
148  internal srcInter(srcBlock);
149  internal dstInter(dstBlock);
150 
151  dstInter.values[dst_i] = srcInter.values[src_i];
152 
153  m_collection->write_block(src.handle);
154  m_collection->write_block(dst.handle);
155  }
156 
157  void move(leaf_type src, size_t src_i,
158  leaf_type dst, size_t dst_i) {
159  blocks::block * srcBlock = m_collection->read_block(src.handle);
160  blocks::block * dstBlock = m_collection->read_block(dst.handle);
161 
162  leaf srcInter(srcBlock);
163  leaf dstInter(dstBlock);
164 
165  dstInter.values[dst_i] = srcInter.values[src_i];
166 
167  m_collection->write_block(src.handle);
168  m_collection->write_block(dst.handle);
169  }
170 
171  void set(leaf_type dst, size_t dst_i, T c) {
172  blocks::block * dstBlock = m_collection->read_block(dst.handle);
173  leaf dstInter(dstBlock);
174 
175  dstInter.values[dst_i] = c;
176 
177  m_collection->write_block(dst.handle);
178  }
179 
180  void set(internal_type node, size_t i, internal_type c) {
181  blocks::block * nodeBlock = m_collection->read_block(node.handle);
182  internal nodeInter(nodeBlock);
183 
184  nodeInter.values[i].handle = c.handle;
185 
186  m_collection->write_block(node.handle);
187  }
188 
189  void set(internal_type node, size_t i, leaf_type c) {
190  blocks::block * nodeBlock = m_collection->read_block(node.handle);
191  internal nodeInter(nodeBlock);
192 
193  nodeInter.values[i].handle = c.handle;
194 
195  m_collection->write_block(node.handle);
196  }
197 
198  const T & get(leaf_type node, size_t i) const {
199  blocks::block * nodeBlock = m_collection->read_block(node.handle);
200  leaf nodeInter(nodeBlock);
201 
202  return nodeInter.values[i];
203  }
204 
205  size_t count(internal_type node) const {
206  blocks::block * nodeBlock = m_collection->read_block(node.handle);
207  internal nodeInter(nodeBlock);
208 
209  return *(nodeInter.count);
210  }
211 
212  size_t count(leaf_type node) const {
213  blocks::block * nodeBlock = m_collection->read_block(node.handle);
214  leaf nodeInter(nodeBlock);
215 
216  return *(nodeInter.count);
217  }
218 
219  size_t count_child_leaf(internal_type node, size_t i) const {
220  blocks::block * nodeBlock = m_collection->read_block(node.handle);
221  internal nodeInter(nodeBlock);
222 
223  leaf_type wrap(nodeInter.values[i].handle);
224  return count(wrap);
225  }
226 
227  size_t count_child_internal(internal_type node, size_t i) const {
228  blocks::block * nodeBlock = m_collection->read_block(node.handle);
229  internal nodeInter(nodeBlock);
230 
231  internal_type wrap(nodeInter.values[i].handle);
232  return count(wrap);
233  }
234 
235  void set_count(internal_type node, size_t i) {
236  blocks::block * nodeBlock = m_collection->read_block(node.handle);
237  internal nodeInter(nodeBlock);
238 
239  *(nodeInter.count) = i;
240 
241  m_collection->write_block(node.handle);
242  }
243 
244  void set_count(leaf_type node, size_t i) {
245  blocks::block * nodeBlock = m_collection->read_block(node.handle);
246  leaf nodeInter(nodeBlock);
247 
248  *(nodeInter.count) = i;
249 
250  m_collection->write_block(node.handle);
251  }
252 
253  leaf_type create_leaf() {
254  blocks::block_handle h = m_collection->get_free_block();
255  blocks::block * b = m_collection->read_block(h);
256  leaf l(b);
257  (*l.count) = 0;
258  m_collection->write_block(h);
259  return leaf_type(h);
260  }
261 
262  leaf_type create(leaf_type) {
263  return create_leaf();
264  }
265 
266  internal_type create_internal() {
267  blocks::block_handle h = m_collection->get_free_block();
268  blocks::block * b = m_collection->read_block(h);
269  internal i(b);
270  (*i.count) = 0;
271  m_collection->write_block(h);
272  return internal_type(h);
273  }
274 
275  internal_type create(internal_type) {
276  return create_internal();
277  }
278 
279  void destroy(internal_type node) {
280  m_collection->free_block(node.handle);
281  }
282 
283  void destroy(leaf_type node) {
284  m_collection->free_block(node.handle);
285  }
286 
287  void set_root(internal_type node) {
288  m_root = node.handle;
289  }
290 
291  void set_root(leaf_type node) {
292  m_root = node.handle;
293  }
294 
295  internal_type get_root_internal() const throw() {
296  return internal_type(m_root);
297  }
298 
299  leaf_type get_root_leaf() const throw() {
300  return leaf_type(m_root);
301  }
302 
303  internal_type get_child_internal(internal_type node, size_t i) const {
304  blocks::block * nodeBlock = m_collection->read_block(node.handle);
305  internal dstInter(nodeBlock);
306 
307  return internal_type(dstInter.values[i].handle);
308  }
309 
310  leaf_type get_child_leaf(internal_type node, size_t i) const {
311  blocks::block * nodeBlock = m_collection->read_block(node.handle);
312  internal dstInter(nodeBlock);
313 
314  return leaf_type(dstInter.values[i].handle);
315  }
316 
317  size_t index(leaf_type child, internal_type node) const {
318  blocks::block * nodeBlock = m_collection->read_block(node.handle);
319  internal dstInter(nodeBlock);
320 
321  for (size_t i=0; i < *(dstInter.count); ++i)
322  if (dstInter.values[i].handle == child.handle) return i;
323  tp_assert(false, "Leaf not found");
324  tpie_unreachable();
325  }
326 
327  size_t index(internal_type child, internal_type node) const {
328  blocks::block * nodeBlock = m_collection->read_block(node.handle);
329  internal dstInter(nodeBlock);
330 
331  for (size_t i=0; i < *(dstInter.count); ++i)
332  if (dstInter.values[i].handle == child.handle) return i;
333  tp_assert(false, "Node not found");
334  tpie_unreachable();
335  }
336 
337  void set_augment(blocks::block_handle child, internal_type node, augment_type augment) {
338  blocks::block * nodeBlock = m_collection->read_block(node.handle);
339  internal nodeInter(nodeBlock);
340 
341  for (size_t i=0; i < *(nodeInter.count); ++i)
342  {
343  if (nodeInter.values[i].handle == child) {
344  nodeInter.values[i].augment = augment;
345  m_collection->write_block(node.handle);
346  return;
347  }
348  }
349 
350  tp_assert(false, "Not found");
351  tpie_unreachable();
352  }
353 
354 
355  void set_augment(leaf_type child, internal_type node, augment_type augment) {
356  set_augment(child.handle, node, augment);
357  }
358 
359  void set_augment(internal_type child, internal_type node, augment_type augment) {
360  set_augment(child.handle, node, augment);
361  }
362 
363  const augment_type & augment(internal_type node, size_t i) const {
364  blocks::block * nodeBlock = m_collection->read_block(node.handle);
365  internal nodeInter(nodeBlock);
366 
367  return nodeInter.values[i].augment;
368  }
369 
370  size_t height() const throw() {
371  return m_height;
372  }
373 
374  void set_height(size_t height) throw() {
375  m_height = height;
376  }
377 
378  size_t size() const throw() {
379  return m_size;
380  }
381 
382  void set_size(size_t size) throw() {
383  m_size = size;
384  }
385 
386  void flush() {}
387  void finalize_build() {}
388 
389  void set_metadata(const std::string & /*data*/) {
390  throw exception("Not yet implemnted.");
391  }
392 
393  std::string get_metadata() {
394  throw exception("Not yet implemnted.");
395  }
396 
397  std::shared_ptr<blocks::block_collection_cache> m_collection;
398 
399  template <typename>
400  friend class btree_node;
401 
402  template <typename>
403  friend class btree_iterator;
404 
405  template <typename, typename>
406  friend class bbits::tree_state;
407 
408  template <typename, typename>
409  friend class bbits::tree;
410 
411  template <typename, typename>
412  friend class bbits::builder;
413 };
414 
415 } //namespace bbits
416 } //namespace tpie
417 #endif /*_TPIE_BTREE_EXTERNAL_STORE_H_*/
Defines the tp_assert macro.
T * get()
Return a raw pointer to the array content.
Definition: array.h:531
A augment_type
Type of augmentation stored.
This file contains a few deprecated definitions for legacy code.
Storage used for an external btree.
Definition: base.h:214
T value_type
Type of value of items stored.
external_store(const std::string &path, bool=false)
Construct a new empty btree storage.
#define tp_assert(condition, message)
Definition: tpie_assert.h:48