22 #include <sys/resource.h>
45 template <
typename ENGINE_OPTION_PTR,
typename CHILD_PTR>
47 std::vector< CHILD_PTR > children;
48 children.push_back(&option->cache_);
49 children.push_back(&option->debugging_);
50 children.push_back(&option->log_);
51 children.push_back(&option->memory_);
52 children.push_back(&option->proc_);
53 children.push_back(&option->restart_);
54 children.push_back(&option->savepoint_);
55 children.push_back(&option->snapshot_);
56 children.push_back(&option->soc_);
57 children.push_back(&option->storage_);
58 children.push_back(&option->thread_);
59 children.push_back(&option->xct_);
63 return get_children_impl<EngineOptions*, externalize::Externalizable*>(option);
66 return get_children_impl<const EngineOptions*, const externalize::Externalizable*>(option);
73 for (
size_t i = 0; i < mine.size(); ++i) {
74 mine[i]->assign(others[i]);
97 std::ifstream file(
"/proc/meminfo");
98 if (!file.is_open()) {
99 *details_out <<
"[FOEDUS] Failed to open /proc/meminfo. Cannot check available hugepages."
105 uint64_t hugepage_size = 1ULL << 21;
106 uint64_t hugepage_count = 0;
107 while (std::getline(file, line)) {
108 if (line.find(
"Hugepagesize:") != std::string::npos) {
110 if (line.find(
"1048576 kB") != std::string::npos) {
111 hugepage_size = 1ULL << 30;
113 ASSERT_ND(line.find(
"2048 kB") != std::string::npos);
115 }
else if (line.find(
"HugePages_Free:") != std::string::npos) {
118 std::string pages_str = line.substr(std::string(
"HugePages_Free:").length());
119 hugepage_count = std::stoull(pages_str);
123 return hugepage_count * hugepage_size;
128 std::stringstream out_buffer;
129 const uint64_t kMarginRatio = 4;
133 bool has_any_error =
false;
137 <<
"[FOEDUS] WARNING. We strongly discourage rigorous_page_boundary_check_ on valgrind."
138 <<
" If you are sure what you are doing, consider increasing VG_N_SEGMENTS and recompile"
145 uint64_t required_shared_bytes;
146 uint64_t required_local_bytes;
149 uint64_t required_total_bytes = required_shared_bytes + required_local_bytes;
150 uint64_t required_total_safe_bytes = required_total_bytes + required_total_bytes / kMarginRatio;
151 if (available_hugepage_bytes < required_total_safe_bytes) {
152 has_any_error =
true;
155 <<
"[FOEDUS] There are not enough hugepages available."
156 <<
" Based on the values in EngineOptions, the machine should have at least "
157 << required_total_safe_bytes <<
" bytes ("
160 <<
" of hugepages, but there are only " << available_hugepage_bytes <<
" bytes available."
161 <<
" eg: sudo sh -c 'echo xyz > /proc/sys/vm/nr_hugepages' "
169 uint64_t required_shared_safe_bytes
170 = required_shared_bytes + required_shared_bytes / kMarginRatio;
173 std::string error_messages = out_buffer.str();
174 *details_out << error_messages;
179 <<
"**********************************************************" << std::endl
180 <<
"**** ENVIRONMENT PRESCREENING DETECTED SOME ISSUES." << std::endl
181 <<
"**** HOWEVER, suppress_memory_prescreening option was specified." << std::endl
182 <<
"**** FOEDUS will start up." << std::endl
183 <<
"**********************************************************" << std::endl;
187 <<
"**********************************************************" << std::endl
188 <<
"**** ENVIRONMENT PRESCREENING FAILED." << std::endl
189 <<
"**** FOEDUS does not start up because of issues listed above." << std::endl
190 <<
"**********************************************************" << std::endl;
199 uint64_t required_total_safe_bytes,
201 std::ostream* details_out)
const {
203 ::rlimit nofile_limit;
204 ::getrlimit(RLIMIT_NOFILE, &nofile_limit);
206 if (nofile_limit.rlim_cur < kMinNoFile) {
207 *has_any_error =
true;
210 <<
"[FOEDUS] ulimit -n is too small (" << nofile_limit.rlim_cur
211 <<
"). You must have at least " << kMinNoFile << std::endl;
228 ::getrlimit(RLIMIT_NPROC, &proc_limit);
230 if (proc_limit.rlim_cur < kMinProc) {
231 *has_any_error =
true;
234 <<
"[FOEDUS] ulimit -u is too small(" << proc_limit.rlim_cur
235 <<
"). You must have at least " << kMinProc << std::endl;
239 ::rlimit memlock_limit;
240 ::getrlimit(RLIMIT_MEMLOCK, &memlock_limit);
241 if (memlock_limit.rlim_cur * (1ULL << 10) < required_total_safe_bytes) {
242 *has_any_error =
true;
245 <<
"[FOEDUS] ulimit -l is too small(" << memlock_limit.rlim_cur
246 <<
"). You must have at least "
247 << (required_total_safe_bytes >> 10) << std::endl;
256 std::ifstream file(path);
257 if (!file.is_open()) {
258 *details_out <<
"[FOEDUS] Fails to read " << path;
263 std::getline(file, line);
266 return std::stoull(line);
270 uint64_t required_shared_safe_bytes,
272 std::ostream* details_out)
const {
274 if (shmall < required_shared_safe_bytes) {
275 *has_any_error =
true;
278 <<
"[FOEDUS] /proc/sys/kernel/shmall is too small (" << shmall <<
".)"
279 <<
" It must be at least " << required_shared_safe_bytes
280 <<
". We recommend to simply set semi-inifinite value: "
281 <<
" sudo sysctl -w kernel.shmall=1152921504606846720"
282 <<
" and adding an entry 'kernel.shmall = 1152921504606846720' to /etc/sysctl.conf"
283 <<
" then sudo sysctl -p"
288 if (shmmax < required_shared_safe_bytes) {
289 *has_any_error =
true;
292 <<
"[FOEDUS] /proc/sys/kernel/shmmax is too small(" << shmmax <<
")."
293 <<
" It must be at least " << required_shared_safe_bytes
294 <<
". We recommend to simply set semi-inifinite value: "
295 <<
" sudo sysctl -w kernel.shmmax=9223372036854775807"
296 <<
" and adding an entry 'kernel.shmmax = 9223372036854775807' to /etc/sysctl.conf"
297 <<
" then sudo sysctl -p"
302 const uint64_t kMinShmmni = 4096;
303 if (shmmni < kMinShmmni) {
304 *has_any_error =
true;
307 <<
"[FOEDUS] /proc/sys/kernel/shmmni is too small(" << shmmni <<
")."
308 <<
" It must be at least " << kMinShmmni
309 <<
". We recommend to set : "
310 <<
" sudo sysctl -w kernel.shmmni=" << kMinShmmni
311 <<
" and adding an entry 'kernel.shmmni = " << kMinShmmni <<
"' to /etc/sysctl.conf"
312 <<
" then sudo sysctl -p"
319 if (shm_group == 0) {
321 <<
"[FOEDUS] Warning: /proc/sys/vm/hugetlb_shm_group is not set."
322 <<
" In some environment, this is fine: FOEDUS can allocate shared memory backed by hugepages"
323 <<
" without configuring it, but some environment might fail without it"
328 if (map_count <= 65530U) {
330 <<
"[FOEDUS] /proc/sys/vm/max_map_count is only " << map_count
331 <<
" When rigorous_memory_boundary_check or rigorous_page_boundary_check features"
332 <<
" are specified, you must set a large number to it."
333 <<
". We recommend to set : "
334 <<
" sudo sysctl -w vm.max_map_count=2147483647"
335 <<
" and adding an entry 'vm.max_map_count=2147483647' to /etc/sysctl.conf"
336 <<
" then sudo sysctl -p"
342 uint64_t* shared_bytes,
343 uint64_t* local_bytes)
const {
351 uint64_t kMaxXmlSize = 1ULL << 22;
std::vector< externalize::Externalizable * > get_children(EngineOptions *option)
static ErrorStack get_child_element(tinyxml2::XMLElement *parent, const std::string &tag, Externalizable *child, bool optional=false)
child Externalizable version
Represents an object that can be written to and read from files/bytes in XML format.
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
static ErrorStack add_child_element(tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, const Externalizable &child)
child Externalizable version
void prescreen_ulimits(uint64_t required_total_safe_bytes, bool *has_any_error, std::ostream *details_out) const
Subroutine of prescreen to check ulimit values.
Brings error stacktrace information as return value of functions.
EngineOptions()
Constructs option values with default values.
static ErrorStack insert_comment(tinyxml2::XMLElement *element, const std::string &comment)
ErrorStack prescreen(std::ostream *details_out) const
Checks the machine environment and raises as many errors as possible before the engine starts up...
memory::MemoryOptions memory_
ErrorStack save(tinyxml2::XMLElement *element) const override
Writes the content of this object to the given XML element.
0x000E : "GENERAL: Pre-screening of the environment detected" " an issue before start up...
uint32_t log_buffer_kb_
Size in KB of log buffer for each worker thread.
void prescreen_sysctl(uint64_t required_shared_safe_bytes, bool *has_any_error, std::ostream *details_out) const
Subroutine of prescreen to check sysctl values.
static uint64_t calculate_global_memory_size(uint64_t xml_size, const EngineOptions &options)
ErrorStack load(tinyxml2::XMLElement *element) override
Reads the content of this object from the given XML element.
static uint64_t get_available_hugepage_memory(std::ostream *details_out)
A utility method to check how much hugepage memory is currently available.
Set of option values given to the engine at start-up.
static uint64_t calculate_node_memory_size(const EngineOptions &options)
uint16_t group_count_
Number of ThreadGroup in the engine.
static uint64_t read_int_from_proc_fs(const char *path, std::ostream *details_out)
A utility method to read /proc/ value in linux.
std::vector< CHILD_PTR > get_children_impl(ENGINE_OPTION_PTR option)
thread::ThreadOptions thread_
static uint64_t calculate_local_small_memory_size(const EngineOptions &options)
To reduce the overhead of grabbing/releasing pages from pool, we pack this many pointers for each gra...
#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.
const ErrorStack kRetOk
Normal return value for no-error case.
void calculate_required_memory(uint64_t *shared_bytes, uint64_t *local_bytes) const
int64_t int_div_ceil(int64_t dividee, int64_t dividor)
Efficient ceil(dividee/dividor) for integer.
ThreadId get_total_thread_count() const
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.
uint32_t snapshot_cache_size_mb_per_node_
Size of the snapshot cache in MB per each NUMA node.
bool suppress_memory_prescreening_
Whether to tolerate insufficient hugepages etc in the prescreen check.
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
bool rigorous_page_boundary_check_
Whether to use mprotect() for page boundaries to detect bogus memory accesses.
uint32_t local_work_memory_size_mb_
Size of local and temporary work memory one transaction can use during transaction.
EngineOptions & operator=(const EngineOptions &other)
cache::CacheOptions cache_
uint16_t loggers_per_node_
Number of loggers per NUMA node.