Zero  0.1.0
btree_page.h
Go to the documentation of this file.
1 /*
2  * (c) Copyright 2011-2014, Hewlett-Packard Development Company, LP
3  */
4 
5 #ifndef __BTREE_PAGE_H
6 #define __BTREE_PAGE_H
7 
8 #include "fixable_page_h.h"
9 #include "vec_t.h"
10 
38 public:
39  enum {
41  hdr_sz = sizeof(generic_page_header) + 48,
42  // 48 above must be kept in sync with size of headers below!
43  // (checked by static asserts after class)
44 
47  };
48 
49 protected:
50  // ======================================================================
51  // BEGIN: BTree but not item-specific headers
52  // ======================================================================
53 
64  PageID btree_root; // +4 -> 4
65 
67  PageID btree_pid0; // +4 -> 8
68 
70  PageID btree_foster; // +4 -> 12
71 
77  int16_t btree_level; // +2 -> 14
78 
83  int16_t btree_fence_low_length; // +2 -> 16
84 
89  int16_t btree_fence_high_length; // +2 -> 18
90 
96  int16_t btree_chain_fence_high_length; // +2 -> 20
97 
106  int16_t btree_prefix_length; // +2 -> 22
107 
120 
121  // ======================================================================
122  // END: BTree but not item-specific headers
123  // ======================================================================
124 
125 
126  // ======================================================================
127  // BEGIN: protected item interface
128  // ======================================================================
129 
134  void init_items();
135 
136  // Remove the largest 'item_count' items from the storage area
137  // It erases existing items from storage therefore use with caution
138  // The function should only be called by full logging page rebalance
139  // restart operation to recovery the source page
140  // item_count - number of records to remove
141  // high - the new high fence after record removal
142  void remove_items(const int item_count, const w_keystr_t& high);
143 
144  int number_of_items() const {
145  return nitems;
146  }
147 
149  int number_of_ghosts() const {
150  return nghosts;
151  }
152 
154  bool is_ghost(int item) const;
155 
157  void set_ghost(int item);
158 
160  void unset_ghost(int item);
161 
163  typedef uint16_t poor_man_key;
164 
166  poor_man_key item_poor(int item) const;
167 
169  poor_man_key& item_poor(int item);
170 
177  PageID& item_child(int item);
178 
185  char* item_data(int item);
186 
191  size_t item_length(int item) const;
192 
211  bool insert_item(int item, bool ghost, poor_man_key poor, PageID child,
212  size_t data_length);
213 
229  bool insert_item(int item, bool ghost, poor_man_key poor, PageID child,
230  const cvec_t& data);
231 
242  bool resize_item(int item, size_t new_length, size_t keep_old);
243 
252  bool replace_item_data(int item, size_t offset, const cvec_t& new_data);
253 
260  void delete_item(int item);
261 
268  void delete_range(int from, int to);
269 
278  void truncate_all(size_t amount, size_t pos);
279 
284  size_t item_space(int item) const;
285 
292  size_t predict_item_space(size_t data_length) const;
293 
298  size_t usable_space() const;
299 
301  void compact();
302 
310  char* unused_part(size_t& length);
311 
317  static const size_t max_item_overhead;
318 
323  bool _items_are_consistent() const;
324 
325 private:
326 // ======================================================================
327 // BEGIN: private implementation details
328 // ======================================================================
329 
330  typedef uint16_t item_index_t;
331 
332  typedef uint16_t item_length_t;
333 
338  typedef int16_t body_offset_t;
339 
340  // ======================================================================
341  // BEGIN: item-specific headers
342  // ======================================================================
343 
345  item_index_t nitems; // +2 -> 26
346 
348  item_index_t nghosts; // +2 -> 28
349 
351  body_offset_t first_used_body; // +2 -> 30
352 
354  uint16_t padding; // +2 -> 32
355 
356  // ======================================================================
357  // END: item-specific headers
358  // ======================================================================
359 
360 protected:
361  // ======================================================================
362  // BEGIN: Single-Page-Recovery-related headers (placed at last so that frequently used
363  // headers like nitems are in the first 64 bytes (one cacheline).
364  // ======================================================================
370  lsn_t btree_pid0_emlsn; // +8 -> 40
371 
378  // ======================================================================
379  // END: Single-Page-Recovery-related headers
380  // ======================================================================
381 
382 private:
383  /*
384  * The item space is organized as follows:
385  *
386  * head_0 head_1 ... head_I <possible gap> body_J body_J+1 ... body_N
387  *
388  * where head_i is a fixed sized value of type item_head that
389  * contains the poor_man_key, the ghost bit, and a offset to a
390  * starting item_body for item # i. As items are added, space is
391  * consumed on both sides of the gap: at the beginning for another
392  * item_head and at the end for one or more item bodies to store
393  * the remaining data, namely the variable-size data field and
394  * (for interior nodes only) the child pointer.
395  *
396  * Here, I is nitems+1, J is first_used_body, and N is max_bodies-1.
397  */
398 
399  typedef struct {
404  body_offset_t offset;
405  poor_man_key poor;
406  } item_head;
407  //static_assert(sizeof(item_head) == 4, "item_head has wrong length");
408  BOOST_STATIC_ASSERT(sizeof(item_head) == 4);
409 
410  typedef struct {
411  // item format depends on whether we are a leaf or not:
412  union {
413  struct {
414  item_length_t item_len;
416  char item_data[6];
417  } leaf;
418  struct {
420  item_length_t item_len;
422  char item_data[2];
423  } interior;
429  };
430  } item_body;
431 
432  BOOST_STATIC_ASSERT(sizeof(item_body) == 8);
433 
434  BOOST_STATIC_ASSERT(data_sz % sizeof(item_body) == 0);
435  enum {
441  interior_overhead = sizeof(item_length_t) + sizeof(PageID),
442  };
443 
444  union {
447  };
448  // check field sizes are large enough:
449  /*
450  * #define here is a workaround for ebrowse cannot handle < in
451  * marcos calls, numeric_limits::min() is not constant
452  */
453 #define STATIC_LESS_THAN(x, y) BOOST_STATIC_ASSERT((x) < (y))
454  STATIC_LESS_THAN(data_sz, 1 << (sizeof(item_length_t) * 8));
455  STATIC_LESS_THAN(max_heads, 1 << (sizeof(item_index_t) * 8));
456  STATIC_LESS_THAN(max_bodies, 1 << (sizeof(body_offset_t) * 8 - 1)); // -1 for ghost bit
457 
458 
460  bool is_leaf() const {
461  return btree_level == 1;
462  }
463 
465  static size_t _item_align(size_t i) {
466  return (i + sizeof(item_body) - 1) & ~(sizeof(item_body) - 1);
467  }
468 
470  size_t _item_body_overhead() const;
471 
477  item_length_t& _item_body_length(body_offset_t offset);
478 
484  item_length_t _item_body_length(body_offset_t offset) const;
485 
490  body_offset_t _item_bodies(body_offset_t offset) const;
491 
492 public:
493  friend std::ostream& operator<<(std::ostream&, btree_page_data&);
494 
495  bool eq(const btree_page_data&) const;
496 };
497 
498 // forward references for friending test...
499 class ss_m;
500 class test_volume_t;
501 
518 class btree_page : public btree_page_data {
519  friend class btree_page_h;
520 
521  template<class T> friend class page_img_format_t; // for unused_part()
522  friend class btree_split_log;
523 
524  // _ux_deadopt_foster_apply_foster_parent
525  // _ux_adopt_foster_apply_child
526  friend class btree_impl;
527  friend class test_bf_tree;
528 
529  friend w_rc_t test_bf_fix_virgin_root(ss_m* /*ssm*/, test_volume_t* test_volume);
530 
531  // these are for access to headers from btree_page_headers:
532  friend w_rc_t test_bf_fix_virgin_child(ss_m* /*ssm*/, test_volume_t* test_volume);
533 
534  friend w_rc_t test_bf_evict(ss_m* /*ssm*/, test_volume_t* test_volume);
535 
536  friend w_rc_t _test_bf_swizzle(ss_m* /*ssm*/, test_volume_t* test_volume, bool enable_swizzle);
537 };
538 //static_assert(sizeof(btree_page) == sizeof(generic_page),
539 // "btree_page has wrong length");
540 BOOST_STATIC_ASSERT(sizeof(btree_page) == sizeof(generic_page));
541 
542 
543 
544 /***************************************************************************/
545 /* */
546 /* Rest of file is inlined method implementations */
547 /* */
548 /***************************************************************************/
549 
551  if (is_leaf()) {
552  return leaf_overhead;
553  } else {
554  return interior_overhead;
555  }
556 }
557 
559  w_assert1(offset >= 0);
560  if (is_leaf()) {
561  return body[offset].leaf.item_len;
562  } else {
563  return body[offset].interior.item_len;
564  }
565 }
566 
568  w_assert1(offset >= 0);
569  if (is_leaf()) {
570  return body[offset].leaf.item_len;
571  } else {
572  return body[offset].interior.item_len;
573  }
574 }
575 
577  w_assert1(offset >= 0);
578  return _item_align(_item_body_length(offset)) / sizeof(item_body);
579 }
580 
581 inline bool btree_page_data::is_ghost(int item) const {
582  w_assert1(item >= 0 && item < nitems);
583  return head[item].offset < 0;
584 }
585 
587  w_assert1(item >= 0 && item < nitems);
588  return head[item].poor;
589 }
590 
592  w_assert1(item >= 0 && item < nitems);
593  return head[item].poor;
594 }
595 
597  w_assert1(item >= 0 && item < nitems);
598  w_assert1(!is_leaf());
599 
600  body_offset_t offset = head[item].offset;
601  if (offset < 0) {
602  offset = -offset;
603  }
604  return body[offset].interior.child;
605 }
606 
607 inline char* btree_page_data::item_data(int item) {
608  w_assert1(item >= 0 && item < nitems);
609  body_offset_t offset = head[item].offset;
610  if (offset < 0) {
611  offset = -offset;
612  }
613  if (is_leaf()) {
614  return body[offset].leaf.item_data;
615  } else {
616  return body[offset].interior.item_data;
617  }
618 }
619 
620 inline size_t btree_page_data::item_length(int item) const {
621  w_assert1(item >= 0 && item < nitems);
622  body_offset_t offset = head[item].offset;
623  if (offset < 0) {
624  offset = -offset;
625  }
626 
627  int length;
628  if (is_leaf()) {
629  length = body[offset].leaf.item_len - leaf_overhead;
630  } else {
631  length = body[offset].interior.item_len - interior_overhead;
632  }
633  w_assert1(length >= 0);
634  return length;
635 }
636 
637 inline size_t btree_page_data::predict_item_space(size_t data_length) const {
638  size_t body_length = data_length + _item_body_overhead();
639  return _item_align(body_length) + sizeof(item_head);
640 }
641 
642 inline size_t btree_page_data::item_space(int item) const {
643  w_assert1(item >= 0 && item < nitems);
644  body_offset_t offset = head[item].offset;
645  if (offset < 0) {
646  offset = -offset;
647  }
648 
649  return _item_align(_item_body_length(offset)) + sizeof(item_head);
650 }
651 
652 inline size_t btree_page_data::usable_space() const {
653  w_assert1(first_used_body * sizeof(item_body) >= nitems * sizeof(item_head));
654  return first_used_body * sizeof(item_body) - nitems * sizeof(item_head);
655 }
656 
669 template<typename T>
670 inline T volatile& ACCESS_ONCE(T& t) {
671  return static_cast<T volatile&>(t);
672 }
673 
674 #endif // __BTREE_PAGE_H
PageID btree_foster
Foster link page ID (0 if not linked).
Definition: btree_page.h:70
Definition: btree_page.h:410
Definition: logdef_gen.h:353
void unset_ghost(int item)
turn the given item into a non-ghost item
Definition: btree_page.cpp:95
void remove_items(const int item_count, const w_keystr_t &high)
Definition: btree_page.cpp:22
struct btree_page_data::item_body::@22::@25 interior
size of region available to store items
Definition: btree_page.h:46
STATIC_LESS_THAN(data_sz, 1<<(sizeof(item_length_t) *8))
static size_t _item_align(size_t i)
align to item_body alignment boundary (integral multiple of item_body&#39;s)
Definition: btree_page.h:465
#define w_assert1(x)
Level 1 should not add significant extra time.
Definition: w_base.h:198
bool replace_item_data(int item, size_t offset, const cvec_t &new_data)
Definition: btree_page.cpp:189
item_head head[max_heads]
Definition: btree_page.h:445
item_index_t nghosts
number of current ghost items
Definition: btree_page.h:348
Page handle for B-Tree data page.
Definition: btree_page_h.h:185
size_t usable_space() const
Definition: btree_page.h:652
bool resize_item(int item, size_t new_length, size_t keep_old)
Definition: btree_page.cpp:147
item_length_t item_len
Definition: btree_page.h:414
int16_t btree_chain_fence_high_length
Definition: btree_page.h:96
A generic page view: any Zero page can be viewed as being of this type but it only exposes fields sha...
Definition: generic_page.h:121
Page headers shared by all Zero pages.
Definition: generic_page.h:34
Key string class which can represent a few special values.
Definition: w_key.h:47
bool is_leaf() const
are we a leaf node?
Definition: btree_page.h:460
void set_ghost(int item)
turn the given item into a ghost item
Definition: btree_page.cpp:84
The internal implementation class which actually implements the functions of btree_m.
Definition: btree_impl.h:66
Definition: btree_page.h:399
int16_t btree_level
Definition: btree_page.h:77
A constant vec_t (meaning things pointed to cannot be changed).
Definition: vec_t.h:95
char * unused_part(size_t &length)
Definition: btree_page.cpp:477
Definition: logrec_support.h:19
size_t item_length(int item) const
Definition: btree_page.h:620
void init_items()
Definition: btree_page.cpp:12
body_offset_t _item_bodies(body_offset_t offset) const
Definition: btree_page.h:576
uint16_t padding
padding to ensure header size is a multiple of 8
Definition: btree_page.h:354
size_t _item_body_overhead() const
add this to data length to get bytes used in item bodies (not counting padding)
Definition: btree_page.h:550
void truncate_all(size_t amount, size_t pos)
Definition: btree_page.cpp:276
friend std::ostream & operator<<(std::ostream &, btree_page_data &)
Definition: btree_page.cpp:344
uint32_t PageID
Definition: basics.h:45
void delete_range(int from, int to)
Definition: btree_page.cpp:220
This is the SHORE Storage Manager API.
Definition: sm.h:405
size of all header fields combined
Definition: btree_page.h:41
Log Sequence Number. See Log Sequence Numbers (LSN).
Definition: lsn.h:243
body_offset_t offset
Definition: btree_page.h:404
PageID btree_root
Definition: btree_page.h:64
BOOST_STATIC_ASSERT(sizeof(item_head)==4)
lsn_t btree_foster_emlsn
Definition: btree_page.h:377
Definition: btree_page.h:441
int16_t btree_consecutive_skewed_insertions
Definition: btree_page.h:119
T volatile & ACCESS_ONCE(T &t)
Definition: btree_page.h:670
int16_t btree_fence_high_length
Definition: btree_page.h:89
bool is_ghost(int item) const
is the given item a ghost?
Definition: btree_page.h:581
item_index_t nitems
current number of items
Definition: btree_page.h:345
Return code for most functions and methods.
Definition: w_rc.h:87
uint16_t item_length_t
Definition: btree_page.h:332
void delete_item(int item)
Definition: btree_page.cpp:198
uint16_t poor_man_key
The type of poor_man_key data.
Definition: btree_page.h:163
Definition: btree_page.h:436
void compact()
compact item space, making all freed space available.
Definition: btree_page.cpp:446
char * item_data(int item)
Definition: btree_page.h:607
bool insert_item(int item, bool ghost, poor_man_key poor, PageID child, size_t data_length)
Definition: btree_page.cpp:106
Definition: btree_page.h:437
body_offset_t first_used_body
offset to beginning of used item bodies (# of used item body that is located left-most).
Definition: btree_page.h:351
int16_t btree_fence_low_length
Definition: btree_page.h:83
poor_man_key item_poor(int item) const
return the poor_man_key data for the given item
Definition: btree_page.h:591
PageID btree_pid0
First child pointer in non-leaf nodes.
Definition: btree_page.h:67
int16_t body_offset_t
Definition: btree_page.h:338
int64_t _for_alignment_only
Definition: btree_page.h:428
Definition: btree_page.h:439
bool _items_are_consistent() const
Definition: btree_page.cpp:365
PageID child
Definition: btree_page.h:419
item_body body[max_bodies]
Definition: btree_page.h:446
size_t item_space(int item) const
Definition: btree_page.h:642
int number_of_ghosts() const
return number of current items that are ghosts
Definition: btree_page.h:149
bool eq(const btree_page_data &) const
Definition: btree_page.cpp:321
struct btree_page_data::item_body::@22::@24 leaf
poor_man_key poor
Definition: btree_page.h:405
int16_t btree_prefix_length
Definition: btree_page.h:106
int number_of_items() const
Definition: btree_page.h:144
item_length_t & _item_body_length(body_offset_t offset)
Definition: btree_page.h:558
lsn_t btree_pid0_emlsn
Definition: btree_page.h:370
uint16_t item_index_t
Definition: btree_page.h:330
#define T
Definition: w_okvl_inl.h:45
This class holds B-tree-specific headers as well as an ordered list of items.
Definition: btree_page.h:37
static const size_t max_item_overhead
Definition: btree_page.h:317
B-tree page.
Definition: btree_page.h:518
PageID & item_child(int item)
Definition: btree_page.h:596
size_t predict_item_space(size_t data_length) const
Definition: btree_page.h:637