libfoedus-core
FOEDUS Core Library
restart_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 "foedus/engine.hpp"
24 #include "foedus/epoch.hpp"
37 
38 namespace foedus {
39 namespace restart {
43  }
45  get_global_memory_anchors()->restart_manager_memory_;
46 
47  // Restart manager works only in master
48  if (engine_->is_master()) {
49  LOG(INFO) << "Initializing RestartManager..";
50 
51  // after all other initializations, we trigger recovery procedure.
53  }
54  return kRetOk;
55 }
56 
58  ErrorStackBatch batch;
61  }
62  if (engine_->is_master()) {
63  LOG(INFO) << "Uninitializing RestartManager..";
64  // restart manager essentially has nothing to release, but because this is the first module
65  // to uninit, we place "stop them first" kind of operations here.
66  engine_->get_snapshot_manager()->get_pimpl()->stop_snapshot_thread(); // stop snapshot thread
67  }
68  return SUMMARIZE_ERROR_BATCH(batch);
69 }
70 
74  LOG(INFO) << "Recovering the database... durable_epoch=" << durable_epoch
75  << ", snapshot_epoch=" << snapshot_epoch;
76 
77  if (durable_epoch.value() == Epoch::kEpochInitialDurable) {
78  if (!snapshot_epoch.is_valid()) {
79  LOG(INFO) << "The database is in initial state. Nothing to recover.";
80  return kRetOk;
81  } else {
82  // this means durable_epoch wraps around. nothing wrong, but worth logging.
83  LOG(INFO) << "Interesting. durable_epoch is initial value, but we have snapshot."
84  << " This means epoch wrapped around!";
85  }
86  }
87 
88  if (durable_epoch == snapshot_epoch) {
89  LOG(INFO) << "The snapshot is up-to-date. No need to recover.";
90  return kRetOk;
91  }
92 
93  LOG(INFO) << "There are logs that are durable but not yet snapshotted.";
94  CHECK_ERROR(redo_meta_logs(durable_epoch, snapshot_epoch));
95  LOG(INFO) << "Launching snapshot..";
97  snapshot::Snapshot the_snapshot;
98  CHECK_ERROR(snapshot_pimpl->handle_snapshot_triggered(&the_snapshot));
99  LOG(INFO) << "Finished initial snapshot during start-up.";
100 
101  // This fixes Bug #127.
102  // Right after the recovery-snapshot, any non-null volatile root pages becomes stale.
103  // we need to replace them with the new snapshot pages.
105 
106  LOG(INFO) << "Now we can start processing transaction";
107  return kRetOk;
108 }
109 
111  ASSERT_ND(!snapshot_epoch.is_valid() || snapshot_epoch < durable_epoch);
112  LOG(INFO) << "Redoing metadata operations from " << snapshot_epoch << " to " << durable_epoch;
113 
114  // Because metadata log is tiny, we do nothing complex here. Just read them all.
117  WRAP_ERROR_CODE(file.open(true, false, false, false));
118  uint64_t oldest_offset;
119  uint64_t durable_offset;
120  engine_->get_savepoint_manager()->get_meta_logger_offsets(&oldest_offset, &durable_offset);
121  ASSERT_ND(oldest_offset % (1 << 12) == 0);
122  ASSERT_ND(durable_offset % (1 << 12) == 0);
123  ASSERT_ND(oldest_offset <= durable_offset);
124  ASSERT_ND(fs::file_size(path) >= durable_offset);
125  uint32_t read_size = durable_offset - oldest_offset;
126 
127  LOG(INFO) << "Will read " << read_size << " bytes from meta log";
128 
129  // Assuming it's tiny, just read it in one shot.
130  memory::AlignedMemory buffer;
131  buffer.alloc(read_size, 1U << 12, memory::AlignedMemory::kNumaAllocOnnode, 0);
132 
133  WRAP_ERROR_CODE(file.seek(oldest_offset, fs::DirectIoFile::kDirectIoSeekSet));
134  WRAP_ERROR_CODE(file.read_raw(read_size, buffer.get_block()));
135 
136  char* buf = reinterpret_cast<char*>(buffer.get_block());
137  uint32_t cur = 0;
138  uint32_t processed = 0;
140  while (cur < read_size) {
141  log::BaseLogType* entry = reinterpret_cast<log::BaseLogType*>(buf + cur);
143  const uint32_t log_length = entry->header_.log_length_;
144  cur += log_length;
145  log::LogCode type = entry->header_.get_type();
147  if (type == log::kLogCodeFiller || type == log::kLogCodeEpochMarker) {
148  continue;
149  }
150  Epoch epoch = entry->header_.xct_id_.get_epoch();
151  if (epoch > durable_epoch) {
152  LOG(FATAL) << "WTF. This should have been checked in meta logger's startup??";
153  }
154  if (snapshot_epoch.is_valid() && epoch <= snapshot_epoch) {
155  continue;
156  }
157  switch (type) {
159  LOG(INFO) << "Redoing DROP STORAGE-" << entry->header_.storage_id_;
161  ++processed;
162  break;
167  reinterpret_cast<storage::CreateLogType*>(entry)->apply_storage(
168  engine_,
169  entry->header_.storage_id_);
170  ++processed;
171  break;
172  default:
173  LOG(ERROR) << "Unexpected log type in metadata log:" << entry->header_;
174  }
175  }
176 
177  file.close();
178  LOG(INFO) << "Redone " << processed << " metadata operations";
179  return kRetOk;
180 }
181 
182 } // namespace restart
183 } // namespace foedus
LogCodeKind get_kind() const __attribute__((always_inline))
Convenience method to get LogCodeKind.
LogCode
A unique identifier of all log types.
Definition: log_type.hpp:87
numa_alloc_onnode() and numa_free().
void emprace_back(ErrorStack &&error_stack)
If the given ErrorStack is an error, this method adds it to the end of this batch.
SnapshotManagerPimpl * get_pimpl()
Do not use this unless you know what you are doing.
storage::StorageManager * get_storage_manager() const
See Storage Manager.
Definition: engine.cpp:60
#define ERROR_STACK(e)
Instantiates ErrorStack with the given foedus::error_code, creating an error stack with the current f...
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
ErrorStack handle_snapshot_triggered(Snapshot *new_snapshot)
handle_snapshot() calls this when it should start snapshotting.
bool is_initialized() const override
Returns whether the object has been already initialized or not.
Definition: xct_manager.cpp:31
0x0005 : "GENERAL: A dependent module is not initialized yet. This implies a wrong initialization ord...
Definition: error_code.hpp:109
record targetted logs
Definition: log_type.hpp:103
Brings error stacktrace information as return value of functions.
Definition: error_stack.hpp:81
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.
Declares common log types used in all packages.
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
savepoint::SavepointManager * get_savepoint_manager() const
See Savepoint Manager.
Definition: engine.cpp:53
RestartManagerControlBlock * control_block_
Base class for log type.
0x1027 : foedus::storage::hash::HashCreateLogType .
Definition: log_type.hpp:120
Batches zero or more ErrorStack objects to represent in one ErrorStack.
Analogue of boost::filesystem::path.
Definition: path.hpp:37
Declares common log types for all (or at least multiple) storage types.
log::LogManager * get_log_manager() const
See Log Manager.
Definition: engine.cpp:49
0x1021 : foedus::storage::array::ArrayCreateLogType .
Definition: log_type.hpp:114
Epoch get_epoch() const __attribute__((always_inline))
Definition: xct_id.hpp:964
xct::XctId xct_id_
Epoch and in-epoch ordinal of this log.
Represents one snapshot that converts all logs from base epoch to valid_until epoch into snapshot fil...
Definition: snapshot.hpp:37
void * get_block() const
Returns the memory block.
uint16_t log_length_
Byte size of this log entry including this header itself and everything.
uint64_t file_size(const Path &p)
Returns size of the file.
Definition: filesystem.cpp:120
ErrorStack recover()
Recover the state of database from recent snapshot files and transaction logs.
#define SUMMARIZE_ERROR_BATCH(x)
This macro calls ErrorStackBatch::summarize() with automatically provided parameters.
xct::XctManager * get_xct_manager() const
See Transaction Manager.
Definition: engine.cpp:61
std::string construct_meta_log_path() const
metadata log file is placed in node-0/logger-0 folder
Definition: log_options.cpp:51
bool is_valid() const
Definition: epoch.hpp:96
Epoch get_durable_global_epoch() const
Returns the durable epoch of the entire engine.
Definition: log_manager.cpp:36
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
Represents an I/O stream on one file without filesystem caching.
Represents one memory block aligned to actual OS/hardware pages.
foedus::fs::DeviceEmulationOptions emulation_
Settings to emulate slower logging device.
const ErrorStack kRetOk
Normal return value for no-error case.
Storage Manager class that provides API to create/open/close/drop key-value stores.
0 is reserved as a non-existing log type.
Definition: log_type.hpp:89
soc::SocManager * get_soc_manager() const
See SOC and IPC.
Definition: engine.cpp:59
void stop_snapshot_thread()
This is a hidden API called at the beginning of engine shutdown (namely restart manager).
storage::StorageId storage_id_
The storage this loggable operation mainly affects.
0x3001 : foedus::log::FillerLogType .
Definition: log_type.hpp:111
LogCode get_type() const __attribute__((always_inline))
Convenience method to cast into LogCode.
void get_meta_logger_offsets(uint64_t *oldest_offset, uint64_t *durable_offset) const
Returns the saved information of metadata logger in lateset savepoint.
ErrorStack redo_meta_logs(Epoch durable_epoch, Epoch snapshot_epoch)
Redo metadata operation (create/drop storage) since the latest snapshot.
snapshot::SnapshotManager * get_snapshot_manager() const
See Snapshot Manager.
Definition: engine.cpp:56
As there is no transaction in ep-1, initial durable_epoch is 1.
Definition: epoch.hpp:70
void drop_storage_apply(StorageId id)
This is called while restart to apply DROP STORAGE logs.
Base type for CREATE STORAGE operation.
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
#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
Epoch get_snapshot_epoch() const
Returns the most recently snapshot-ed epoch, all logs upto this epoch is safe to delete.
#define WRAP_ERROR_CODE(x)
Same as CHECK_ERROR(x) except it receives only an error code, thus more efficient.
0x1031 : foedus::storage::masstree::MasstreeCreateLogType .
Definition: log_type.hpp:125
0x1025 : foedus::storage::sequential::SequentialCreateLogType .
Definition: log_type.hpp:118
The offset is set to offset bytes.
0x1011 : foedus::storage::DropLogType .
Definition: log_type.hpp:113
EpochInteger value() const
Returns the raw integer representation.
Definition: epoch.hpp:102
SharedMemoryRepo * get_shared_memory_repo()
Returns the shared memories maintained across SOCs.
Definition: soc_manager.cpp:38
0x3002 : foedus::log::EpochMarkerLogType .
Definition: log_type.hpp:112