MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ndbd.cpp
1 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 #include <ndb_global.h>
17 
18 #include <NdbEnv.h>
19 #include <NdbConfig.h>
20 #include <NdbSleep.h>
21 #include <portlib/NdbDir.hpp>
22 #include <NdbAutoPtr.hpp>
23 #include <portlib/NdbNuma.h>
24 
25 #include "vm/SimBlockList.hpp"
26 #include "vm/WatchDog.hpp"
27 #include "vm/ThreadConfig.hpp"
28 #include "vm/Configuration.hpp"
29 
30 #include "ndbd.hpp"
31 
32 #include <ConfigRetriever.hpp>
33 #include <LogLevel.hpp>
34 
35 #if defined NDB_SOLARIS
36 #include <sys/processor.h>
37 #endif
38 
39 #include <EventLogger.hpp>
40 extern EventLogger * g_eventLogger;
41 
42 static void
43 systemInfo(const Configuration & config, const LogLevel & logLevel)
44 {
45 #ifdef NDB_WIN32
46  int processors = 0;
47  int speed;
48  SYSTEM_INFO sinfo;
49  GetSystemInfo(&sinfo);
50  processors = sinfo.dwNumberOfProcessors;
51  HKEY hKey;
52  if(ERROR_SUCCESS==RegOpenKeyEx
53  (HKEY_LOCAL_MACHINE,
54  TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
55  0, KEY_READ, &hKey)) {
56  DWORD dwMHz;
57  DWORD cbData = sizeof(dwMHz);
58  if(ERROR_SUCCESS==RegQueryValueEx(hKey,
59  "~MHz", 0, 0, (LPBYTE)&dwMHz, &cbData)) {
60  speed = int(dwMHz);
61  }
62  RegCloseKey(hKey);
63  }
64 #elif defined NDB_SOLARIS
65  // Search for at max 16 processors among the first 256 processor ids
66  processor_info_t pinfo; memset(&pinfo, 0, sizeof(pinfo));
67  int pid = 0;
68  while(processors < 16 && pid < 256){
69  if(!processor_info(pid++, &pinfo))
70  processors++;
71  }
72  speed = pinfo.pi_clock;
73 #endif
74 
75  if(logLevel.getLogLevel(LogLevel::llStartUp) > 0){
76  g_eventLogger->info("NDB Cluster -- DB node %d", globalData.ownId);
77  g_eventLogger->info("%s --", NDB_VERSION_STRING);
78 #ifdef NDB_SOLARIS
79  g_eventLogger->info("NDB is running on a machine with %d processor(s) at %d MHz",
80  processor, speed);
81 #endif
82  }
83  if(logLevel.getLogLevel(LogLevel::llStartUp) > 3){
84  Uint32 t = config.timeBetweenWatchDogCheck();
85  g_eventLogger->info("WatchDog timer is set to %d ms", t);
86  }
87 }
88 
89 
90 Uint32
91 compute_acc_32kpages(const ndb_mgm_configuration_iterator * p)
92 {
93  Uint64 accmem = 0;
94  ndb_mgm_get_int64_parameter(p, CFG_DB_INDEX_MEM, &accmem);
95  if (accmem)
96  {
97  accmem /= GLOBAL_PAGE_SIZE;
98 
99  Uint32 lqhInstances = 1;
100  if (globalData.isNdbMtLqh)
101  {
102  lqhInstances = globalData.ndbMtLqhWorkers;
103  }
104 
105  accmem += lqhInstances * (32 / 4); // Added as safty in Configuration.cpp
106  }
107  return Uint32(accmem);
108 }
109 
110 static int
111 init_global_memory_manager(EmulatorData &ed, Uint32 *watchCounter)
112 {
114  ed.theConfiguration->getOwnConfigIterator();
115  if (p == 0)
116  {
117  abort();
118  }
119 
120  Uint32 numa = 0;
121  ndb_mgm_get_int_parameter(p, CFG_DB_NUMA, &numa);
122  if (numa == 1)
123  {
124  int res = NdbNuma_setInterleaved();
125  g_eventLogger->info("numa_set_interleave_mask(numa_all_nodes) : %s",
126  res == 0 ? "OK" : "no numa support");
127  }
128 
129  Uint64 shared_mem = 8*1024*1024;
130  ndb_mgm_get_int64_parameter(p, CFG_DB_SGA, &shared_mem);
131  Uint32 shared_pages = Uint32(shared_mem /= GLOBAL_PAGE_SIZE);
132 
133  Uint32 tupmem = 0;
134  if (ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE, &tupmem))
135  {
136  g_eventLogger->alert("Failed to get CFG_TUP_PAGE parameter from "
137  "config, exiting.");
138  return -1;
139  }
140 
141  {
145  Uint32 accpages = compute_acc_32kpages(p);
146  tupmem += accpages; // Add to RG_DATAMEM
147  }
148 
149  Uint32 lqhInstances = 1;
150  if (globalData.isNdbMtLqh)
151  {
152  lqhInstances = globalData.ndbMtLqhWorkers;
153  }
154 
155  if (tupmem)
156  {
157  Resource_limit rl;
158  rl.m_min = tupmem;
159  rl.m_max = tupmem;
160  rl.m_resource_id = RG_DATAMEM;
161  ed.m_mem_manager->set_resource_limit(rl);
162  }
163 
164  Uint32 maxopen = 4 * 4; // 4 redo parts, max 4 files per part
165  Uint32 filebuffer = NDB_FILE_BUFFER_SIZE;
166  Uint32 filepages = (filebuffer / GLOBAL_PAGE_SIZE) * maxopen;
167 
168  {
172  Uint32 redomem = 0;
173  ndb_mgm_get_int_parameter(p, CFG_DB_REDO_BUFFER,
174  &redomem);
175 
176  if (redomem)
177  {
178  redomem /= GLOBAL_PAGE_SIZE;
179  Uint32 tmp = redomem & 15;
180  if (tmp != 0)
181  {
182  redomem += (16 - tmp);
183  }
184 
185  filepages += lqhInstances * redomem; // Add to RG_FILE_BUFFERS
186  }
187  }
188 
189  if (filepages)
190  {
191  Resource_limit rl;
192  rl.m_min = filepages;
193  rl.m_max = filepages;
194  rl.m_resource_id = RG_FILE_BUFFERS;
195  ed.m_mem_manager->set_resource_limit(rl);
196  }
197 
198  Uint32 jbpages = compute_jb_pages(&ed);
199  if (jbpages)
200  {
201  Resource_limit rl;
202  rl.m_min = jbpages;
203  rl.m_max = jbpages;
204  rl.m_resource_id = RG_JOBBUFFER;
205  ed.m_mem_manager->set_resource_limit(rl);
206  }
207 
208  Uint32 sbpages = 0;
209  if (globalTransporterRegistry.get_using_default_send_buffer() == false)
210  {
211  Uint64 mem = globalTransporterRegistry.get_total_max_send_buffer();
212  sbpages = Uint32((mem + GLOBAL_PAGE_SIZE - 1) / GLOBAL_PAGE_SIZE);
213  Resource_limit rl;
214  rl.m_min = sbpages;
215  rl.m_max = sbpages;
216  rl.m_resource_id = RG_TRANSPORTER_BUFFERS;
217  ed.m_mem_manager->set_resource_limit(rl);
218  }
219 
220  Uint32 pgman_pages = 0;
221  {
225  Uint64 page_buffer = 64*1024*1024;
226  ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY,&page_buffer);
227 
228  Uint32 pages = 0;
229  pages += Uint32(page_buffer / GLOBAL_PAGE_SIZE); // in pages
230  pages += LCP_RESTORE_BUFFER * lqhInstances;
231 
232  pgman_pages += pages;
233  pgman_pages += 64;
234 
235  Resource_limit rl;
236  rl.m_min = pgman_pages;
237  rl.m_max = pgman_pages;
238  rl.m_resource_id = RG_DISK_PAGE_BUFFER; // Add to RG_DISK_PAGE_BUFFER
239  ed.m_mem_manager->set_resource_limit(rl);
240  }
241 
242  Uint32 sum = shared_pages + tupmem + filepages + jbpages + sbpages +
243  pgman_pages;
244 
245  if (sum)
246  {
247  Resource_limit rl;
248  rl.m_min = 0;
249  rl.m_max = sum;
250  rl.m_resource_id = 0;
251  ed.m_mem_manager->set_resource_limit(rl);
252  }
253 
254  if (!ed.m_mem_manager->init(watchCounter))
255  {
256  struct ndb_mgm_param_info dm;
257  struct ndb_mgm_param_info sga;
258  size_t size;
259 
260  size = sizeof(ndb_mgm_param_info);
261  ndb_mgm_get_db_parameter_info(CFG_DB_DATA_MEM, &dm, &size);
262  size = sizeof(ndb_mgm_param_info);
263  ndb_mgm_get_db_parameter_info(CFG_DB_SGA, &sga, &size);
264 
265  g_eventLogger->alert("Malloc (%lld bytes) for %s and %s failed, exiting",
266  Uint64(shared_mem + tupmem) * GLOBAL_PAGE_SIZE,
267  dm.m_name, sga.m_name);
268  return -1;
269  }
270 
271  Uint32 late_alloc = 0;
272  ndb_mgm_get_int_parameter(p, CFG_DB_LATE_ALLOC,
273  &late_alloc);
274 
275  Uint32 memlock = 0;
276  ndb_mgm_get_int_parameter(p, CFG_DB_MEMLOCK, &memlock);
277 
278  if (late_alloc)
279  {
283  Uint32 rg[] = { RG_JOBBUFFER, RG_FILE_BUFFERS, RG_TRANSPORTER_BUFFERS, 0 };
284  ed.m_mem_manager->map(watchCounter, memlock, rg);
285  }
286  else
287  {
288  ed.m_mem_manager->map(watchCounter, memlock); // Map all
289  }
290 
291  return 0; // Success
292 }
293 
294 
295 static int
296 get_multithreaded_config(EmulatorData& ed)
297 {
298  // multithreaded is compiled in ndbd/ndbmtd for now
299  globalData.isNdbMt = SimulatedBlock::isMultiThreaded();
300  if (!globalData.isNdbMt)
301  {
302  ndbout << "NDBMT: non-mt" << endl;
303  return 0;
304  }
305 
306  THRConfig & conf = ed.theConfiguration->m_thr_config;
307 
308  Uint32 threadcount = conf.getThreadCount();
309  ndbout << "NDBMT: MaxNoOfExecutionThreads=" << threadcount << endl;
310 
311  globalData.isNdbMtLqh = true;
312 
313  {
314  if (conf.getMtClassic())
315  {
316  globalData.isNdbMtLqh = false;
317  }
318  }
319 
320  if (!globalData.isNdbMtLqh)
321  return 0;
322 
323  Uint32 threads = conf.getThreadCount(THRConfig::T_LDM);
324  Uint32 workers = threads;
325  {
326  ndb_mgm_configuration * conf = ed.theConfiguration->getClusterConfig();
327  if (conf == 0)
328  {
329  abort();
330  }
332  ndb_mgm_create_configuration_iterator(conf, CFG_SECTION_NODE);
333  if (ndb_mgm_find(p, CFG_NODE_ID, globalData.ownId))
334  {
335  abort();
336  }
337  ndb_mgm_get_int_parameter(p, CFG_NDBMT_LQH_WORKERS, &workers);
338  }
339 
340 #ifdef VM_TRACE
341  // testing
342  {
343  const char* p;
344  p = NdbEnv_GetEnv("NDBMT_LQH_WORKERS", (char*)0, 0);
345  if (p != 0)
346  workers = atoi(p);
347  }
348 #endif
349 
350  ndbout << "NDBMT: workers=" << workers
351  << " threads=" << threads << endl;
352 
353  assert(workers != 0 && workers <= MAX_NDBMT_LQH_WORKERS);
354  assert(threads != 0 && threads <= MAX_NDBMT_LQH_THREADS);
355  assert(workers % threads == 0);
356 
357  globalData.ndbMtLqhWorkers = workers;
358  globalData.ndbMtLqhThreads = threads;
359  return 0;
360 }
361 
362 
363 static void
364 ndbd_exit(int code)
365 {
366  // Don't allow negative return code
367  if (code < 0)
368  code = 255;
369 
370 // gcov will not produce results when using _exit
371 #ifdef HAVE_gcov
372  exit(code);
373 #else
374  _exit(code);
375 #endif
376 }
377 
378 
379 static FILE *angel_info_w = NULL;
380 
381 static void
382 writeChildInfo(const char *token, int val)
383 {
384  fprintf(angel_info_w, "%s=%d\n", token, val);
385  fflush(angel_info_w);
386 }
387 
388 static void
389 childReportSignal(int signum)
390 {
391  writeChildInfo("signal", signum);
392 }
393 
394 static void
395 childExit(int error_code, int exit_code, Uint32 currentStartPhase)
396 {
397  writeChildInfo("error", error_code);
398  writeChildInfo("sphase", currentStartPhase);
399  fprintf(angel_info_w, "\n");
400  fclose(angel_info_w);
401  ndbd_exit(exit_code);
402 }
403 
404 static void
405 childAbort(int error_code, int exit_code, Uint32 currentStartPhase)
406 {
407  writeChildInfo("error", error_code);
408  writeChildInfo("sphase", currentStartPhase);
409  fprintf(angel_info_w, "\n");
410  fclose(angel_info_w);
411 
412 #ifdef _WIN32
413  // Don't use 'abort' on Windows since it returns
414  // exit code 3 which conflict with NRT_NoStart_InitialStart
415  ndbd_exit(exit_code);
416 #else
417  signal(SIGABRT, SIG_DFL);
418  abort();
419 #endif
420 }
421 
422 extern "C"
423 void
424 handler_shutdown(int signum){
425  g_eventLogger->info("Received signal %d. Performing stop.", signum);
426  childReportSignal(signum);
427  globalData.theRestartFlag = perform_stop;
428 }
429 
430 extern NdbMutex * theShutdownMutex;
431 
432 extern "C"
433 void
434 handler_error(int signum){
435  // only let one thread run shutdown
436  static bool handling_error = false;
437  static pthread_t thread_id; // Valid when handling_error is true
438 
439  if (handling_error &&
440  pthread_equal(thread_id, pthread_self()))
441  {
442  // Shutdown thread received signal
443 #ifndef NDB_WIN32
444  signal(signum, SIG_DFL);
445  kill(getpid(), signum);
446 #endif
447  while(true)
448  NdbSleep_MilliSleep(10);
449  }
450  if(theShutdownMutex && NdbMutex_Trylock(theShutdownMutex) != 0)
451  while(true)
452  NdbSleep_MilliSleep(10);
453 
454  thread_id = pthread_self();
455  handling_error = true;
456 
457  g_eventLogger->info("Received signal %d. Running error handler.", signum);
458  childReportSignal(signum);
459  // restart the system
460  char errorData[64], *info= 0;
461 #ifdef HAVE_STRSIGNAL
462  info= strsignal(signum);
463 #endif
464  BaseString::snprintf(errorData, sizeof(errorData), "Signal %d received; %s", signum,
465  info ? info : "No text for signal available");
466  ERROR_SET_SIGNAL(fatal, NDBD_EXIT_OS_SIGNAL_RECEIVED, errorData, __FILE__);
467 }
468 
469 
470 static void
471 catchsigs(bool foreground){
472  static const int signals_shutdown[] = {
473 #ifdef SIGBREAK
474  SIGBREAK,
475 #endif
476 #ifdef SIGHUP
477  SIGHUP,
478 #endif
479  SIGINT,
480 #if defined SIGPWR
481  SIGPWR,
482 #elif defined SIGINFO
483  SIGINFO,
484 #endif
485  SIGQUIT,
486  SIGTERM,
487 #ifdef SIGTSTP
488  SIGTSTP,
489 #endif
490 #ifdef SIGTTIN
491  SIGTTIN,
492 #endif
493 #ifdef SIGTTOU
494  SIGTTOU
495 #endif
496  };
497 
498  static const int signals_error[] = {
499  SIGABRT,
500 #ifdef SIGALRM
501  SIGALRM,
502 #endif
503 #ifdef SIGBUS
504  SIGBUS,
505 #endif
506 #ifdef SIGCHLD
507  SIGCHLD,
508 #endif
509  SIGFPE,
510  SIGILL,
511 #ifdef SIGIO
512  SIGIO,
513 #endif
514 #ifdef SIGPOLL
515  SIGPOLL,
516 #endif
517  SIGSEGV
518  };
519 
520  static const int signals_ignore[] = {
521  SIGPIPE
522  };
523 
524  size_t i;
525  for(i = 0; i < sizeof(signals_shutdown)/sizeof(signals_shutdown[0]); i++)
526  signal(signals_shutdown[i], handler_shutdown);
527  for(i = 0; i < sizeof(signals_error)/sizeof(signals_error[0]); i++)
528  signal(signals_error[i], handler_error);
529  for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++)
530  signal(signals_ignore[i], SIG_IGN);
531 
532 #ifdef SIGTRAP
533  if (!foreground)
534  signal(SIGTRAP, handler_error);
535 #endif
536 
537 }
538 
539 #ifdef _WIN32
540 static HANDLE g_shutdown_event;
541 
542 DWORD WINAPI shutdown_thread(LPVOID)
543 {
544  // Wait forever until the shutdown event is signaled
545  WaitForSingleObject(g_shutdown_event, INFINITE);
546 
547  g_eventLogger->info("Performing stop");
548  globalData.theRestartFlag = perform_stop;
549  return 0;
550 }
551 #endif
552 
553 
554 void
555 ndbd_run(bool foreground, int report_fd,
556  const char* connect_str, int force_nodeid, const char* bind_address,
557  bool no_start, bool initial, bool initialstart,
558  unsigned allocated_nodeid)
559 {
560 #ifdef _WIN32
561  {
562  char shutdown_event_name[32];
563  _snprintf(shutdown_event_name, sizeof(shutdown_event_name),
564  "ndbd_shutdown_%d", GetCurrentProcessId());
565 
566  g_shutdown_event = CreateEvent(NULL, TRUE, FALSE, shutdown_event_name);
567  if (g_shutdown_event == NULL)
568  {
569  g_eventLogger->error("Failed to create shutdown event, error: %d",
570  GetLastError());
571  ndbd_exit(1);
572  }
573 
574  HANDLE thread = CreateThread(NULL, 0, &shutdown_thread, NULL, 0, NULL);
575  if (thread == NULL)
576  {
577  g_eventLogger->error("couldn't start shutdown thread, error: %d",
578  GetLastError());
579  ndbd_exit(1);
580  }
581  }
582 #endif
583 
584  if (foreground)
585  g_eventLogger->info("Ndb started in foreground");
586 
587  if (report_fd)
588  {
589  g_eventLogger->debug("Opening report stream on fd: %d", report_fd);
590  // Open a stream for sending extra status to angel
591  if (!(angel_info_w = fdopen(report_fd, "w")))
592  {
593  g_eventLogger->error("Failed to open stream for reporting "
594  "to angel, error: %d (%s)", errno, strerror(errno));
595  ndbd_exit(-1);
596  }
597  }
598  else
599  {
600  // No reporting requested, open /dev/null
601  const char* dev_null = IF_WIN("nul", "/dev/null");
602  if (!(angel_info_w = fopen(dev_null, "w")))
603  {
604  g_eventLogger->error("Failed to open stream for reporting to "
605  "'%s', error: %d (%s)", dev_null, errno,
606  strerror(errno));
607  ndbd_exit(-1);
608  }
609  }
610 
611  globalEmulatorData.create();
612 
613  Configuration* theConfig = globalEmulatorData.theConfiguration;
614  if(!theConfig->init(no_start, initial, initialstart))
615  {
616  g_eventLogger->error("Failed to init Configuration");
617  ndbd_exit(-1);
618  }
619 
620  theConfig->fetch_configuration(connect_str, force_nodeid, bind_address,
621  allocated_nodeid);
622 
623  if (NdbDir::chdir(NdbConfig_get_path(NULL)) != 0)
624  {
625  g_eventLogger->warning("Cannot change directory to '%s', error: %d",
626  NdbConfig_get_path(NULL), errno);
627  // Ignore error
628  }
629 
630  theConfig->setupConfiguration();
631 
632  if (get_multithreaded_config(globalEmulatorData))
633  ndbd_exit(-1);
634 
635  systemInfo(* theConfig, * theConfig->m_logLevel);
636 
637  NdbThread* pWatchdog = globalEmulatorData.theWatchDog->doStart();
638 
639  {
640  /*
641  * Memory allocation can take a long time for large memory.
642  *
643  * So we want the watchdog to monitor the process of initial allocation.
644  */
645  Uint32 watchCounter;
646  watchCounter = 9; // Means "doing allocation"
647  globalEmulatorData.theWatchDog->registerWatchedThread(&watchCounter, 0);
648  if (init_global_memory_manager(globalEmulatorData, &watchCounter))
649  ndbd_exit(1);
650  globalEmulatorData.theWatchDog->unregisterWatchedThread(0);
651  }
652 
653  globalEmulatorData.theThreadConfig->init();
654 
655 #ifdef VM_TRACE
656  // Create a signal logger before block constructors
657  char *buf= NdbConfig_SignalLogFileName(globalData.ownId);
658  NdbAutoPtr<char> tmp_aptr(buf);
659  FILE * signalLog = fopen(buf, "a");
660  globalSignalLoggers.setOwnNodeId(globalData.ownId);
661  globalSignalLoggers.setOutputStream(signalLog);
662 #if 1 // to log startup
663  { const char* p = NdbEnv_GetEnv("NDB_SIGNAL_LOG", (char*)0, 0);
664  if (p != 0) {
665  char buf[200];
666  BaseString::snprintf(buf, sizeof(buf), "BLOCK=%s", p);
667  for (char* q = buf; *q != 0; q++) *q = toupper(toascii(*q));
668  globalSignalLoggers.log(SignalLoggerManager::LogInOut, buf);
669  globalData.testOn = 1;
670  assert(signalLog != 0);
671  fprintf(signalLog, "START\n");
672  fflush(signalLog);
673  }
674  }
675 #endif
676 #endif
677 
678  // Load blocks (both main and workers)
679  globalEmulatorData.theSimBlockList->load(globalEmulatorData);
680 
681  // Set thread concurrency for Solaris' light weight processes
682  int status;
683  status = NdbThread_SetConcurrencyLevel(30);
684  assert(status == 0);
685 
686  catchsigs(foreground);
687 
691  switch(globalData.theRestartFlag){
692  case initial_state:
693  globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
694  break;
695  case perform_start:
696  globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
697  globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
698  break;
699  default:
700  assert("Illegal state globalData.theRestartFlag" == 0);
701  }
702 
703  globalTransporterRegistry.startSending();
704  globalTransporterRegistry.startReceiving();
705  if (!globalTransporterRegistry.start_service(*globalEmulatorData.m_socket_server)){
706  ndbout_c("globalTransporterRegistry.start_service() failed");
707  ndbd_exit(-1);
708  }
709 
710  // Re-use the mgm handle as a transporter
711  if(!globalTransporterRegistry.connect_client(
712  theConfig->get_config_retriever()->get_mgmHandlePtr()))
713  ERROR_SET(fatal, NDBD_EXIT_CONNECTION_SETUP_FAILED,
714  "Failed to convert mgm connection to a transporter",
715  __FILE__);
716 
717  NdbThread* pTrp = globalTransporterRegistry.start_clients();
718  if (pTrp == 0)
719  {
720  ndbout_c("globalTransporterRegistry.start_clients() failed");
721  ndbd_exit(-1);
722  }
723 
724  NdbThread* pSockServ = globalEmulatorData.m_socket_server->startServer();
725 
726  globalEmulatorData.theConfiguration->addThread(pTrp, SocketClientThread);
727  globalEmulatorData.theConfiguration->addThread(pWatchdog, WatchDogThread);
728  globalEmulatorData.theConfiguration->addThread(pSockServ, SocketServerThread);
729 
730  // theConfig->closeConfiguration();
731  {
732  NdbThread *pThis = NdbThread_CreateObject(0);
733  Uint32 inx = globalEmulatorData.theConfiguration->addThread(pThis,
734  MainThread);
735  globalEmulatorData.theThreadConfig->ipControlLoop(pThis, inx);
736  globalEmulatorData.theConfiguration->removeThreadId(inx);
737  }
738  NdbShutdown(0, NST_Normal);
739 
740  ndbd_exit(0);
741 }
742 
743 
744 extern "C" my_bool opt_core;
745 
746 // instantiated and updated in NdbcntrMain.cpp
747 extern Uint32 g_currentStartPhase;
748 
749 int simulate_error_during_shutdown= 0;
750 
751 void
752 NdbShutdown(int error_code,
753  NdbShutdownType type,
754  NdbRestartType restartType)
755 {
756  if(type == NST_ErrorInsert)
757  {
758  type = NST_Restart;
759  restartType = (NdbRestartType)
760  globalEmulatorData.theConfiguration->getRestartOnErrorInsert();
761  if(restartType == NRT_Default)
762  {
763  type = NST_ErrorHandler;
764  globalEmulatorData.theConfiguration->stopOnError(true);
765  }
766  }
767 
768  if((type == NST_ErrorHandlerSignal) || // Signal handler has already locked mutex
769  (NdbMutex_Trylock(theShutdownMutex) == 0)){
770  globalData.theRestartFlag = perform_stop;
771 
772  bool restart = false;
773 
774  if((type != NST_Normal &&
775  globalEmulatorData.theConfiguration->stopOnError() == false) ||
776  type == NST_Restart)
777  {
778  restart = true;
779  }
780 
781  const char * shutting = "shutting down";
782  if(restart)
783  {
784  shutting = "restarting";
785  }
786 
787  switch(type){
788  case NST_Normal:
789  g_eventLogger->info("Shutdown initiated");
790  break;
791  case NST_Watchdog:
792  g_eventLogger->info("Watchdog %s system", shutting);
793  break;
794  case NST_ErrorHandler:
795  g_eventLogger->info("Error handler %s system", shutting);
796  break;
797  case NST_ErrorHandlerSignal:
798  g_eventLogger->info("Error handler signal %s system", shutting);
799  break;
800  case NST_Restart:
801  g_eventLogger->info("Restarting system");
802  break;
803  default:
804  g_eventLogger->info("Error handler %s system (unknown type: %u)",
805  shutting, (unsigned)type);
806  type = NST_ErrorHandler;
807  break;
808  }
809 
810  const char * exitAbort = 0;
811  if (opt_core)
812  exitAbort = "aborting";
813  else
814  exitAbort = "exiting";
815 
816  if(type == NST_Watchdog)
817  {
821  g_eventLogger->info("Watchdog shutdown completed - %s", exitAbort);
822  if (opt_core)
823  {
824  childAbort(error_code, -1,g_currentStartPhase);
825  }
826  else
827  {
828  childExit(error_code, -1,g_currentStartPhase);
829  }
830  }
831 
832 #ifndef NDB_WIN32
833  if (simulate_error_during_shutdown)
834  {
835  kill(getpid(), simulate_error_during_shutdown);
836  while(true)
837  NdbSleep_MilliSleep(10);
838  }
839 #endif
840 
841  globalEmulatorData.theWatchDog->doStop();
842 
843 #ifdef VM_TRACE
844  FILE * outputStream = globalSignalLoggers.setOutputStream(0);
845  if(outputStream != 0)
846  fclose(outputStream);
847 #endif
848 
854 #if NOT_YET
855 
859  globalEmulatorData.m_socket_server->stopServer();
860  globalEmulatorData.m_socket_server->stopSessions();
861  globalTransporterRegistry.stop_clients();
862 
866  globalTransporterRegistry.stopSending();
867  globalTransporterRegistry.stopReceiving();
868 
872  globalTransporterRegistry.removeAll();
873 #endif
874 
875  if(type == NST_ErrorInsert && opt_core)
876  {
877  // Unload some structures to reduce size of core
878  globalEmulatorData.theSimBlockList->unload();
879  NdbMutex_Unlock(theShutdownMutex);
880  globalEmulatorData.destroy();
881  }
882 
883  if(type != NST_Normal && type != NST_Restart)
884  {
885  g_eventLogger->info("Error handler shutdown completed - %s", exitAbort);
886  if (opt_core)
887  {
888  childAbort(error_code, -1,g_currentStartPhase);
889  }
890  else
891  {
892  childExit(error_code, -1,g_currentStartPhase);
893  }
894  }
895 
899  if(type == NST_Restart){
900  childExit(error_code, restartType,g_currentStartPhase);
901  }
902 
903  g_eventLogger->info("Shutdown completed - exiting");
904  }
905  else
906  {
914  if (type== NST_Watchdog)
915  {
916  g_eventLogger->info("Watchdog is killing system the hard way");
917 #if defined VM_TRACE
918  childAbort(error_code, -1,g_currentStartPhase);
919 #else
920  childExit(error_code, -1, g_currentStartPhase);
921 #endif
922  }
923 
924  while(true)
925  NdbSleep_MilliSleep(10);
926  }
927 }