libfoedus-core
FOEDUS Core Library
engine_memory.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 <numa.h>
21 #include <glog/logging.h>
22 
23 #include <fstream>
24 #include <iostream>
25 #include <sstream>
26 #include <string>
27 #include <thread>
28 #include <vector>
29 
30 #include "foedus/engine.hpp"
37 #include "foedus/storage/page.hpp"
40 
41 namespace foedus {
42 namespace memory {
44  LOG(INFO) << "Initializing EngineMemory..";
45  if (!engine_->get_debug()->is_initialized()) {
47  } else if (::numa_available() < 0) {
48  LOG(WARNING) << "WARNING, this machine is not a NUMA machine. FOEDUS still works fine,"
49  << " but it is mainly designed for large servers with many sockets and cores";
50  // Even if the kernel is built without NUMA (eg ARMv8), we keep running.
51  // return ERROR_STACK(kErrorCodeMemoryNumaUnavailable);
52  }
53 
54  ASSERT_ND(node_memories_.empty());
55  const EngineOptions& options = engine_->get_options();
56  const thread::ThreadGroupId numa_nodes = options.thread_.group_count_;
58  uint64_t pool_begin = 0, pool_end = 0;
59  for (thread::ThreadGroupId node = 0; node < numa_nodes; ++node) {
60  NumaNodeMemoryRef* ref = new NumaNodeMemoryRef(engine_, node);
61  node_memories_.push_back(ref);
62  bases[node] = ref->get_volatile_pool()->get_base();
63  pool_begin = ref->get_volatile_pool()->get_resolver().begin_;
64  pool_end = ref->get_volatile_pool()->get_resolver().end_;
65  }
66  global_volatile_page_resolver_ = GlobalVolatilePageResolver(
67  bases,
68  numa_nodes,
69  pool_begin,
70  pool_end);
71 
72  // Initialize local memory.
73  if (!engine_->is_master()) {
74  soc::SocId node = engine_->get_soc_id();
75  local_memory_ = new NumaNodeMemory(engine_, node);
76  CHECK_ERROR(local_memory_->initialize());
77  LOG(INFO) << "Node memory-" << node << " was initialized!";
78  } else {
79  if (options.memory_.rigorous_memory_boundary_check_) {
80  LOG(WARNING) << "CAUTION: memory_.rigorous_memory_boundary_check_ is ON. We will"
81  << " put mprotect-ed pages between memory regions for debugging. It will be SLOW!";
82  }
83  if (options.memory_.rigorous_page_boundary_check_) {
84  LOG(WARNING) << "CAUTION: memory_.rigorous_page_boundary_check_ is ON. We will"
85  << " put mprotect-ed pages between every single page for debugging. It will be SLOOOW!";
86  }
87  }
88  return kRetOk;
89 }
90 
92  LOG(INFO) << "Uninitializing EngineMemory..";
93  ErrorStackBatch batch;
94  if (!engine_->get_debug()->is_initialized()) {
96  }
97  for (auto* ref : node_memories_) {
98  delete ref;
99  }
100  node_memories_.clear();
101 
102  // Uninitialize local memory.
103  if (!engine_->is_master() && local_memory_) {
104  soc::SocId node = engine_->get_soc_id();
105  batch.emprace_back(local_memory_->uninitialize());
106  delete local_memory_;
107  local_memory_ = nullptr;
108  LOG(INFO) << "Node memory-" << node << " was uninitialized!";
109  }
110  return SUMMARIZE_ERROR_BATCH(batch);
111 }
112 
114  return engine_->get_soc_manager()->get_shared_user_memory();
115 }
116 
118  return engine_->get_soc_manager()->get_shared_user_memory_size();
119 }
120 
122  std::stringstream ret;
123  ret << " == Free memory stat ==" << std::endl;
124  thread::ThreadGroupId numa_nodes = engine_->get_options().thread_.group_count_;
125  for (thread::ThreadGroupId node = 0; node < numa_nodes; ++node) {
126  NumaNodeMemoryRef* memory = node_memories_[node];
127  ret << " - Node_" << static_cast<int>(node) << " -" << std::endl;
128  ret << memory->dump_free_memory_stat();
129  if (node + 1U < numa_nodes) {
130  ret << std::endl;
131  }
132  }
133  return ret.str();
134 }
135 
139  storage::Page** page) {
140  PagePool* pool = get_node_memory(node)->get_volatile_pool();
141  PagePoolOffset offset;
142  WRAP_ERROR_CODE(pool->grab_one(&offset));
143  *page = pool->get_resolver().resolve_offset_newpage(offset);
144  pointer->set(node, offset);
145  return kRetOk;
146 }
147 
149  cache::SnapshotFileSet* fileset,
150  storage::SnapshotPagePointer snapshot_pointer,
152  storage::Page** page) {
153  ASSERT_ND(snapshot_pointer != 0);
155  CHECK_ERROR(grab_one_volatile_page(node, pointer, page));
156  WRAP_ERROR_CODE(fileset->read_page(snapshot_pointer, *page));
157  (*page)->get_header().snapshot_ = false;
158  (*page)->get_header().page_id_ = pointer->word;
159  return kRetOk;
160 }
161 
162 } // namespace memory
163 } // namespace foedus
ErrorStack uninitialize_once() override
std::string dump_free_memory_stat() const
Report rough statistics of free memory.
Definitions of IDs in this package and a few related constant values.
ErrorCode read_page(storage::SnapshotPagePointer page_id, void *out)
void emprace_back(ErrorStack &&error_stack)
If the given ErrorStack is an error, this method adds it to the end of this batch.
#define ERROR_STACK(e)
Instantiates ErrorStack with the given foedus::error_code, creating an error stack with the current f...
Page pool for volatile read/write store (VolatilePage) and the read-only bufferpool (SnapshotPage)...
Definition: page_pool.hpp:173
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
ErrorCode grab_one(PagePoolOffset *offset)
Grab only one page.
Definition: page_pool.cpp:132
uint32_t PagePoolOffset
Offset in PagePool that compactly represents the page address (unlike 8 bytes pointer).
Definition: memory_id.hpp:44
Typedefs of ID types used in thread package.
0x0005 : "GENERAL: A dependent module is not initialized yet. This implies a wrong initialization ord...
Definition: error_code.hpp:109
Represents a pointer to a volatile page with modification count for preventing ABA.
Definition: storage_id.hpp:194
storage::Page * resolve_offset_newpage(PagePoolOffset offset) const __attribute__((always_inline))
As the name suggests, this version is for new pages, which don't have sanity checks.
ErrorStack load_one_volatile_page(cache::SnapshotFileSet *fileset, storage::SnapshotPagePointer snapshot_pointer, storage::VolatilePagePointer *pointer, storage::Page **page)
Another convenience method that also reads an existing snapshot page to the volatile page...
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
Holds a set of read-only file objects for snapshot files.
ErrorStack initialize_once() override
void * get_shared_user_memory() const
As part of the global shared memory, we reserve this size of 'user memory' that can be used for arbit...
const EngineOptions & get_options() const
Definition: engine.cpp:39
bool is_master() const
Returns if this engine object is a master instance.
Definition: engine.cpp:68
PagePoolOffset end_
where a valid page entry ends.
A view of NumaNodeMemory for other SOCs and master engine.
Batches zero or more ErrorStack objects to represent in one ErrorStack.
storage::Page * get_base() const
Definition: page_pool.cpp:119
int numa_available(void)
uint64_t get_shared_user_memory_size() const
Definition: soc_manager.cpp:43
void * get_shared_user_memory() const
Shortcut for get_shared_memory_repo()->get_global_user_memory()
Definition: soc_manager.cpp:40
uint64_t SnapshotPagePointer
Page ID of a snapshot page.
Definition: storage_id.hpp:79
ErrorStack initialize() override final
Typical implementation of Initializable::initialize() that provides initialize-once semantics...
Repository of memories dynamically acquired and shared within one NUMA node (socket).
NumaNodeMemoryRef * get_node_memory(foedus::thread::ThreadGroupId group) const
Just a marker to denote that the memory region represents a data page.
Definition: page.hpp:334
void set(uint8_t numa_node, memory::PagePoolOffset offset)
Definition: storage_id.hpp:212
Set of option values given to the engine at start-up.
ErrorStack grab_one_volatile_page(foedus::thread::ThreadGroupId node, storage::VolatilePagePointer *pointer, storage::Page **page)
A convenience function to grab one free volatile page from the given node.
uint8_t extract_numa_node_from_snapshot_pointer(SnapshotPagePointer pointer)
Definition: storage_id.hpp:95
uint16_t group_count_
Number of ThreadGroup in the engine.
uint64_t get_shared_user_memory_size() const
#define SUMMARIZE_ERROR_BATCH(x)
This macro calls ErrorStackBatch::summarize() with automatically provided parameters.
std::string dump_free_memory_stat() const
Report rough statistics of free memory.
uint16_t SocId
Represents an ID of an SOC, or NUMA node.
Definition: soc_id.hpp:41
thread::ThreadOptions thread_
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
soc::SocManager * get_soc_manager() const
See SOC and IPC.
Definition: engine.cpp:59
Resolves an offset in a volatile page pool to an actual pointer and vice versa.
PagePoolOffset begin_
where a valid page entry starts.
soc::SocId get_soc_id() const
If this is a child instance, returns its SOC ID (NUMA node).
Definition: engine.cpp:73
const LocalPageResolver & get_resolver() const
Gives an object to resolve an offset in this page pool (thus local) to an actual pointer and vice ver...
Definition: page_pool.cpp:146
debugging::DebuggingSupports * get_debug() const
See Debug-Support functionalities.
Definition: engine.cpp:48
0x0006 : "GENERAL: A dependent module is already uninitialized. This implies a wrong uninitialization...
Definition: error_code.hpp:110
#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
#define WRAP_ERROR_CODE(x)
Same as CHECK_ERROR(x) except it receives only an error code, thus more efficient.
uint8_t ThreadGroupId
Typedef for an ID of ThreadGroup (NUMA node).
Definition: thread_id.hpp:38
bool is_initialized() const override final
Returns whether the object has been already initialized or not.