libfoedus-core
FOEDUS Core Library
shared_memory_repo.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 <unistd.h>
21 
22 #include <cstring>
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26 #include <thread>
27 #include <vector>
28 
29 #include "foedus/assert_nd.hpp"
31 #include "foedus/storage/page.hpp"
33 
34 namespace foedus {
35 namespace soc {
36 
37 std::string get_self_path(uint64_t upid, Eid eid) {
38  std::string pid_str = std::to_string(upid);
39  std::string eid_str = std::to_string(eid);
40  return std::string("/tmp/libfoedus_shm_") + pid_str + std::string("_") + eid_str;
41 }
42 std::string get_master_path(uint64_t master_upid, Eid master_eid) {
43  std::string pid_str = std::to_string(master_upid);
44  std::string eid_str = std::to_string(master_eid);
45  return std::string("/tmp/libfoedus_shm_") + pid_str + std::string("_") + eid_str;
46 }
47 
52 }
53 
55  if (logger_memories_) {
56  delete[] logger_memories_;
57  logger_memories_ = nullptr;
58  }
59  if (thread_anchors_) {
60  delete[] thread_anchors_;
61  thread_anchors_ = nullptr;
62  }
63 }
64 
65 uint64_t align_4kb(uint64_t value) { return assorted::align< uint64_t, (1U << 12) >(value); }
66 uint64_t align_2mb(uint64_t value) { return assorted::align< uint64_t, (1U << 21) >(value); }
67 
68 void SharedMemoryRepo::allocate_one_node(
69  uint64_t upid,
70  Eid eid,
71  uint16_t node,
72  uint64_t node_memory_size,
73  bool rigorous_memory_boundary_check,
74  bool rigorous_page_boundary_check,
75  ErrorStack* alloc_result,
76  SharedMemoryRepo* repo) {
77  // NEVER do COERCE_ERROR here. We must responsibly release shared memory even on errors.
78  std::string node_memory_path
79  = get_self_path(upid, eid) + std::string("_node_") + std::to_string(node);
80  bool use_hugepages = true;
81  if (rigorous_memory_boundary_check || rigorous_page_boundary_check) {
82  // when mprotect is enabled, we cannot use hugepages
83  use_hugepages = false;
84  }
85  *alloc_result = repo->node_memories_[node].alloc(
86  node_memory_path,
87  node_memory_size,
88  node,
89  use_hugepages);
90  if (alloc_result->is_error()) {
91  repo->node_memories_[node].release_block();
92  return;
93  }
94 }
95 
97  uint64_t upid,
98  Eid eid,
99  const EngineOptions& options) {
101  init_empty(options);
102 
103  // We place a serialized EngineOptions in the beginning of shared memory.
104  std::stringstream options_stream;
105  options.save_to_stream(&options_stream);
106  std::string xml(options_stream.str());
107  uint64_t xml_size = xml.size();
108 
109  // construct unique meta files using PID.
110  uint64_t global_memory_size = align_2mb(calculate_global_memory_size(xml_size, options));
111  std::string global_memory_path = get_self_path(upid, eid) + std::string("_global");
112  const bool global_hugepages = !options.memory_.rigorous_memory_boundary_check_;
113  CHECK_ERROR(global_memory_.alloc(global_memory_path, global_memory_size, 0, global_hugepages));
114 
115  // from now on, be very careful to not exit without releasing this shared memory.
116 
117  set_global_memory_anchors(xml_size, options, true);
119 
120  // copy the EngineOptions string into the beginning of the global memory
121  std::memcpy(global_memory_.get_block(), &xml_size, sizeof(xml_size));
122  std::memcpy(global_memory_.get_block() + sizeof(xml_size), xml.data(), xml_size);
123 
124  // the following is parallelized
125  uint64_t node_memory_size = align_2mb(calculate_node_memory_size(options));
126  ErrorStack alloc_results[kMaxSocs];
127  std::vector< std::thread > alloc_threads;
128  for (uint16_t node = 0; node < soc_count_; ++node) {
129  alloc_threads.emplace_back(std::thread(
130  SharedMemoryRepo::allocate_one_node,
131  upid,
132  eid,
133  node,
134  node_memory_size,
137  alloc_results + node,
138  this));
139  }
140 
141  ErrorStack last_error;
142  bool failed = false;
143  for (uint16_t node = 0; node < soc_count_; ++node) {
144  alloc_threads[node].join();
145  if (alloc_results[node].is_error()) {
146  std::cerr << "[FOEDUS] Failed to allocate node shared memory for node-" << node
147  << ". " << alloc_results[node] << std::endl;
148  last_error = alloc_results[node];
149  failed = true;
150  }
151  }
152 
153  if (failed) {
155  return last_error;
156  }
157 
158  for (uint16_t node = 0; node < soc_count_; ++node) {
159  set_node_memory_anchors(node, options, true);
160  }
161 
162  return kRetOk;
163 }
164 
166  uint64_t master_upid,
167  Eid master_eid,
168  SocId my_soc_id,
169  EngineOptions* options) {
171 
172  std::string base = get_master_path(master_upid, master_eid);
173  std::string global_memory_path = base + std::string("_global");
174  const bool global_hugepages = !options->memory_.rigorous_memory_boundary_check_;
175  global_memory_.attach(global_memory_path, global_hugepages);
176  if (global_memory_.is_null()) {
179  }
180 
181  // read the options from global_memory
182  uint64_t xml_size = 0;
183  std::memcpy(&xml_size, global_memory_.get_block(), sizeof(xml_size));
184  ASSERT_ND(xml_size > 0);
185  std::string xml(global_memory_.get_block() + sizeof(xml_size), xml_size);
186  CHECK_ERROR(options->load_from_string(xml));
187 
188  my_soc_id_ = my_soc_id;
189  init_empty(*options);
190  set_global_memory_anchors(xml_size, *options, false);
191 
192  bool failed = false;
193  for (uint16_t node = 0; node < soc_count_; ++node) {
194  std::string node_memory_str = base + std::string("_node_") + std::to_string(node);
195  node_memories_[node].attach(node_memory_str, !options->memory_.rigorous_memory_boundary_check_);
196  if (node_memories_[node].is_null()) {
197  failed = true;
198  } else {
199  set_node_memory_anchors(node, *options, false);
200  }
201  }
202 
203  if (failed) {
204  if (!node_memories_[my_soc_id].is_null()) {
205  // then we can at least notify the error via the shared memory
207  }
210  }
211  return kRetOk;
212 }
213 
215  // mark_for_release() is idempotent, so just do it on all of them
216  global_memory_.mark_for_release();
217  for (uint16_t i = 0; i < soc_count_; ++i) {
218  if (node_memories_) {
219  node_memories_[i].mark_for_release();
220  }
221  }
222 }
225 
226  if (!global_memory_.is_null()) {
227  if (global_memory_anchors_.protected_boundaries_needs_release_) {
228  for (uint32_t i = 0; i < global_memory_anchors_.protected_boundaries_count_; ++i) {
229  assorted::ProtectedBoundary* boundary = global_memory_anchors_.protected_boundaries_[i];
230  boundary->release_protect();
231  boundary->assert_boundary();
232  }
233  }
234  }
235  global_memory_anchors_.clear();
236 
237  // release_block() is idempotent, so just do it on all of them
238  global_memory_.release_block();
239 
240  for (uint16_t i = 0; i < soc_count_; ++i) {
241  if (node_memories_) {
242  if (node_memory_anchors_[i].protected_boundaries_needs_release_) {
243  for (uint32_t j = 0; j < node_memory_anchors_[i].protected_boundaries_count_; ++j) {
244  assorted::ProtectedBoundary* boundary = node_memory_anchors_[i].protected_boundaries_[j];
245  boundary->release_protect();
246  boundary->assert_boundary();
247  }
248  }
249 
250  node_memories_[i].release_block();
251  }
252  }
253 
254  if (node_memories_) {
255  delete[] node_memories_;
256  node_memories_ = nullptr;
257  }
258  if (node_memory_anchors_) {
259  delete[] node_memory_anchors_;
260  node_memory_anchors_ = nullptr;
261  }
262  soc_count_ = 0;
263 }
264 
265 void SharedMemoryRepo::init_empty(const EngineOptions& options) {
266  soc_count_ = options.thread_.group_count_;
267  node_memories_ = new memory::SharedMemory[soc_count_];
268  node_memory_anchors_ = new NodeMemoryAnchors[soc_count_];
269  for (uint16_t node = 0; node < soc_count_; ++node) {
270  node_memory_anchors_[node].allocate_arrays(options);
271  }
272 }
273 
274 void SharedMemoryRepo::set_global_memory_anchors(
275  uint64_t xml_size,
276  const EngineOptions& options,
277  bool reset_boundaries) {
278  char* base = global_memory_.get_block();
279  uint64_t total = 0;
280  global_memory_anchors_.options_xml_length_ = xml_size;
281  global_memory_anchors_.options_xml_ = base + sizeof(uint64_t);
282  total += align_4kb(sizeof(uint64_t) + xml_size);
283  put_global_memory_boundary(&total, "options_xml_boundary", reset_boundaries);
284 
285  global_memory_anchors_.master_status_memory_
286  = reinterpret_cast<MasterEngineStatus*>(base + total);
288  put_global_memory_boundary(&total, "master_status_memory_boundary", reset_boundaries);
289 
290  global_memory_anchors_.log_manager_memory_
291  = reinterpret_cast<log::LogManagerControlBlock*>(base + total);
293  put_global_memory_boundary(&total, "log_manager_memory_boundary", reset_boundaries);
294 
295  global_memory_anchors_.meta_logger_memory_
296  = reinterpret_cast<log::MetaLogControlBlock*>(base + total);
298  put_global_memory_boundary(&total, "meta_logger_memory_boundary", reset_boundaries);
299 
300  global_memory_anchors_.restart_manager_memory_
301  = reinterpret_cast<restart::RestartManagerControlBlock*>(base + total);
303  put_global_memory_boundary(&total, "restart_manager_memory_boundary", reset_boundaries);
304 
305  global_memory_anchors_.savepoint_manager_memory_
306  = reinterpret_cast<savepoint::SavepointManagerControlBlock*>(base + total);
308  put_global_memory_boundary(&total, "savepoint_manager_memory_boundary", reset_boundaries);
309 
310  global_memory_anchors_.snapshot_manager_memory_
311  = reinterpret_cast<snapshot::SnapshotManagerControlBlock*>(base + total);
313  put_global_memory_boundary(&total, "snapshot_manager_memory_boundary", reset_boundaries);
314 
315  global_memory_anchors_.storage_manager_memory_
316  = reinterpret_cast<storage::StorageManagerControlBlock*>(base + total);
318  put_global_memory_boundary(&total, "storage_manager_memory_boundary", reset_boundaries);
319 
320  global_memory_anchors_.xct_manager_memory_
321  = reinterpret_cast<xct::XctManagerControlBlock*>(base + total);
323  put_global_memory_boundary(&total, "xct_manager_memory_boundary", reset_boundaries);
324 
325  global_memory_anchors_.partitioner_metadata_
326  = reinterpret_cast<storage::PartitionerMetadata*>(base + total);
327  total += align_4kb(sizeof(storage::PartitionerMetadata) * options.storage_.max_storages_);
328  put_global_memory_boundary(&total, "partitioner_metadata_boundary", reset_boundaries);
329  global_memory_anchors_.partitioner_data_ = base + total;
330  total += static_cast<uint64_t>(options.storage_.partitioner_data_memory_mb_) << 20;
331  put_global_memory_boundary(&total, "partitioner_data_boundary", reset_boundaries);
332 
333  global_memory_anchors_.storage_name_sort_memory_
334  = reinterpret_cast<storage::StorageId*>(base + total);
335  total += align_4kb(sizeof(storage::StorageId) * options.storage_.max_storages_);
336  put_global_memory_boundary(&total, "storage_name_sort_memory_boundary", reset_boundaries);
337 
338  global_memory_anchors_.storage_memories_
339  = reinterpret_cast<storage::StorageControlBlock*>(base + total);
340  total += static_cast<uint64_t>(GlobalMemoryAnchors::kStorageMemorySize)
341  * options.storage_.max_storages_;
342  put_global_memory_boundary(&total, "storage_memories_boundary", reset_boundaries);
343 
344  global_memory_anchors_.user_memory_ = base + total;
345  total += align_4kb(1024ULL * options.soc_.shared_user_memory_size_kb_);
346  put_global_memory_boundary(&total, "user_memory_boundary", reset_boundaries);
347 
348  // we have to be super careful here. let's not use assertion.
349  if (calculate_global_memory_size(xml_size, options) != total) {
350  std::cerr << "[FOEDUS] global memory size doesn't match. bug?"
351  << " allocated=" << calculate_global_memory_size(xml_size, options)
352  << ", expected=" << total << std::endl;
353  }
354 
355  if (options.memory_.rigorous_memory_boundary_check_) {
356  // this might mean mprotect() multiple times when SOCs are emulated SOCs.
357  // however, acquire_protect() is idempotent, hence it's fine.
358  for (assorted::ProtectedBoundary* boundary : global_memory_anchors_.protected_boundaries_) {
359  boundary->acquire_protect();
360  }
361  global_memory_anchors_.protected_boundaries_needs_release_ = true;
362  }
363 }
364 
366  uint64_t xml_size,
367  const EngineOptions& options) {
368  const uint64_t kBoundarySize = sizeof(assorted::ProtectedBoundary);
369  uint64_t total = 0;
370  total += align_4kb(sizeof(xml_size) + xml_size) + kBoundarySize; // options_xml_
371  total += GlobalMemoryAnchors::kMasterStatusMemorySize + kBoundarySize;
372  total += GlobalMemoryAnchors::kLogManagerMemorySize + kBoundarySize;
373  total += GlobalMemoryAnchors::kMetaLoggerSize + kBoundarySize;
374  total += GlobalMemoryAnchors::kRestartManagerMemorySize + kBoundarySize;
375  total += GlobalMemoryAnchors::kSavepointManagerMemorySize + kBoundarySize;
376  total += GlobalMemoryAnchors::kSnapshotManagerMemorySize + kBoundarySize;
377  total += GlobalMemoryAnchors::kStorageManagerMemorySize + kBoundarySize;
378  total += GlobalMemoryAnchors::kXctManagerMemorySize + kBoundarySize;
379  total +=
381  + kBoundarySize;
382  total +=
383  (static_cast<uint64_t>(options.storage_.partitioner_data_memory_mb_) << 20)
384  + kBoundarySize;
385  total +=
387  + kBoundarySize;
388  total +=
389  static_cast<uint64_t>(GlobalMemoryAnchors::kStorageMemorySize) * options.storage_.max_storages_
390  + kBoundarySize;
391  total += align_4kb(1024ULL * options.soc_.shared_user_memory_size_kb_) + kBoundarySize;
392  return total;
393 }
394 
395 void SharedMemoryRepo::set_node_memory_anchors(
396  SocId node,
397  const EngineOptions& options,
398  bool reset_boundaries) {
399  char* base = node_memories_[node].get_block();
400  NodeMemoryAnchors& anchor = node_memory_anchors_[node];
401  uint64_t total = 0;
402  anchor.child_status_memory_ = reinterpret_cast<ChildEngineStatus*>(base);
404  put_node_memory_boundary(node, &total, "node_child_status_memory_boundary", reset_boundaries);
405 
406  anchor.volatile_pool_status_ = reinterpret_cast<memory::PagePoolControlBlock*>(base + total);
408  put_node_memory_boundary(node, &total, "node_volatile_pool_status_boundary", reset_boundaries);
409 
410  anchor.proc_manager_memory_ = reinterpret_cast<proc::ProcManagerControlBlock*>(base + total);
412  put_node_memory_boundary(node, &total, "node_proc_manager_memory_boundary", reset_boundaries);
413 
414  anchor.proc_memory_ = reinterpret_cast<proc::ProcAndName*>(base + total);
415  total += align_4kb(sizeof(proc::ProcAndName) * options.proc_.max_proc_count_);
416  put_node_memory_boundary(node, &total, "node_proc_memory_boundary", reset_boundaries);
417 
418  anchor.proc_name_sort_memory_ = reinterpret_cast<proc::LocalProcId*>(base + total);
419  total += align_4kb(sizeof(proc::LocalProcId) * options.proc_.max_proc_count_);
420  put_node_memory_boundary(node, &total, "node_proc_name_sort_memory_boundary", reset_boundaries);
421 
422  anchor.log_reducer_memory_ = reinterpret_cast<snapshot::LogReducerControlBlock*>(base + total);
424  put_node_memory_boundary(node, &total, "node_log_reducer_memory_boundary", reset_boundaries);
425 
426  anchor.log_reducer_root_info_pages_ = reinterpret_cast<storage::Page*>(base + total);
427  total += options.storage_.max_storages_ * 4096ULL;
428  put_node_memory_boundary(
429  node,
430  &total,
431  "node_log_reducer_root_info_pages_boundary",
432  reset_boundaries);
433 
434  for (uint16_t i = 0; i < options.log_.loggers_per_node_; ++i) {
435  anchor.logger_memories_[i] = reinterpret_cast<log::LoggerControlBlock*>(base + total);
437  put_node_memory_boundary(node, &total, "node_logger_memories_boundary", reset_boundaries);
438  }
439 
440  for (uint16_t i = 0; i < options.thread_.thread_count_per_group_; ++i) {
441  ThreadMemoryAnchors& thread_anchor = anchor.thread_anchors_[i];
442  thread_anchor.thread_memory_ = reinterpret_cast<thread::ThreadControlBlock*>(base + total);
444  put_node_memory_boundary(node, &total, "thread_memory_boundary", reset_boundaries);
445 
446  thread_anchor.task_input_memory_ = base + total;
448  put_node_memory_boundary(node, &total, "thread_task_input_memory_boundary", reset_boundaries);
449 
450  thread_anchor.task_output_memory_ = base + total;
452  put_node_memory_boundary(node, &total, "thread_task_output_memory_boundary", reset_boundaries);
453 
454  thread_anchor.mcs_ww_lock_memories_ = reinterpret_cast<xct::McsWwBlock*>(base + total);
456  put_node_memory_boundary(node, &total, "thread_mcs_lock_memories_boundary", reset_boundaries);
457 
458  thread_anchor.mcs_rw_simple_lock_memories_
459  = reinterpret_cast<xct::McsRwSimpleBlock*>(base + total);
461  put_node_memory_boundary(
462  node, &total, "thread_mcs_rw_simple_lock_memories_boundary", reset_boundaries);
463  thread_anchor.mcs_rw_extended_lock_memories_
464  = reinterpret_cast<xct::McsRwExtendedBlock*>(base + total);
466  put_node_memory_boundary(
467  node, &total, "thread_mcs_rw_extended_lock_memories_boundary", reset_boundaries);
468 
469  thread_anchor.mcs_rw_async_mappings_memories_
470  = reinterpret_cast<xct::McsRwAsyncMapping*>(base + total);
472  put_node_memory_boundary(
473  node, &total, "thread_mcs_rw_async_mappings_memories_boundary", reset_boundaries);
474  }
475 
476  // This is larger than others (except volatile pool). we place this at the end.
477  uint64_t reducer_buffer_size
478  = static_cast<uint64_t>(options.snapshot_.log_reducer_buffer_mb_) << 20;
479  anchor.log_reducer_buffers_[0] = base + total;
480  anchor.log_reducer_buffers_[1] = base + total + (reducer_buffer_size / 2);
481  total += reducer_buffer_size;
482  put_node_memory_boundary(node, &total, "node_log_reducer_buffers_boundary", reset_boundaries);
483 
484  // Then volatile pool at the end. This is even bigger
485  anchor.volatile_page_pool_ = base + total;
486  total += (static_cast<uint64_t>(options.memory_.page_pool_size_mb_per_node_) << 20);
487  put_node_memory_boundary(node, &total, "volatile_pool_boundary", reset_boundaries);
488 
489  // we have to be super careful here. let's not use assertion.
490  if (total != calculate_node_memory_size(options)) {
491  std::cerr << "[FOEDUS] node memory size doesn't match. bug?"
492  << " allocated=" << calculate_node_memory_size(options)
493  << ", expected=" << total << std::endl;
494  }
495 
496  // same as global memory
498  for (assorted::ProtectedBoundary* boundary : anchor.protected_boundaries_) {
499  boundary->acquire_protect();
500  }
502  }
503 }
504 
506  const uint64_t kBoundarySize = sizeof(assorted::ProtectedBoundary);
507  uint64_t total = 0;
508  total += NodeMemoryAnchors::kChildStatusMemorySize + kBoundarySize;
509  total += NodeMemoryAnchors::kPagePoolMemorySize + kBoundarySize;
510  total += NodeMemoryAnchors::kProcManagerMemorySize + kBoundarySize;
511  total += align_4kb(sizeof(proc::ProcAndName) * options.proc_.max_proc_count_) + kBoundarySize;
512  total += align_4kb(sizeof(proc::LocalProcId) * options.proc_.max_proc_count_) + kBoundarySize;
513  total += NodeMemoryAnchors::kLogReducerMemorySize + kBoundarySize;
514  total += options.storage_.max_storages_ * 4096ULL + kBoundarySize;
515 
516  uint64_t loggers_per_node = options.log_.loggers_per_node_;
517  total += loggers_per_node * (NodeMemoryAnchors::kLoggerMemorySize + kBoundarySize);
518 
519  uint64_t threads_per_node = options.thread_.thread_count_per_group_;
520  total += threads_per_node * (ThreadMemoryAnchors::kThreadMemorySize + kBoundarySize);
521  total += threads_per_node * (ThreadMemoryAnchors::kTaskInputMemorySize + kBoundarySize);
522  total += threads_per_node * (ThreadMemoryAnchors::kTaskOutputMemorySize + kBoundarySize);
523  total += threads_per_node * (ThreadMemoryAnchors::kMcsWwLockMemorySize + kBoundarySize);
524  total += threads_per_node * (ThreadMemoryAnchors::kMcsRwLockMemorySize + kBoundarySize);
525  total += threads_per_node * (ThreadMemoryAnchors::kMcsRwLockMemorySize + kBoundarySize);
526  total += threads_per_node * (ThreadMemoryAnchors::kMcsRwAsyncMappingMemorySize + kBoundarySize);
527 
528  total +=
529  (static_cast<uint64_t>(options.snapshot_.log_reducer_buffer_mb_) << 20)
530  + kBoundarySize;
531 
532  // Then volatile pool at the end.
533  total +=
534  (static_cast<uint64_t>(options.memory_.page_pool_size_mb_per_node_) << 20)
535  + kBoundarySize;
536  return total;
537 }
538 
540  global_memory_anchors_.master_status_memory_->change_status_atomic(new_status);
541 }
542 
544  return global_memory_anchors_.master_status_memory_->read_status_atomic();
545 }
546 
548  node_memory_anchors_[node].child_status_memory_->change_status_atomic(new_status);
549 }
550 
552  return node_memory_anchors_[node].child_status_memory_->read_status_atomic();
553 }
554 
555 
556 } // namespace soc
557 } // namespace foedus
ErrorStack load_from_string(const std::string &xml)
Load the content of this object from the given XML string.
uint32_t protected_boundaries_count_
To be a POD, we avoid vector and instead uses a fix-sized array.
ErrorStack allocate_shared_memories(uint64_t upid, Eid eid, const EngineOptions &options)
Master process creates shared memories by calling this method.
void save_to_stream(std::ostream *ptr) const
Invokes save() and directs the resulting XML text to the given stream.
0x0C02 : "SOC : Failed to attach a shared memory." .
Definition: error_code.hpp:221
A 4kb dummy data placed between separate memory regions so that we can check if/where a bogus memory ...
void change_master_status(MasterEngineStatus::StatusCode new_status)
#define ERROR_STACK(e)
Instantiates ErrorStack with the given foedus::error_code, creating an error stack with the current f...
storage::StorageId * storage_name_sort_memory_
This memory stores the ID of storages sorted by their names.
uint32_t StorageId
Unique ID for storage.
Definition: storage_id.hpp:55
uint64_t options_xml_length_
The beginning of global memory is an XML-serialized EngineOption.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
void * partitioner_data_
Data block to place detailed information of partitioners.
proc::LocalProcId * proc_name_sort_memory_
This memory stores the ID of procedures sorted by their names.
log::LogManagerControlBlock * log_manager_memory_
Tiny memory for log manager.
StatusCode
These statuses represent each step described in SocManager comment.
log::LoggerControlBlock ** logger_memories_
Status and synchronization mechanism for loggers on this node.
void * volatile_page_pool_
By far the largest memory for volatile page pool on this node.
Shared data of ThreadPimpl.
void deallocate_shared_memories()
Detaches and releases the shared memories.
void change_status_atomic(StatusCode new_status)
Update the value of status_code_ with fence.
char * get_block() const
Returns the memory block.
void change_status_atomic(StatusCode new_status)
Update the value of status_code_ with fence.
std::string get_self_path(uint64_t upid, Eid eid)
uint64_t align_4kb(uint64_t value)
Brings error stacktrace information as return value of functions.
Definition: error_stack.hpp:81
Reader-writer (RW) MCS lock classes.
Definition: xct_id.hpp:387
void * user_memory_
This 'user memory' can be used for arbitrary purporses by the user to communicate between SOCs...
StatusCode read_status_atomic() const
Read status_code_ with fence.
Same as GlobalMemoryAnchors except this is for node_memories_.
void mark_for_release()
Marks shared memories as being removed so that it will be reclaimed when all processes detach it...
Part of NodeMemoryAnchors for each thread.
uint64_t align_2mb(uint64_t value)
proc::ProcOptions proc_
log::MetaLogControlBlock * meta_logger_memory_
Tiny memory for metadata logger.
bool rigorous_memory_boundary_check_
Whether to use mprotect() for memory boundaries to detect bogus memory accesses.
uint32_t max_storages_
Maximum number of storages in this database.
ThreadLocalOrdinal thread_count_per_group_
Number of Thread in each ThreadGroup.
storage::StorageControlBlock * storage_memories_
Status of each storage instance is stored in this shared memory.
Represents memory shared between processes.
proc::ProcManagerControlBlock * proc_manager_memory_
ProcManagers's status and its synchronization mechanism on this node.
storage::StorageManagerControlBlock * storage_manager_memory_
Tiny memory for storage manager.
uint32_t partitioner_data_memory_mb_
Size in MB of a shared memory buffer allocated for all partitioners during log gleaning.
uint32_t protected_boundaries_count_
To be a POD, we avoid vector and instead uses a fix-sized array.
memory::MemoryOptions memory_
storage::PartitionerMetadata * partitioner_metadata_
Tiny metadata memory for partitioners.
Pre-allocated MCS block for WW-locks.
Definition: xct_id.hpp:274
storage::StorageOptions storage_
ErrorStack attach_shared_memories(uint64_t master_upid, Eid master_eid, SocId my_soc_id, EngineOptions *options)
Child processes (emulated or not) set a reference to shared memory and receive the EngnieOption value...
static uint64_t calculate_global_memory_size(uint64_t xml_size, const EngineOptions &options)
snapshot::SnapshotOptions snapshot_
Pre-allocated MCS block for extended version of RW-locks.
Definition: xct_id.hpp:513
thread::ThreadControlBlock * thread_memory_
Status and synchronization mechanism for impersonation of this thread.
Just a marker to denote that the memory region represents a data page.
Definition: page.hpp:334
std::pair< ProcName, Proc > ProcAndName
Just a std::pair.
Definition: proc_id.hpp:119
Set of option values given to the engine at start-up.
snapshot::LogReducerControlBlock * log_reducer_memory_
Tiny control memory for LogReducer in this node.
Current status of a child SOC engine.
static uint64_t calculate_node_memory_size(const EngineOptions &options)
void * log_reducer_buffers_[2]
Actual buffers for LogReducer.
std::string get_master_path(uint64_t master_upid, Eid master_eid)
uint16_t group_count_
Number of ThreadGroup in the engine.
xct::XctManagerControlBlock * xct_manager_memory_
Tiny memory for xct manager.
Shared data of Logger.
Definition: logger_impl.hpp:51
void attach(const std::string &meta_path, bool use_hugepages)
Attach an already-allocated shared memory so that this object points to the memory.
snapshot::SnapshotManagerControlBlock * snapshot_manager_memory_
Tiny memory for snapshot manager.
uint32_t log_reducer_buffer_mb_
The size in MB of a buffer to store log entries in reducer (partition).
storage::Page * log_reducer_root_info_pages_
This is the 'output' of the reducer in this node.
Shared data in PagePoolPimpl.
uint16_t SocId
Represents an ID of an SOC, or NUMA node.
Definition: soc_id.hpp:41
ThreadMemoryAnchors * thread_anchors_
Anchors for each thread.
void assert_boundary() const
Called at shutdown to check whether these boundaries were not accessed.
thread::ThreadOptions thread_
Tiny metadata of partitioner for every storage used while log gleaning.
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
uint32_t page_pool_size_mb_per_node_
Size of the page pool in MB per each NUMA node.
proc::ProcAndName * proc_memory_
Procedure list on this node.
const ErrorStack kRetOk
Normal return value for no-error case.
MasterEngineStatus * master_status_memory_
This tiny piece of memory contains the current status of the master engine and its synchronization me...
This small control block is used to synchronize the access to the array.
void allocate_arrays(const EngineOptions &options)
ChildEngineStatus * child_status_memory_
This tiny piece of memory contains the current status of the child engine on this node...
savepoint::SavepointManagerControlBlock * savepoint_manager_memory_
Tiny memory for savepoint manager.
uint32_t LocalProcId
Represents a locally-unique ID of a procedure in one SOC.
Definition: proc_id.hpp:56
uint64_t Eid
An Engine ID to differentiate two Engine objects instantiated in the same process.
Definition: engine_type.hpp:29
uint32_t max_proc_count_
Maximum number of system/user procedures.
assorted::ProtectedBoundary * protected_boundaries_[kMaxBoundaries]
sanity check boundaries to detect bogus memory accesses that overrun a memory region ...
void change_child_status(SocId node, ChildEngineStatus::StatusCode new_status)
#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
ErrorCode release_protect()
Removes all access restrictions via mprotect().
void mark_for_release()
Marks the shared memory as being removed so that it will be reclaimed when all processes detach it...
restart::RestartManagerControlBlock * restart_manager_memory_
Tiny memory for restart manager.
bool rigorous_page_boundary_check_
Whether to use mprotect() for page boundaries to detect bogus memory accesses.
bool is_null() const
Returns if this object doesn't hold a valid memory block.
bool protected_boundaries_needs_release_
whether we have invoked mprotect on them
StatusCode read_status_atomic() const
Read status_code_ with fence.
memory::PagePoolControlBlock * volatile_pool_status_
PagePool's status and its synchronization mechanism for the volatile pool on this node...
uint64_t shared_user_memory_size_kb_
As part of the global shared memory, we reserve this size of 'user memory' that can be used for arbit...
Definition: soc_options.hpp:60
ErrorStack alloc(const std::string &meta_path, uint64_t size, int numa_node, bool use_hugepages)
Newly allocate a shared memory of given size on given NUMA node.
bool protected_boundaries_needs_release_
whether we have invoked mprotect on them
ChildEngineStatus::StatusCode get_child_status(SocId node) const
assorted::ProtectedBoundary * protected_boundaries_[kMaxBoundaries]
sanity check boundaries to detect bogus memory accesses that overrun a memory region ...
const uint16_t kMaxSocs
Maximum number of SOCs.
Definition: soc_id.hpp:35
void release_block()
Releases the memory block IF this process has an ownership.
StatusCode
These statuses represent each step described in SocManager comment.
bool is_error() const
Returns if this return code is not kErrorCodeOk.
Master engine has just started.
The child engine observed some unrecoverable error and has exit.
uint16_t loggers_per_node_
Number of loggers per NUMA node.
Definition: log_options.hpp:80
MasterEngineStatus::StatusCode get_master_status() const