libfoedus-core
FOEDUS Core Library
page.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP.
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details. You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * HP designates this particular file as subject to the "Classpath" exception
16  * as provided by HP in the LICENSE.txt file that accompanied this code.
17  */
18 #ifndef FOEDUS_STORAGE_PAGE_HPP_
19 #define FOEDUS_STORAGE_PAGE_HPP_
20 
21 #include <cstring>
22 #include <iosfwd>
23 
24 #include "foedus/assert_nd.hpp"
25 #include "foedus/compiler.hpp"
26 #include "foedus/cxx11.hpp"
27 #include "foedus/epoch.hpp"
30 #include "foedus/memory/fwd.hpp"
31 #include "foedus/storage/fwd.hpp"
33 #include "foedus/thread/fwd.hpp"
35 #include "foedus/xct/xct_id.hpp"
36 
37 namespace foedus {
38 namespace storage {
46 enum PageType {
57 };
58 
60  enum Constants {
61  kRetiredBit = 1 << 31,
62  kMovedBit = 1 << 30,
64  kHasNextPageBit = 1 << 29,
65  kReservedBit2 = 1 << 28,
66  kVersionMask = 0x0FFFFFFF,
67  };
69  void reset() ALWAYS_INLINE { status_ = 0; }
70 
71  bool is_moved() const ALWAYS_INLINE { return (status_ & kMovedBit) != 0; }
72  bool is_retired() const ALWAYS_INLINE { return (status_ & kRetiredBit) != 0; }
73  bool has_next_page() const ALWAYS_INLINE { return (status_ & kHasNextPageBit) != 0; }
74 
75  bool operator==(const PageVersionStatus& other) const ALWAYS_INLINE {
76  return status_ == other.status_;
77  }
78  bool operator!=(const PageVersionStatus& other) const ALWAYS_INLINE {
79  return status_ != other.status_;
80  }
81 
83  ASSERT_ND(!is_moved());
84  status_ |= kMovedBit;
85  }
87  ASSERT_ND(is_moved()); // we always set moved bit first. retire must happen later.
90  }
92  ASSERT_ND(!is_moved());
96  }
97 
98  // TASK(Hideaki) deprecated. we don't need page-version number any more. No longer used in any way
100  return status_ & kVersionMask;
101  }
102  // TASK(Hideaki) deprecated. we don't need page-version number any more. No longer used in any way
104  // we do this only when we insert a new key or split, so this never overflows.
106  ++status_;
107  }
108 
109  friend std::ostream& operator<<(std::ostream& o, const PageVersionStatus& v);
110 
111  uint32_t status_;
112 };
113 
131 
134  lock_.reset();
135  status_.reset();
136  }
137 
138  bool is_locked() const ALWAYS_INLINE { return lock_.is_locked(); }
139  bool is_moved() const ALWAYS_INLINE { return status_.is_moved(); }
140  bool is_retired() const ALWAYS_INLINE { return status_.is_retired(); }
142 
143  bool operator==(const PageVersion& other) const ALWAYS_INLINE { return status_ == other.status_; }
144  bool operator!=(const PageVersion& other) const ALWAYS_INLINE { return status_ != other.status_; }
145 
147  ASSERT_ND(is_locked());
148  status_.set_moved();
149  }
151  ASSERT_ND(is_locked());
153  }
155  ASSERT_ND(is_locked());
157  }
158 
159  // TASK(Hideaki) deprecated. we don't need page-version number any more. No longer used in any way
161  return status_.get_version_counter();
162  }
163  // TASK(Hideaki) deprecated. we don't need page-version number any more. No longer used in any way
165  ASSERT_ND(is_locked());
167  }
168 
169  friend std::ostream& operator<<(std::ostream& o, const PageVersion& v);
170 
171  xct::McsWwLock lock_; // +8 -> 8
173  uint32_t unused_; // +4 -> 16. this space might be used for interesting range "lock".
174 };
175 
191  uint64_t page_id_; // +8 -> 8
192 
196  StorageId storage_id_; // +4 -> 12
197 
202  Checksum checksum_; // +4 -> 16
203 
205  uint8_t page_type_; // +1 -> 17
206 
211  bool snapshot_; // +1 -> 18
212 
219  uint16_t key_count_; // +2 -> 20
220 
226  uint8_t masstree_layer_; // +1 -> 21
227 
243  uint8_t masstree_in_layer_level_; // +1 -> 22
244 
251  uint8_t stat_last_updater_node_; // +1 -> 23
252 
273 
274  // No instantiation.
277  PageHeader& operator=(const PageHeader& other) CXX11_FUNC_DELETE;
278  friend std::ostream& operator<<(std::ostream& o, const PageHeader& v);
279 
280  PageType get_page_type() const { return static_cast<PageType>(page_type_); }
281  uint8_t get_in_layer_level() const { return masstree_in_layer_level_; }
282  void set_in_layer_level(uint8_t level) { masstree_in_layer_level_ = level; }
283 
284  inline void init_volatile(
285  VolatilePagePointer page_id,
286  StorageId storage_id,
287  PageType page_type) ALWAYS_INLINE {
288  page_id_ = page_id.word;
289  storage_id_ = storage_id;
290  checksum_ = 0;
291  page_type_ = page_type;
292  snapshot_ = false;
293  key_count_ = 0;
294  masstree_layer_ = 0;
295  masstree_in_layer_level_ = 0;
296  stat_last_updater_node_ = page_id.get_numa_node();
297  hotness_.reset();
298  page_version_.reset();
299  }
300 
301  inline void init_snapshot(
302  SnapshotPagePointer page_id,
303  StorageId storage_id,
304  PageType page_type) ALWAYS_INLINE {
305  page_id_ = page_id;
306  storage_id_ = storage_id;
307  checksum_ = 0;
308  page_type_ = page_type;
309  snapshot_ = true;
310  key_count_ = 0;
311  masstree_layer_ = 0;
312  masstree_in_layer_level_ = 0;
313  stat_last_updater_node_ = extract_numa_node_from_snapshot_pointer(page_id);
314  hotness_.reset();
315  page_version_.reset();
316  }
317 
319  void set_key_count(uint8_t key_count) ALWAYS_INLINE { key_count_ = key_count; }
320 
321  bool contains_hot_records(thread::Thread* context);
322 };
323 
336  PageHeader& get_header() { return header_; }
337  const PageHeader& get_header() const { return header_; }
338  PageType get_page_type() const { return header_.get_page_type(); }
340  ASSERT_ND(!header_.snapshot_);
341  return VolatilePagePointer(header_.page_id_);
342  }
344  ASSERT_ND(header_.snapshot_);
345  return static_cast<SnapshotPagePointer>(header_.page_id_);
346  }
347  char* get_data() { return data_; }
348  const char* get_data() const { return data_; }
349 
350  private:
351  PageHeader header_;
352  char data_[kPageSize - sizeof(PageHeader)];
353 
354  // No instantiation.
355 
357  Page(const Page& other) CXX11_FUNC_DELETE;
358  Page& operator=(const Page& other) CXX11_FUNC_DELETE;
359 };
360 
373  const Page* parent_;
376 };
377 
387 typedef void (*VolatilePageInit)(const VolatilePageInitArguments& args);
388 
395 inline Page* to_page(const void* address) {
396  uintptr_t int_address = reinterpret_cast<uintptr_t>(address);
397  uint64_t aligned_address = static_cast<uint64_t>(int_address) / kPageSize * kPageSize;
398  return reinterpret_cast<Page*>(
399  reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(aligned_address)));
400 }
401 
402 inline void assert_aligned_page(const void* page) {
403  ASSERT_ND(page);
404  ASSERT_ND(reinterpret_cast<uintptr_t>(page) % kPageSize == 0);
405 }
406 
407 inline void assert_valid_volatile_page(const Page* page, uint32_t offset) {
408  ASSERT_ND(page);
409  ASSERT_ND(offset);
410 #ifndef NDEBUG
411  assert_aligned_page(page);
412  PageType type = page->get_header().get_page_type();
413  ASSERT_ND(type >= kArrayPageType);
415  VolatilePagePointer pointer;
416  pointer.word = page->get_header().page_id_;
417  ASSERT_ND(pointer.get_offset() == offset);
418 #endif // NDEBUG
419 }
420 
421 // Defined in cpp. Don't directly invoke because it causes overhead to invoke one func.
423  const memory::GlobalVolatilePageResolver& resolver,
424  const void* address);
425 
426 // Use this instead. In release version, this method is completely eliminated by compiler
427 #ifndef NDEBUG
429  const memory::GlobalVolatilePageResolver& resolver,
430  const void* address) {
431  assert_within_valid_volatile_page_impl(resolver, address);
432 }
433 #else // NDEBUG
435  const memory::GlobalVolatilePageResolver& /*resolver*/,
436  const void* /*address*/) {
437 }
438 #endif // NDEBUG
439 
441 
442 } // namespace storage
443 } // namespace foedus
444 #endif // FOEDUS_STORAGE_PAGE_HPP_
void assert_aligned_page(const void *page)
Definition: page.hpp:402
void increment_version_counter() __attribute__((always_inline))
Definition: page.hpp:164
void reset() __attribute__((always_inline))
used only while page initialization
Definition: xct_id.hpp:355
const char * get_data() const
Definition: page.hpp:348
Definitions of IDs in this package and a few related constant values.
char * get_data()
Definition: page.hpp:347
Page * to_page(const void *address)
super-dirty way to obtain Page the address belongs to.
Definition: page.hpp:395
bool has_next_page() const __attribute__((always_inline))
Definition: page.hpp:141
uint8_t page_type_
Actually of PageType.
Definition: page.hpp:205
bool is_retired() const __attribute__((always_inline))
Definition: page.hpp:140
uint32_t StorageId
Unique ID for storage.
Definition: storage_id.hpp:55
void init_volatile(VolatilePagePointer page_id, StorageId storage_id, PageType page_type) __attribute__((always_inline))
Definition: page.hpp:284
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
void increment_key_count() __attribute__((always_inline))
Definition: page.hpp:318
Represents one thread running on one NUMA core.
Definition: thread.hpp:48
Typedefs of ID types used in thread package.
uint8_t masstree_layer_
used only in masstree.
Definition: page.hpp:226
bool operator!=(const PageVersion &other) const __attribute__((always_inline))
Definition: page.hpp:144
StorageId storage_id_
ID of the storage this page belongs to.
Definition: page.hpp:196
bool is_moved() const __attribute__((always_inline))
Definition: page.hpp:71
PageType
The following 1-byte value is stored in the common page header.
Definition: page.hpp:46
Represents a pointer to a volatile page with modification count for preventing ABA.
Definition: storage_id.hpp:194
Just a synonym of XctId to be used as a page lock mechanism.
Definition: page.hpp:129
STL namespace.
uint32_t get_version_counter() const __attribute__((always_inline))
Definition: page.hpp:160
uint16_t index_in_parent_
[IN] Some index (meaning depends on page type) of pointer in parent page to the new page...
Definition: page.hpp:375
void reset() __attribute__((always_inline))
used only while page initialization
Definition: page.hpp:133
Implements a probabilistic counter [Morris 1978].
Page * page_
[IN, OUT] The new page to initialize.
Definition: page.hpp:371
void set_has_next_page() __attribute__((always_inline))
Definition: page.hpp:154
bool contains_hot_records(thread::Thread *context)
Definition: page.cpp:81
bool is_moved() const __attribute__((always_inline))
Definition: page.hpp:139
thread::Thread * context_
[IN] Thread on which the procedure is running
Definition: page.hpp:367
void assert_valid_volatile_page(const Page *page, uint32_t offset)
Definition: page.hpp:407
VolatilePagePointer get_volatile_page_id() const
Definition: page.hpp:339
uint8_t masstree_in_layer_level_
used only in masstree.
Definition: page.hpp:243
void set_retired() __attribute__((always_inline))
Definition: page.hpp:150
uint16_t key_count_
physical key count (those keys might be deleted) in this page.
Definition: page.hpp:219
bool operator==(const PageVersionStatus &other) const __attribute__((always_inline))
Definition: page.hpp:75
Forward declarations of classes in storage package.
memory::PagePoolOffset get_offset() const
Definition: storage_id.hpp:202
Definitions of IDs in this package and a few related constant values.
An exclusive-only (WW) MCS lock data structure.
Definition: xct_id.hpp:324
xct::McsWwLock lock_
Definition: page.hpp:171
#define CXX11_FINAL
Used in public headers in place of "final" of C++11.
Definition: cxx11.hpp:131
uint64_t SnapshotPagePointer
Page ID of a snapshot page.
Definition: storage_id.hpp:79
void assert_within_valid_volatile_page_impl(const memory::GlobalVolatilePageResolver &resolver, const void *address)
Definition: page.cpp:85
void assert_within_valid_volatile_page(const memory::GlobalVolatilePageResolver &resolver, const void *address)
Definition: page.hpp:428
bool operator!=(const PageVersionStatus &other) const __attribute__((always_inline))
Definition: page.hpp:78
PageType get_page_type() const
Definition: page.hpp:338
PageType get_page_type() const
Definition: page.hpp:280
const Page * parent_
[IN] Parent of the new page.
Definition: page.hpp:373
Just a marker to denote that a memory region represents a data page.
Definition: page.hpp:184
void reset() __attribute__((always_inline))
Definition: page.hpp:69
Set of arguments, both inputs and outputs, given to each volatile page initializer.
Definition: page.hpp:365
Just a marker to denote that the memory region represents a data page.
Definition: page.hpp:334
PageVersion page_version_
Used in several storage types as concurrency control mechanism for the page.
Definition: page.hpp:272
uint32_t get_version_counter() const __attribute__((always_inline))
Definition: page.hpp:99
friend std::ostream & operator<<(std::ostream &o, const PageVersionStatus &v)
Definition: page.cpp:33
void set_moved() __attribute__((always_inline))
Definition: page.hpp:82
uint8_t extract_numa_node_from_snapshot_pointer(SnapshotPagePointer pointer)
Definition: storage_id.hpp:95
Forward declarations of classes in memory package.
void set_moved() __attribute__((always_inline))
Definition: page.hpp:146
so far used only in hash storage, where data page forms a linked list
Definition: page.hpp:64
friend std::ostream & operator<<(std::ostream &o, const PageVersion &v)
Definition: page.cpp:42
Checksum checksum_
Checksum of the content of this page to detect corrupted pages.
Definition: page.hpp:202
bool is_locked() const
This is a "relaxed" check.
Definition: xct_id.hpp:334
#define CXX11_FUNC_DELETE
Used in public headers in place of " = delete" of C++11.
Definition: cxx11.hpp:128
VolatilePagePointer page_id
[IN] New page ID
Definition: page.hpp:369
void init_snapshot(SnapshotPagePointer page_id, StorageId storage_id, PageType page_type) __attribute__((always_inline))
Definition: page.hpp:301
PageVersionStatus status_
Definition: page.hpp:172
bool operator==(const PageVersion &other) const __attribute__((always_inline))
Definition: page.hpp:143
Atomic fence methods and load/store with fences that work for both C++11/non-C++11 code...
void(* VolatilePageInit)(const VolatilePageInitArguments &args)
A function pointer to initialize a volatile page.
Definition: page.hpp:387
#define STATIC_SIZE_CHECK(desired, actual)
const PageHeader & get_header() const
Definition: page.hpp:337
uint8_t stat_last_updater_node_
A loosely maintained statistics for volatile pages.
Definition: page.hpp:251
Resolves an offset in a volatile page pool to an actual pointer and vice versa.
void set_key_count(uint8_t key_count) __attribute__((always_inline))
Definition: page.hpp:319
PageHeader & get_header()
At least the basic header exists in all pages.
Definition: page.hpp:336
bool has_next_page() const __attribute__((always_inline))
Definition: page.hpp:73
void set_retired() __attribute__((always_inline))
Definition: page.hpp:86
bool is_retired() const __attribute__((always_inline))
Definition: page.hpp:72
uint8_t get_in_layer_level() const
Definition: page.hpp:281
assorted::ProbCounter hotness_
Loosely maintained statistics on data temperature.
Definition: page.hpp:268
bool snapshot_
Whether this page image is of a snapshot page.
Definition: page.hpp:211
SnapshotPagePointer get_snapshot_page_id() const
Definition: page.hpp:343
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
bool is_locked() const __attribute__((always_inline))
Definition: page.hpp:138
Forward declarations of classes in thread package.
#define ALWAYS_INLINE
A function suffix to hint that the function should always be inlined.
Definition: compiler.hpp:106
void set_has_next_page() __attribute__((always_inline))
Definition: page.hpp:91
const uint16_t kPageSize
A constant defining the page size (in bytes) of both snapshot pages and volatile pages.
Definition: storage_id.hpp:45
uint32_t Checksum
Checksum of a snapshot page.
Definition: storage_id.hpp:174
void increment_version_counter() __attribute__((always_inline))
Definition: page.hpp:103
uint64_t page_id_
Page ID of this page.
Definition: page.hpp:191
void set_in_layer_level(uint8_t level)
Definition: page.hpp:282
PageVersion() __attribute__((always_inline))
Definition: page.hpp:130