libfoedus-core
FOEDUS Core Library
storage_manager_pimpl.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 <cstring>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 
27 #include "foedus/engine.hpp"
61 
62 namespace foedus {
63 namespace storage {
64 
67 }
68 
70  LOG(INFO) << "Initializing StorageManager..";
74  }
75 
76  // attach shared memories
80  storages_ = anchors->storage_memories_;
82 
83  if (engine_->is_master()) {
84  // initialize the shared memory. only on master engine
87 
88  // Then, initialize storages with latest snapshot
90  }
91  return kRetOk;
92 }
93 
96  LOG(INFO) << "Initializing list of storages with latest snapshot file...";
98  if (snapshot_id == snapshot::kNullSnapshotId) {
99  LOG(INFO) << "There was no previous snapshot. start from empty storages";
100  return kRetOk;
101  }
102 
104  CHECK_ERROR(engine_->get_snapshot_manager()->read_snapshot_metadata(snapshot_id, &metadata));
105  LOG(INFO) << "Latest snapshot contains " << metadata.largest_storage_id_ << " storages";
107 
108  debugging::StopWatch stop_watch;
109  uint32_t active_storages = 0;
110  for (uint32_t id = 1; id <= control_block_->largest_storage_id_; ++id) {
111  StorageControlBlock* block = storages_ + id;
112  const StorageControlBlock& snapshot_block = metadata.storage_control_blocks_[id];
113  if (snapshot_block.status_ != kExists) {
114  VLOG(0) << "Storage-" << id << " is a dropped storage.";
115  block->status_ = kNotExists;
116  } else {
117  VLOG(0) << "Storage-" << id << " exists in the snapshot.";
118  ASSERT_ND(snapshot_block.meta_.id_ == id);
119  ASSERT_ND(!snapshot_block.meta_.name_.empty());
120  ASSERT_ND(!exists(snapshot_block.meta_.name_));
121  block->initialize();
124 
125  block->meta_.type_ = snapshot_block.meta_.type_;
126  switch (snapshot_block.meta_.type_) {
127  case kArrayStorage:
128  CHECK_ERROR(array::ArrayStorage(engine_, block).load(snapshot_block));
129  break;
130  case kHashStorage:
131  CHECK_ERROR(hash::HashStorage(engine_, block).load(snapshot_block));
132  break;
133  case kMasstreeStorage:
134  CHECK_ERROR(masstree::MasstreeStorage(engine_, block).load(snapshot_block));
135  break;
136  case kSequentialStorage:
137  CHECK_ERROR(sequential::SequentialStorage(engine_, block).load(snapshot_block));
138  break;
139  default:
141  }
142 
143  ASSERT_ND(get_storage(id)->exists());
144 
145  ++active_storages;
146  }
147  }
148  stop_watch.stop();
149  LOG(INFO) << "Found " << active_storages
150  << " active storages in " << stop_watch.elapsed_ms() << " milliseconds";
151  return kRetOk;
152 }
153 
155  return pimpl_->reinitialize_for_recovered_snapshot();
156 }
158  LOG(INFO) << "Replacing existing, stale volatile root pages with the new root snapshot pages..";
159  auto* memory_manager = engine_->get_memory_manager();
160  const auto& resolver = memory_manager->get_global_volatile_page_resolver();
161  debugging::StopWatch stop_watch;
162  uint32_t refreshed_storages = 0;
163 
165  CHECK_ERROR(fileset.initialize());
167  for (uint32_t id = 1; id <= control_block_->largest_storage_id_; ++id) {
168  StorageControlBlock* block = storages_ + id;
169  const SnapshotPagePointer snapshot_page_id = block->root_page_pointer_.snapshot_pointer_;
170  const VolatilePagePointer volatile_page_id = block->root_page_pointer_.volatile_pointer_;
171  if (!block->exists()) {
172  continue;
173  } else if (snapshot_page_id == 0) {
174  continue;
175  } else if (volatile_page_id.is_null()) {
176  // some storage type allows null volatile root pages. In that case,
177  // we don't have to do anything at this point. When the initial non-read-ony request
178  // is made, the root volatile page will be automatically created.
179  continue;
180  }
181 
182  LOG(INFO) << "Re-initializing root of storage-" << id << " from the recovered snapshot."
183  << "Volatile page ID=" << volatile_page_id << ", Snapshot page ID=" << snapshot_page_id;
184  Page* volatile_page = resolver.resolve_offset(volatile_page_id);
185  ASSERT_ND(!volatile_page->get_header().snapshot_);
186  ASSERT_ND(volatile_page->get_header().storage_id_ == id);
187  ASSERT_ND(volatile_page->get_volatile_page_id() == volatile_page_id);
188 
189  // Here, we assume that the initially-allocated volatile root page does NOT have
190  // any child volatile page (it shouldn't!). Otherwise, the following overwrite
191  // will cause leaked volatile pages.
192  WRAP_ERROR_CODE(fileset.read_page(snapshot_page_id, volatile_page));
193  ASSERT_ND(volatile_page->get_header().snapshot_);
194  ASSERT_ND(volatile_page->get_header().storage_id_ == id);
195  ASSERT_ND(volatile_page->get_snapshot_page_id() == snapshot_page_id);
196  volatile_page->get_header().snapshot_ = false;
197  volatile_page->get_header().page_id_ = volatile_page_id.word;
198  ++refreshed_storages;
199  }
200 
201  CHECK_ERROR(fileset.uninitialize());
202  stop_watch.stop();
203  LOG(INFO) << "Refreshed " << refreshed_storages
204  << " storages with the recovered snapshot in " << stop_watch.elapsed_ms() << " milliseconds";
205  return kRetOk;
206 }
207 
209  LOG(INFO) << "Uninitializing StorageManager..";
210  ErrorStackBatch batch;
214  }
215  if (engine_->is_master()) {
216  // drop all existing storages just for releasing memories.
217  // this is not a real drop, so we just invoke drop_apply
218  uint32_t dropped = 0;
219  for (storage::StorageId i = 1; i <= control_block_->largest_storage_id_; ++i) {
220  if (storages_[i].exists()) {
221  // TASK(Hideaki) we should have a separate method for this once we add "marked-for-death"
222  // feature.
224  ++dropped;
225  ASSERT_ND(!storages_[i].exists());
226  }
227  }
228  LOG(INFO) << "Uninitialized " << dropped << " storages";
229 
231  }
232  return SUMMARIZE_ERROR_BATCH(batch);
233 }
234 
236  soc::SharedMutexScope guard(&control_block_->mod_lock_); // implies fence too
238  LOG(INFO) << "Incremented largest_storage_id_: " << control_block_->largest_storage_id_;
240 }
241 
244  // TASK(Hideaki) so far sequential search
245  for (uint32_t i = 0; i <= control_block_->largest_storage_id_; ++i) {
246  if (storages_[i].meta_.name_ == name) {
247  return &storages_[i];
248  }
249  }
250  LOG(WARNING) << "Requested storage name '" << name << "' was not found";
251  return &storages_[0]; // storage ID 0 is always not-initialized
252 }
255  // TASK(Hideaki) so far sequential search
256  for (uint32_t i = 0; i <= control_block_->largest_storage_id_; ++i) {
257  if (storages_[i].meta_.name_ == name) {
258  return true;
259  }
260  }
261  return false;
262 }
263 
265  StorageControlBlock* block = storages_ + id;
266  if (!block->exists()) {
267  LOG(ERROR) << "This storage ID does not exist or has been already dropped: " << id;
269  }
270 
271  StorageName name = block->meta_.name_;
272  LOG(INFO) << "Dropping storage " << id << "(" << name << ")";
273  StorageType type = block->meta_.type_;
274  if (type == kArrayStorage) {
275  CHECK_ERROR(array::ArrayStorage(engine_, block).drop());
276  } else if (type == kHashStorage) {
277  CHECK_ERROR(hash::HashStorage(engine_, block).drop());
278  } else if (type == kMasstreeStorage) {
280  } else if (type == kSequentialStorage) {
282  } else {
283  LOG(FATAL) << "WTF:" << type;
284  }
285 
286  char log_buffer[1 << 12];
287  std::memset(log_buffer, 0, sizeof(log_buffer));
288  DropLogType* drop_log = reinterpret_cast<DropLogType*>(log_buffer);
289  drop_log->populate(id);
290  engine_->get_log_manager()->get_meta_buffer()->commit(drop_log, commit_epoch);
291 
292  ASSERT_ND(commit_epoch->is_valid());
293  block->status_ = kMarkedForDeath;
294  ASSERT_ND(!block->exists());
295  block->uninitialize();
296  LOG(INFO) << "Dropped storage " << id << "(" << name << ")";
297  return kRetOk;
298 }
299 
301  StorageControlBlock* block = storages_ + id;
302  ASSERT_ND(block->exists());
303  StorageType type = block->meta_.type_;
304  if (type == kArrayStorage) {
305  COERCE_ERROR(array::ArrayStorage(engine_, block).drop());
306  } else if (type == kHashStorage) {
307  COERCE_ERROR(hash::HashStorage(engine_, block).drop());
308  } else if (type == kMasstreeStorage) {
310  } else if (type == kSequentialStorage) {
312  } else {
313  LOG(FATAL) << "WTF:" << type;
314  }
315  block->status_ = kMarkedForDeath;
316  ASSERT_ND(!block->exists());
317  block->uninitialize();
318 }
319 
320 template <typename STORAGE>
322  typedef typename STORAGE::ThisMetadata TheMetadata;
323  typedef typename STORAGE::ThisCreateLogType TheLogType;
324 
325  StorageId id = meta->id_;
326  StorageControlBlock* block = storages_ + id;
327  STORAGE storage(engine_, block);
328  const TheMetadata* casted_meta = reinterpret_cast< const TheMetadata *>(meta);
329  ASSERT_ND(!block->exists());
330  CHECK_ERROR(storage.create(*casted_meta));
331  ASSERT_ND(block->exists());
332 
333  if (commit_epoch) {
334  // if commit_epoch is null, it means "apply-only" mode in restart. do not log then
335  char log_buffer[sizeof(TheLogType)];
336  std::memset(log_buffer, 0, sizeof(log_buffer));
337  TheLogType* create_log = reinterpret_cast<TheLogType*>(log_buffer);
338  create_log->header_.storage_id_ = id;
339  create_log->header_.log_type_code_ = log::get_log_code<TheLogType>();
340  create_log->header_.log_length_ = sizeof(TheLogType);
341  create_log->metadata_ = *casted_meta;
342  ASSERT_ND(create_log->header_.storage_id_ == id);
343  ASSERT_ND(create_log->metadata_.id_ == id);
344  ASSERT_ND(create_log->metadata_.type_ == meta->type_);
345  ASSERT_ND(create_log->metadata_.name_ == meta->name_);
346 
347  engine_->get_log_manager()->get_meta_buffer()->commit(create_log, commit_epoch);
348  }
349  return kRetOk;
350 }
351 
353  *commit_epoch = INVALID_EPOCH;
355  if (id >= get_max_storages()) {
357  }
358  if (metadata->name_.empty()) {
360  }
361  metadata->id_ = id;
362 
363  const StorageName& name = metadata->name_;
364  if (exists(name)) {
365  LOG(ERROR) << "This storage name already exists: " << name;
367  }
368 
369  get_storage(id)->initialize();
370  ASSERT_ND(!get_storage(id)->exists());
371  storages_[id].meta_.type_ = metadata->type_;
372 
373  metadata->name_.zero_fill_remaining(); // make valgrind overload happy.
374  ErrorStack result;
375  if (metadata->type_ == kArrayStorage) {
376  result = create_storage_and_log< array::ArrayStorage >(metadata, commit_epoch);
377  } else if (metadata->type_ == kHashStorage) {
378  result = create_storage_and_log< hash::HashStorage >(metadata, commit_epoch);
379  } else if (metadata->type_ == kMasstreeStorage) {
380  result = create_storage_and_log< masstree::MasstreeStorage >(metadata, commit_epoch);
381  } else if (metadata->type_ == kSequentialStorage) {
382  result = create_storage_and_log< sequential::SequentialStorage >(metadata, commit_epoch);
383  } else {
384  LOG(FATAL) << "WTF:" << metadata->type_;
385  }
386  CHECK_ERROR(result);
387 
388  ASSERT_ND(commit_epoch->is_valid());
389  ASSERT_ND(get_storage(id)->exists());
390  return kRetOk;
391 }
392 
394  // this method is called only while restart, so no race.
395  ASSERT_ND(metadata.id_ > 0);
396  ASSERT_ND(!metadata.name_.empty());
397  StorageId id = metadata.id_;
400  }
401 
402  ASSERT_ND(!exists(metadata.name_));
403 
404  get_storage(id)->initialize();
405  ASSERT_ND(!get_storage(id)->exists());
406  storages_[id].meta_.type_ = metadata.type_;
407  ErrorStack result;
408  if (metadata.type_ == kArrayStorage) {
409  result = create_storage_and_log< array::ArrayStorage >(&metadata, nullptr);
410  } else if (metadata.type_ == kHashStorage) {
411  result = create_storage_and_log< hash::HashStorage >(&metadata, nullptr);
412  } else if (metadata.type_ == kMasstreeStorage) {
413  result = create_storage_and_log< masstree::MasstreeStorage >(&metadata, nullptr);
414  } else if (metadata.type_ == kSequentialStorage) {
415  result = create_storage_and_log< sequential::SequentialStorage >(&metadata, nullptr);
416  } else {
417  LOG(FATAL) << "WTF:" << metadata.type_;
418  }
419  if (result.is_error()) {
420  LOG(FATAL) << "create_storage_apply() failed. " << result
421  << " Failed to restart the engine";
422  }
423 
424  ASSERT_ND(get_storage(id)->exists());
425 }
426 
428  StorageControlBlock* block = storages_ + storage_id;
429  ASSERT_ND(block->exists());
430  StorageType type = block->meta_.type_;
431  if (type == kMasstreeStorage) {
433  } else if (type == kHashStorage) {
435  } else if (type == kArrayStorage) {
437  } else {
438  // Seq storage doesn't need it.
439  LOG(WARNING) << "This storage type doesn't need HCC counter reset. type=" << type;
440  }
441  return kRetOk;
442 }
443 
444 // define here to allow inline
446  StorageId storage_id,
447  xct::RwLockableXctId* old_address,
448  xct::WriteXctAccess* write_set) {
449  return pimpl_->track_moved_record(storage_id, old_address, write_set);
450 }
451 
453  StorageId storage_id,
454  xct::RwLockableXctId* old_address,
455  xct::WriteXctAccess* write_set) {
456  // so far Masstree and Hash have tracking
457  StorageControlBlock* block = storages_ + storage_id;
458  ASSERT_ND(block->exists());
459  StorageType type = block->meta_.type_;
460  if (type == kMasstreeStorage) {
461  return masstree::MasstreeStorage(engine_, block).track_moved_record(old_address, write_set);
462  } else if (type == kHashStorage) {
463  return hash::HashStorage(engine_, block).track_moved_record(old_address, write_set);
464  } else {
465  LOG(ERROR) << "Unexpected storage type for a moved-record. Bug? type=" << type;
467  }
468 }
469 
471  snapshot::SnapshotMetadata *metadata) {
472  debugging::StopWatch stop_watch;
474 
475  // not just the metadata, just copy the whole control block.
476  // this is a single memcpy, which should be much more efficient.
477  uint64_t memory_size
478  = static_cast<uint64_t>(metadata->largest_storage_id_ + 1)
481  memory_size,
482  1 << 12,
484  0);
485  metadata->storage_control_blocks_ = reinterpret_cast<storage::StorageControlBlock*>(
487  std::memcpy(metadata->storage_control_blocks_, storages_, memory_size);
488 
489  stop_watch.stop();
490  LOG(INFO) << "Duplicated metadata of " << metadata->largest_storage_id_
491  << " storages in " << stop_watch.elapsed_ms() << " milliseconds";
492  return kRetOk;
493 }
494 
495 } // namespace storage
496 } // namespace foedus
Log type of DROP STORAGE operation.
StorageControlBlock * storages_
Storage instances (pimpl objects) are allocated in this shared memory.
Represents the data in one snapshot metadata file.
storage::StorageControlBlock * storage_control_blocks_
control block of all storages.
0x0803 : "STORAGE: This Storage Name already exists" .
Definition: error_code.hpp:169
MetaLogBuffer * get_meta_buffer()
Definition: log_manager.cpp:61
void populate(StorageId storage_id)
Metadata meta_
common part of the metadata.
Definition: storage.hpp:84
numa_alloc_onnode() and numa_free().
ErrorStack drop_storage(StorageId id, Epoch *commit_epoch)
snapshot::SnapshotId get_latest_snapshot_id() const
The storage has been marked for drop and can't be used.
Definition: storage_id.hpp:164
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.
Automatically calls if uninitialize() wasn't called when it gets out of scope, and just complains whe...
Declares all log types used in this storage type.
#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
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
Represents a record of write-access during a transaction.
Definition: xct_access.hpp:168
Represents a key-value store based on a dense and regular array.
GlobalMemoryAnchors * get_global_memory_anchors()
ErrorStack reinitialize_for_recovered_snapshot()
Special method called only from recovery manager.
StorageId storage_id_
ID of the storage this page belongs to.
Definition: page.hpp:196
0x0823 : "STORAGE: This storage does not exist or has been already dropped" .
Definition: error_code.hpp:186
Declares all log types used in this storage type.
const GlobalVolatilePageResolver & get_global_volatile_page_resolver() const
Returns the page resolver to convert volatile page ID to page pointer.
double elapsed_ms() const
Definition: stop_watch.hpp:48
bool is_initialized() const override
Returns whether the object has been already initialized or not.
Definition: log_manager.cpp:32
Result of track_moved_record().
Definition: xct_id.hpp:1180
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
StorageManagerControlBlock * control_block_
ErrorStack uninitialize() override final
Typical implementation of Initializable::uninitialize() that provides uninitialize-once semantics...
StorageId largest_storage_id_
The largest StorageId we so far observed.
Brings error stacktrace information as return value of functions.
Definition: error_stack.hpp:81
xct::TrackMovedRecordResult track_moved_record(StorageId storage_id, xct::RwLockableXctId *old_address, xct::WriteXctAccess *write)
DualPagePointer root_page_pointer_
Points to the root page (or something equivalent).
Definition: storage.hpp:82
Represents a time epoch.
Definition: epoch.hpp:61
void alloc(uint64_t size, uint64_t alignment, AllocType alloc_type, int numa_node) noexcept
Allocate a memory, releasing the current memory if exists.
ErrorStack create_storage_and_log(const Metadata *meta, Epoch *commit_epoch)
The storage has been created and ready for use.
Definition: storage_id.hpp:158
Holds a set of read-only file objects for snapshot files.
ErrorStack read_snapshot_metadata(SnapshotId snapshot_id, SnapshotMetadata *out)
Read the snapshot metadata file that contains storages as of the snapshot.
const EngineOptions & get_options() const
Definition: engine.cpp:39
uint32_t max_storages_
Maximum number of storages in this database.
#define COERCE_ERROR(x)
This macro calls x and aborts if encounters an error.
bool is_master() const
Returns if this engine object is a master instance.
Definition: engine.cpp:68
xct::TrackMovedRecordResult track_moved_record(xct::RwLockableXctId *old_address, xct::WriteXctAccess *write_set)
Resolves a "moved" record.
savepoint::SavepointManager * get_savepoint_manager() const
See Savepoint Manager.
Definition: engine.cpp:53
storage::StorageControlBlock * storage_memories_
Status of each storage instance is stored in this shared memory.
The MCS reader-writer lock variant of LockableXctId.
Definition: xct_id.hpp:1132
Metadata of one storage.
Definition: metadata.hpp:58
Represents an append/scan-only store.
storage::StorageManagerControlBlock * storage_manager_memory_
Tiny memory for storage manager.
Batches zero or more ErrorStack objects to represent in one ErrorStack.
VolatilePagePointer volatile_pointer_
Definition: storage_id.hpp:308
xct::TrackMovedRecordResult track_moved_record(xct::RwLockableXctId *old_address, xct::WriteXctAccess *write_set)
Resolves a "moved" record.
VolatilePagePointer get_volatile_page_id() const
Definition: page.hpp:339
bool is_initialized() const override
Returns whether the object has been already initialized or not.
Definition: thread_pool.cpp:37
Declares common log types for all (or at least multiple) storage types.
StorageControlBlock * get_storage(StorageId id)
log::LogManager * get_log_manager() const
See Log Manager.
Definition: engine.cpp:49
void create_storage_apply(const Metadata &metadata)
storage::StorageOptions storage_
Declares all log types used in this storage type.
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...
bool empty() const noexcept
Test if string is empty.
uint64_t stop()
Take another current time tick.
Definition: stop_watch.cpp:35
SnapshotPagePointer snapshot_pointer_
Definition: storage_id.hpp:307
memory::AlignedMemory storage_control_blocks_memory_
Memory backing storage_control_blocks_.
StorageName name_
the unique name of this storage.
Definition: metadata.hpp:107
Auto-lock scope object for SharedMutex.
soc::SharedMutex mod_lock_
In case there are multiple threads that add/delete/expand storages, those threads take this lock...
Just a marker to denote that the memory region represents a data page.
Definition: page.hpp:334
0x0824 : "STORAGE: Storage name is empty" .
Definition: error_code.hpp:187
0x0822 : "STORAGE: Reached maximum number of storages. To register more storages, adjust StorageOptio...
Definition: error_code.hpp:185
void * get_block() const
Returns the memory block.
uint16_t SnapshotId
Unique ID of Snapshot.
Definition: snapshot_id.hpp:43
Represents a key-value store based on a dense and regular hash.
Just a set of pointers within global_memory_ for ease of use.
const SnapshotId kNullSnapshotId
Definition: snapshot_id.hpp:45
StorageType
Type of the storage, such as hash.
Definition: storage_id.hpp:122
#define SUMMARIZE_ERROR_BATCH(x)
This macro calls ErrorStackBatch::summarize() with automatically provided parameters.
StorageType type_
type of the storage.
Definition: metadata.hpp:105
ErrorStack hcc_reset_all_temperature_stat(StorageId storage_id)
Resets all volatile pages' temperature stat to be zero in the specified storage.
storage::StorageId * storage_name_sort_
This shared memory stores the ID of storages sorted by their names.
bool is_valid() const
Definition: epoch.hpp:96
Declares all log types used in this storage type.
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const Epoch INVALID_EPOCH
A constant epoch object that represents an invalid epoch.
Definition: epoch.hpp:204
void commit(BaseLogType *metalog, Epoch *commit_epoch)
Synchronously writes out the given log to metadata log file.
const ErrorStack kRetOk
Normal return value for no-error case.
soc::SocManager * get_soc_manager() const
See SOC and IPC.
Definition: engine.cpp:59
Initial state, which means the storage has not been created yet.
Definition: storage_id.hpp:156
xct::TrackMovedRecordResult track_moved_record(StorageId storage_id, xct::RwLockableXctId *old_address, xct::WriteXctAccess *write_set)
Resolves a "moved" record.
Atomic fence methods and load/store with fences that work for both C++11/non-C++11 code...
0x0807 : "STORAGE: This metadata type is not yet supported" .
Definition: error_code.hpp:173
PageHeader & get_header()
At least the basic header exists in all pages.
Definition: page.hpp:336
snapshot::SnapshotManager * get_snapshot_manager() const
See Snapshot Manager.
Definition: engine.cpp:56
ErrorStack reinitialize_for_recovered_snapshot()
Special method called only from recovery manager.
0x0006 : "GENERAL: A dependent module is already uninitialized. This implies a wrong uninitialization...
Definition: error_code.hpp:110
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
A high-resolution stop watch.
Definition: stop_watch.hpp:30
StorageStatus status_
Status of the storage.
Definition: storage.hpp:80
#define WRAP_ERROR_CODE(x)
Same as CHECK_ERROR(x) except it receives only an error code, thus more efficient.
A base layout of shared data for all storage types.
Definition: storage.hpp:53
StorageId id_
the unique ID of this storage.
Definition: metadata.hpp:103
memory::EngineMemory * get_memory_manager() const
See Memory Manager.
Definition: engine.cpp:50
thread::ThreadPool * get_thread_pool() const
See Thread and Thread-Group.
Definition: engine.cpp:52
storage::StorageId largest_storage_id_
The largest StorageId we so far observed.
void zero_fill_remaining() const noexcept
Sets zeros to unused data_ region.
bool is_error() const
Returns if this return code is not kErrorCodeOk.
uint64_t page_id_
Page ID of this page.
Definition: page.hpp:191
SharedMemoryRepo * get_shared_memory_repo()
Returns the shared memories maintained across SOCs.
Definition: soc_manager.cpp:38
void memory_fence_acq_rel()
Equivalent to std::atomic_thread_fence(std::memory_order_acq_rel).
SnapshotPagePointer root_snapshot_page_id_
Pointer to a snapshotted page this storage is rooted at.
Definition: metadata.hpp:112
ErrorStack clone_all_storage_metadata(snapshot::SnapshotMetadata *metadata)
ErrorStack create_storage(Metadata *metadata, Epoch *commit_epoch)