libfoedus-core
FOEDUS Core Library
hash_storage_verify.cpp
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  */
19 
20 #include <glog/logging.h>
21 
22 #include "foedus/engine.hpp"
29 #include "foedus/thread/thread.hpp"
30 
31 namespace foedus {
32 namespace storage {
33 namespace hash {
34 
35 #define CHECK_AND_ASSERT(x) do { ASSERT_ND(x); if (!(x)) \
36  return ERROR_STACK(kErrorCodeStrHashFailedVerification); } while (0)
37 
38 
40  return verify_single_thread(context->get_engine());
41 }
43  VolatilePagePointer pointer = control_block_->root_page_pointer_.volatile_pointer_;
44  if (!pointer.is_null()) {
45  // TASK(Hideaki) probably two versions: always follow volatile vs snapshot
46  // so far check volatile only
47  HashIntermediatePage* root = reinterpret_cast<HashIntermediatePage*>(
49  CHECK_AND_ASSERT(root->get_level() + 1U == control_block_->levels_);
51  }
52  return kRetOk;
53 }
54 
56  Engine* engine,
57  HashIntermediatePage* page) {
62  uint8_t level = page->get_level();
63  HashBin begin = page->get_bin_range().begin_;
64  HashBin interval = kHashMaxBins[level];
65  CHECK_AND_ASSERT(page->get_bin_range().end_ == begin + interval * kHashIntermediatePageFanout);
66  const auto& resolver = engine->get_memory_manager()->get_global_volatile_page_resolver();
67  for (uint8_t i = 0; i < kHashIntermediatePageFanout; ++i) {
68  DualPagePointer pointer = page->get_pointer(i);
69  if (!pointer.volatile_pointer_.is_null()) {
70  if (level == 0) {
71  HashDataPage* child = reinterpret_cast<HashDataPage*>(
72  resolver.resolve_offset(pointer.volatile_pointer_));
73  CHECK_AND_ASSERT(child->get_bin() == begin + i);
74  CHECK_ERROR(verify_single_thread_data(engine, child));
75  } else {
76  HashIntermediatePage* child = reinterpret_cast<HashIntermediatePage*>(
77  resolver.resolve_offset(pointer.volatile_pointer_));
78  CHECK_AND_ASSERT(child->get_level() + 1U == level);
79  CHECK_AND_ASSERT(child->get_bin_range().begin_ == begin + i * interval);
81  }
82  }
83  }
84  return kRetOk;
85 }
86 
88  Engine* engine,
89  HashDataPage* head) {
90  const auto& resolver = engine->get_memory_manager()->get_global_volatile_page_resolver();
91  HashBin bin = head->get_bin();
92  for (HashDataPage* page = head; page;) {
93  CHECK_AND_ASSERT(page->header().get_page_type() == kHashDataPageType);
94  CHECK_AND_ASSERT(!page->header().page_version_.is_locked());
95  CHECK_AND_ASSERT(!page->header().page_version_.is_moved());
96  CHECK_AND_ASSERT(!page->header().page_version_.is_retired());
97  CHECK_AND_ASSERT(page->header().masstree_in_layer_level_ == 0);
98  CHECK_AND_ASSERT(page->get_bin() == bin);
99 
100  page->assert_entries_impl();
101 
102  uint16_t records = page->get_record_count();
103  for (DataPageSlotIndex i = 0; i < records; ++i) {
104  HashDataPage::Slot* slot = page->get_slot_address(i);
108  }
109 
110  VolatilePagePointer next = page->next_page().volatile_pointer_;
111  page = nullptr;
112  if (!next.is_null()) {
113  page = reinterpret_cast<HashDataPage*>(resolver.resolve_offset(next));
114  }
115  }
116 
117  return kRetOk;
118 }
119 
120 
121 } // namespace hash
122 } // namespace storage
123 } // namespace foedus
storage::Page * resolve_offset(uint8_t numa_node, PagePoolOffset offset) const __attribute__((always_inline))
Resolves offset plus NUMA node ID to storage::Page*.
Represents a pointer to another page (usually a child page).
Definition: storage_id.hpp:271
bool is_retired() const __attribute__((always_inline))
Definition: page.hpp:140
const HashBinRange & get_bin_range() const
xct::RwLockableXctId tid_
TID of the record.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
Represents one thread running on one NUMA core.
Definition: thread.hpp:48
const GlobalVolatilePageResolver & get_global_volatile_page_resolver() const
Returns the page resolver to convert volatile page ID to page pointer.
Represents a pointer to a volatile page with modification count for preventing ABA.
Definition: storage_id.hpp:194
Brings error stacktrace information as return value of functions.
Definition: error_stack.hpp:81
XctId xct_id_
the second 64bit: Persistent status part of TID.
Definition: xct_id.hpp:1137
Engine * get_engine() const
Definition: thread.cpp:52
VolatilePagePointer volatile_pointer_
Definition: storage_id.hpp:308
bool is_moved() const __attribute__((always_inline))
Definition: page.hpp:139
ErrorStack verify_single_thread(Engine *engine)
These are defined in hash_storage_verify.cpp.
HashStorageControlBlock * control_block_
The shared data on shared memory that has been initialized in some SOC or master engine.
Definition: attachable.hpp:111
PageType get_page_type() const
Definition: page.hpp:280
Database engine object that holds all resources and provides APIs.
Definition: engine.hpp:109
ErrorStack verify_single_thread_data(Engine *engine, HashDataPage *head)
Epoch get_epoch() const __attribute__((always_inline))
Definition: xct_id.hpp:964
Fix-sized slot for each record, which is placed at the end of data region.
PageVersion page_version_
Used in several storage types as concurrency control mechanism for the page.
Definition: page.hpp:272
HashBin begin_
Inclusive beginning of the range.
Definition: hash_id.hpp:191
uint16_t DataPageSlotIndex
Definition: hash_id.hpp:196
HashBin end_
Exclusive end of the range.
Definition: hash_id.hpp:193
Represents an intermediate page in Hashtable Storage.
ErrorStack verify_single_thread_intermediate(Engine *engine, HashIntermediatePage *page)
bool is_valid() const
Definition: epoch.hpp:96
uint64_t HashBin
Represents a bin of a hash value.
Definition: hash_id.hpp:142
Represents an individual data page in Hashtable Storage.
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
bool is_being_written() const __attribute__((always_inline))
Definition: xct_id.hpp:1038
const uint8_t kHashIntermediatePageFanout
Number of pointers in an intermediate page of hash storage.
Definition: hash_id.hpp:49
const uint64_t kHashMaxBins[]
kHashTotalBins[n] gives the maximum number of hash bins n-level hash can hold.
Definition: hash_id.hpp:74
bool is_locked() const __attribute__((always_inline))
Definition: page.hpp:138
Definitions of IDs in this package and a few related constant values.
DualPagePointer & get_pointer(uint16_t index)
memory::EngineMemory * get_memory_manager() const
See Memory Manager.
Definition: engine.cpp:50
#define CHECK_AND_ASSERT(x)
bool is_keylocked() const __attribute__((always_inline))
Definition: xct_id.hpp:1140