mirror of
https://github.com/MariaDB/server.git
synced 2025-11-16 20:23:18 +03:00
322 lines
8.3 KiB
C++
322 lines
8.3 KiB
C++
/* Copyright (C) 2003 MySQL AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
#include <ndb_global.h>
|
|
|
|
#include <ndb_version.h>
|
|
#include "Configuration.hpp"
|
|
#include <TransporterRegistry.hpp>
|
|
|
|
#include "vm/SimBlockList.hpp"
|
|
#include "ThreadConfig.hpp"
|
|
#include <SignalLoggerManager.hpp>
|
|
#include <NdbOut.hpp>
|
|
#include <NdbMain.h>
|
|
#include <NdbDaemon.h>
|
|
#include <NdbConfig.h>
|
|
#include <WatchDog.hpp>
|
|
|
|
#include <LogLevel.hpp>
|
|
#include <EventLogger.hpp>
|
|
#include <NodeState.hpp>
|
|
|
|
#if defined NDB_SOLARIS // ok
|
|
#include <sys/processor.h> // For system informatio
|
|
#endif
|
|
|
|
#if !defined NDB_SOFTOSE && !defined NDB_OSE
|
|
#include <signal.h> // For process signals
|
|
#endif
|
|
|
|
extern EventLogger g_eventLogger;
|
|
|
|
void catchsigs(bool ignore); // for process signal handling
|
|
extern "C" void handler(int signo); // for process signal handling
|
|
|
|
// Shows system information
|
|
void systemInfo(const Configuration & conf,
|
|
const LogLevel & ll);
|
|
|
|
const char programName[] = "NDB Kernel";
|
|
|
|
NDB_MAIN(ndb_kernel){
|
|
|
|
// Print to stdout/console
|
|
g_eventLogger.createConsoleHandler();
|
|
g_eventLogger.setCategory("NDB");
|
|
g_eventLogger.enable(Logger::LL_INFO, Logger::LL_ALERT); // Log INFO to ALERT
|
|
|
|
globalEmulatorData.create();
|
|
|
|
// Parse command line options
|
|
Configuration* theConfig = globalEmulatorData.theConfiguration;
|
|
if(!theConfig->init(argc, argv)){
|
|
return 0;
|
|
}
|
|
|
|
{ // Do configuration
|
|
theConfig->setupConfiguration();
|
|
}
|
|
|
|
// Get NDB_HOME path
|
|
char homePath[255];
|
|
NdbConfig_HomePath(homePath, 255);
|
|
|
|
if (theConfig->getDaemonMode()) {
|
|
// Become a daemon
|
|
char lockfile[255], logfile[255];
|
|
snprintf(lockfile, 255, "%snode%d.pid", homePath, globalData.ownId);
|
|
snprintf(logfile, 255, "%snode%d.out", homePath, globalData.ownId);
|
|
if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
|
|
ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
for(pid_t child = fork(); child != 0; child = fork()){
|
|
/**
|
|
* Parent
|
|
*/
|
|
catchsigs(true);
|
|
|
|
int status = 0;
|
|
while(waitpid(child, &status, 0) != child);
|
|
if(WIFEXITED(status)){
|
|
switch(WEXITSTATUS(status)){
|
|
case NRT_Default:
|
|
g_eventLogger.info("Angel shutting down");
|
|
exit(0);
|
|
break;
|
|
case NRT_NoStart_Restart:
|
|
theConfig->setInitialStart(false);
|
|
globalData.theRestartFlag = initial_state;
|
|
break;
|
|
case NRT_NoStart_InitialStart:
|
|
theConfig->setInitialStart(true);
|
|
globalData.theRestartFlag = initial_state;
|
|
break;
|
|
case NRT_DoStart_InitialStart:
|
|
theConfig->setInitialStart(true);
|
|
globalData.theRestartFlag = perform_start;
|
|
break;
|
|
default:
|
|
if(theConfig->stopOnError()){
|
|
/**
|
|
* Error shutdown && stopOnError()
|
|
*/
|
|
exit(0);
|
|
}
|
|
// Fall-through
|
|
case NRT_DoStart_Restart:
|
|
theConfig->setInitialStart(false);
|
|
globalData.theRestartFlag = perform_start;
|
|
break;
|
|
}
|
|
} else if(theConfig->stopOnError()){
|
|
/**
|
|
* Error shutdown && stopOnError()
|
|
*/
|
|
exit(0);
|
|
}
|
|
g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
|
|
}
|
|
|
|
g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
|
|
systemInfo(* theConfig, * theConfig->m_logLevel);
|
|
|
|
// Load blocks
|
|
globalEmulatorData.theSimBlockList->load(* theConfig);
|
|
|
|
// Set thread concurrency for Solaris' light weight processes
|
|
int status;
|
|
status = NdbThread_SetConcurrencyLevel(30);
|
|
NDB_ASSERT(status == 0, "Can't set appropriate concurrency level.");
|
|
|
|
#ifdef VM_TRACE
|
|
// Create a signal logger
|
|
char buf[255];
|
|
strcpy(buf, homePath);
|
|
FILE * signalLog = fopen(strncat(buf,"Signal.log", 255), "a");
|
|
globalSignalLoggers.setOwnNodeId(globalData.ownId);
|
|
globalSignalLoggers.setOutputStream(signalLog);
|
|
#endif
|
|
|
|
catchsigs(false);
|
|
|
|
/**
|
|
* Do startup
|
|
*/
|
|
switch(globalData.theRestartFlag){
|
|
case initial_state:
|
|
globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
|
|
break;
|
|
case perform_start:
|
|
globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
|
|
globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
|
|
break;
|
|
default:
|
|
NDB_ASSERT(0, "Illegal state globalData.theRestartFlag");
|
|
}
|
|
|
|
SocketServer socket_server;
|
|
|
|
globalTransporterRegistry.startSending();
|
|
globalTransporterRegistry.startReceiving();
|
|
if (!globalTransporterRegistry.start_service(socket_server))
|
|
NDB_ASSERT(0, "globalTransporterRegistry.start_service() failed");
|
|
|
|
if (!globalTransporterRegistry.start_clients())
|
|
NDB_ASSERT(0, "globalTransporterRegistry.start_clients() failed");
|
|
|
|
globalEmulatorData.theWatchDog->doStart();
|
|
|
|
socket_server.startServer();
|
|
|
|
globalEmulatorData.theThreadConfig->ipControlLoop();
|
|
|
|
NdbShutdown(NST_Normal);
|
|
|
|
socket_server.stopServer();
|
|
socket_server.stopSessions();
|
|
|
|
globalTransporterRegistry.stop_clients();
|
|
|
|
return NRT_Default;
|
|
}
|
|
|
|
|
|
void
|
|
systemInfo(const Configuration & config, const LogLevel & logLevel){
|
|
#ifdef NDB_WIN32
|
|
int processors = 0;
|
|
int speed;
|
|
SYSTEM_INFO sinfo;
|
|
GetSystemInfo(&sinfo);
|
|
processors = sinfo.dwNumberOfProcessors;
|
|
HKEY hKey;
|
|
if(ERROR_SUCCESS==RegOpenKeyEx
|
|
(HKEY_LOCAL_MACHINE,
|
|
TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
|
|
0, KEY_READ, &hKey)) {
|
|
DWORD dwMHz;
|
|
DWORD cbData = sizeof(dwMHz);
|
|
if(ERROR_SUCCESS==RegQueryValueEx(hKey,
|
|
"~MHz", 0, 0, (LPBYTE)&dwMHz, &cbData)) {
|
|
speed = int(dwMHz);
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
#elif defined NDB_SOLARIS // ok
|
|
// Search for at max 16 processors among the first 256 processor ids
|
|
processor_info_t pinfo; memset(&pinfo, 0, sizeof(pinfo));
|
|
int pid = 0;
|
|
while(processors < 16 && pid < 256){
|
|
if(!processor_info(pid++, &pinfo))
|
|
processors++;
|
|
}
|
|
speed = pinfo.pi_clock;
|
|
#endif
|
|
|
|
if(logLevel.getLogLevel(LogLevel::llStartUp) > 0){
|
|
g_eventLogger.info("NDB Cluster -- DB node %d", globalData.ownId);
|
|
g_eventLogger.info("%s --", NDB_VERSION_STRING);
|
|
#ifdef NDB_SOLARIS // ok
|
|
g_eventLogger.info("NDB is running on a machine with %d processor(s) at %d MHz",
|
|
processor, speed);
|
|
#endif
|
|
}
|
|
if(logLevel.getLogLevel(LogLevel::llStartUp) > 3){
|
|
Uint32 t = config.timeBetweenWatchDogCheck();
|
|
g_eventLogger.info("WatchDog timer is set to %d ms", t);
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
catchsigs(bool ignore){
|
|
#if ! defined NDB_SOFTOSE && !defined NDB_OSE
|
|
|
|
#if defined SIGRTMIN
|
|
#define MAX_SIG_CATCH SIGRTMIN
|
|
#elif defined NSIG
|
|
#define MAX_SIG_CATCH NSIG
|
|
#else
|
|
#error "neither SIGRTMIN or NSIG is defined on this platform, please report bug at bugs.mysql.com"
|
|
#endif
|
|
|
|
// Makes the main process catch process signals, eg installs a
|
|
// handler named "handler". "handler" will then be called is instead
|
|
// of the defualt process signal handler)
|
|
if(ignore){
|
|
for(int i = 1; i < MAX_SIG_CATCH; i++){
|
|
if(i != SIGCHLD)
|
|
signal(i, SIG_IGN);
|
|
}
|
|
} else {
|
|
for(int i = 1; i < MAX_SIG_CATCH; i++){
|
|
signal(i, handler);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
extern "C"
|
|
void
|
|
handler(int sig){
|
|
switch(sig){
|
|
case SIGHUP: /* 1 - Hang up */
|
|
case SIGINT: /* 2 - Interrupt */
|
|
case SIGQUIT: /* 3 - Quit */
|
|
case SIGTERM: /* 15 - Terminate */
|
|
#ifdef SIGPWR
|
|
case SIGPWR: /* 19 - Power fail */
|
|
#endif
|
|
#ifdef SIGPOLL
|
|
case SIGPOLL: /* 22 */
|
|
#endif
|
|
case SIGSTOP: /* 23 */
|
|
case SIGTSTP: /* 24 */
|
|
case SIGTTIN: /* 26 */
|
|
case SIGTTOU: /* 27 */
|
|
globalData.theRestartFlag = perform_stop;
|
|
break;
|
|
#ifdef SIGWINCH
|
|
case SIGWINCH:
|
|
#endif
|
|
case SIGPIPE:
|
|
/**
|
|
* Can happen in TCP Transporter
|
|
*
|
|
* Just ignore
|
|
*/
|
|
break;
|
|
default:
|
|
// restart the system
|
|
char errorData[40];
|
|
snprintf(errorData, 40, "Signal %d received", sig);
|
|
ERROR_SET(fatal, 0, errorData, __FILE__);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|