libfoedus-core
FOEDUS Core Library
hash_storage_debug.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"
30 #include "foedus/thread/thread.hpp"
31 
32 namespace foedus {
33 namespace storage {
34 namespace hash {
35 
38  if (buf_.is_null() || buf_.get_size() < 1 << 12U) {
39  buf_.alloc(1 << 12U, 1 << 12U, memory::AlignedMemory::kNumaAllocOnnode, 0);
40  }
41  page_ = reinterpret_cast<Page*>(buf_.get_block());
42  WRAP_ERROR_CODE(files->read_page(pointer, page_));
43  return kRetOk;
44  }
45 
47  HashDataPage* as_data() { return reinterpret_cast<HashDataPage*>(page_); }
48 
51 };
52 
54  Engine* engine,
55  bool volatile_only,
56  bool intermediate_only,
57  uint32_t max_pages) {
58  LOG(INFO) << "**"
59  << std::endl << "***************************************************************"
60  << std::endl << "*** Dumping " << HashStorage(engine_, control_block_) << " in details. "
61  << std::endl << "*** volatile_only=" << volatile_only
62  << ", intermediate_only=" << intermediate_only << ", max_pages=" << max_pages
63  << std::endl << "***************************************************************";
64 
65  if (max_pages == 0) {
66  return kRetOk;
67  }
68 
69  cache::SnapshotFileSet files(engine);
70  CHECK_ERROR(files.initialize());
72 
73  LOG(INFO) << "First, dumping volatile pages...";
74  DualPagePointer pointer = control_block_->root_page_pointer_;
75  if (pointer.volatile_pointer_.is_null()) {
76  LOG(INFO) << "No volatile pages.";
77  } else {
78  HashIntermediatePage* root = reinterpret_cast<HashIntermediatePage*>(
80  pointer.volatile_pointer_));
81  uint32_t remaining = max_pages - 1U;
83  engine,
84  &files,
85  root,
86  true,
87  intermediate_only,
88  &remaining));
89  }
90  LOG(INFO) << "Dumped volatile pages.";
91  if (!volatile_only) {
92  LOG(INFO) << "Now dumping snapshot pages...";
93  if (pointer.snapshot_pointer_ == 0) {
94  LOG(INFO) << "No snapshot pages.";
95  } else {
96  TmpSnashotPage tmp;
97  CHECK_ERROR(tmp.init(&files, pointer.snapshot_pointer_));
99  uint32_t remaining = max_pages - 1U;
101  engine,
102  &files,
103  root,
104  false,
105  intermediate_only,
106  &remaining));
107  }
108  LOG(INFO) << "Dumped snapshot pages.";
109  }
110 
111  CHECK_ERROR(files.uninitialize());
112  return kRetOk;
113 }
114 
115 
117  Engine* engine,
118  cache::SnapshotFileSet* files,
119  HashIntermediatePage* parent,
120  bool follow_volatile,
121  bool intermediate_only,
122  uint32_t* remaining) {
123  if (((*remaining) == 0) || --(*remaining) == 0) {
124  LOG(INFO) << "Reached write-out max. skip the following";
125  return kRetOk;
126  }
127 
128  LOG(INFO) << *parent;
129  bool bottom = parent->get_level() == 0;
130  if (bottom && intermediate_only) {
131  return kRetOk;
132  }
133 
134  const auto& resolver = engine->get_memory_manager()->get_global_volatile_page_resolver();
135  TmpSnashotPage tmp;
136  for (uint8_t i = 0; i < kHashIntermediatePageFanout && ((*remaining) > 0); ++i) {
137  DualPagePointer pointer = parent->get_pointer(i);
138  if (follow_volatile) {
139  if (pointer.volatile_pointer_.is_null()) {
140  continue;
141  }
142  if (bottom) {
143  HashDataPage* page = reinterpret_cast<HashDataPage*>(
144  resolver.resolve_offset(pointer.volatile_pointer_));
145  CHECK_ERROR(debugout_single_thread_data(engine, files, page, true, remaining));
146  } else {
147  HashIntermediatePage* page = reinterpret_cast<HashIntermediatePage*>(
148  resolver.resolve_offset(pointer.volatile_pointer_));
150  engine,
151  files,
152  page,
153  true,
154  intermediate_only,
155  remaining));
156  }
157  } else {
158  if (pointer.snapshot_pointer_ == 0) {
159  continue;
160  }
161  CHECK_ERROR(tmp.init(files, pointer.snapshot_pointer_));
162  if (bottom) {
163  HashDataPage* page = tmp.as_data();
164  CHECK_ERROR(debugout_single_thread_data(engine, files, page, false, remaining));
165  } else {
168  engine,
169  files,
170  page,
171  false,
172  intermediate_only,
173  remaining));
174  }
175  }
176  }
177 
178  return kRetOk;
179 }
180 
182  Engine* engine,
183  cache::SnapshotFileSet* files,
184  HashDataPage* head,
185  bool follow_volatile,
186  uint32_t* remaining) {
187  TmpSnashotPage tmp;
188  const auto& resolver = engine->get_memory_manager()->get_global_volatile_page_resolver();
189  for (HashDataPage* cur = head; cur;) {
190  LOG(INFO) << *cur;
191  if ((*remaining) == 0 || --(*remaining) == 0) {
192  LOG(INFO) << "Reached write-out max. skip the following";
193  return kRetOk;
194  }
195 
196  // here, we take a copy of pointer so that "cur" might be okay to become invalid after here.
197  DualPagePointer pointer = cur->next_page();
198  cur = nullptr;
199  if (follow_volatile) {
200  if (!pointer.volatile_pointer_.is_null()) {
201  cur = reinterpret_cast<HashDataPage*>(resolver.resolve_offset(pointer.volatile_pointer_));
202  }
203  } else {
204  if (pointer.snapshot_pointer_) {
205  CHECK_ERROR(tmp.init(files, pointer.snapshot_pointer_)); // note, this overwrites tmp
206  cur = tmp.as_data();
207  }
208  }
209  }
210  return kRetOk;
211 }
212 
214  LOG(INFO) << "**"
215  << std::endl << "***************************************************************"
216  << std::endl << "*** Reseting " << HashStorage(engine_, control_block_) << "'s "
217  << std::endl << "*** temperature stat for HCC"
218  << std::endl << "***************************************************************";
219 
220  DualPagePointer pointer = control_block_->root_page_pointer_;
221  if (pointer.volatile_pointer_.is_null()) {
222  LOG(INFO) << "No volatile pages.";
223  } else {
225  }
226 
227  LOG(INFO) << "Done resettting";
228  return kRetOk;
229 }
230 
232  VolatilePagePointer intermediate_page_id) {
233  const auto& resolver = engine_->get_memory_manager()->get_global_volatile_page_resolver();
235  = reinterpret_cast<HashIntermediatePage*>(resolver.resolve_offset(intermediate_page_id));
236  ASSERT_ND(page);
237  const bool bottom = page->get_level() == 0;
238  for (uint8_t i = 0; i < kHashIntermediatePageFanout; ++i) {
239  DualPagePointer pointer = page->get_pointer(i);
240  if (pointer.volatile_pointer_.is_null()) {
241  continue;
242  }
243  if (bottom) {
245  } else {
247  }
248  }
249 
250  return kRetOk;
251 }
252 
254  const auto& resolver = engine_->get_memory_manager()->get_global_volatile_page_resolver();
255  HashDataPage* head = reinterpret_cast<HashDataPage*>(resolver.resolve_offset(head_page_id));
256  for (HashDataPage* cur = head; cur;) {
257  cur->header().hotness_.reset();
258  VolatilePagePointer next_id = cur->next_page().volatile_pointer_;
259  cur = nullptr;
260  if (!next_id.is_null()) {
261  cur = reinterpret_cast<HashDataPage*>(resolver.resolve_offset(next_id));
262  }
263  }
264  return kRetOk;
265 }
266 
267 } // namespace hash
268 } // namespace storage
269 } // 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*.
numa_alloc_onnode() and numa_free().
Represents a pointer to another page (usually a child page).
Definition: storage_id.hpp:271
ErrorStack debugout_single_thread(Engine *engine, bool volatile_only, bool intermediate_only, uint32_t max_pages)
These are defined in hash_storage_debug.cpp.
ErrorCode read_page(storage::SnapshotPagePointer page_id, void *out)
Automatically calls if uninitialize() wasn't called when it gets out of scope, and just complains whe...
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
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
ErrorStack uninitialize() override final
Typical implementation of Initializable::uninitialize() that provides uninitialize-once semantics...
Brings error stacktrace information as return value of functions.
Definition: error_stack.hpp:81
ErrorStack hcc_reset_all_temperature_stat()
For stupid reasons (I'm lazy!) these are defined in _debug.cpp.
void alloc(uint64_t size, uint64_t alignment, AllocType alloc_type, int numa_node) noexcept
Allocate a memory, releasing the current memory if exists.
Engine * engine_
Most attachable object stores an engine pointer (local engine), so we define it here.
Definition: attachable.hpp:107
Holds a set of read-only file objects for snapshot files.
ErrorStack hcc_reset_all_temperature_stat_intermediate(VolatilePagePointer intermediate_page_id)
VolatilePagePointer volatile_pointer_
Definition: storage_id.hpp:308
ErrorStack debugout_single_thread_data(Engine *engine, cache::SnapshotFileSet *fileset, HashDataPage *head, bool follow_volatile, uint32_t *remaining_pages)
HashStorageControlBlock * control_block_
The shared data on shared memory that has been initialized in some SOC or master engine.
Definition: attachable.hpp:111
uint64_t SnapshotPagePointer
Page ID of a snapshot page.
Definition: storage_id.hpp:79
Calls Initializable::uninitialize() automatically when it gets out of scope.
ErrorStack initialize() override final
Typical implementation of Initializable::initialize() that provides initialize-once semantics...
Database engine object that holds all resources and provides APIs.
Definition: engine.hpp:109
SnapshotPagePointer snapshot_pointer_
Definition: storage_id.hpp:307
Just a marker to denote that the memory region represents a data page.
Definition: page.hpp:334
void * get_block() const
Returns the memory block.
ErrorStack hcc_reset_all_temperature_stat_data(VolatilePagePointer head_page_id)
Represents a key-value store based on a dense and regular hash.
uint64_t get_size() const
Returns the byte size of the memory block.
ErrorStack debugout_single_thread_intermediate(Engine *engine, cache::SnapshotFileSet *fileset, HashIntermediatePage *parent, bool follow_volatile, bool intermediate_only, uint32_t *remaining_pages)
Represents an intermediate page in Hashtable Storage.
Represents an individual data page in Hashtable Storage.
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
Represents one memory block aligned to actual OS/hardware pages.
const ErrorStack kRetOk
Normal return value for no-error case.
const uint8_t kHashIntermediatePageFanout
Number of pointers in an intermediate page of hash storage.
Definition: hash_id.hpp:49
ErrorStack init(cache::SnapshotFileSet *files, SnapshotPagePointer pointer)
assorted::ProbCounter hotness_
Loosely maintained statistics on data temperature.
Definition: page.hpp:268
#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
Definitions of IDs in this package and a few related constant values.
#define WRAP_ERROR_CODE(x)
Same as CHECK_ERROR(x) except it receives only an error code, thus more efficient.
DualPagePointer & get_pointer(uint16_t index)
memory::EngineMemory * get_memory_manager() const
See Memory Manager.
Definition: engine.cpp:50
bool is_null() const
Returns if this object doesn't hold a valid memory block.