MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Configuration.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 
20 #include "Configuration.hpp"
21 #include <ErrorHandlingMacros.hpp>
22 #include "GlobalData.hpp"
23 
24 #include <ConfigRetriever.hpp>
25 #include <IPCConfig.hpp>
26 #include <ndb_version.h>
27 #include <NdbMem.h>
28 #include <NdbOut.hpp>
29 #include <WatchDog.hpp>
30 #include <NdbConfig.h>
31 
32 #include <mgmapi_configuration.hpp>
33 #include <kernel_config_parameters.h>
34 
35 #include <util/ConfigValues.hpp>
36 #include <NdbEnv.h>
37 
38 #include <ndbapi_limits.h>
39 #include "mt.hpp"
40 
41 #include <EventLogger.hpp>
42 extern EventLogger * g_eventLogger;
43 
44 extern Uint32 g_start_type;
45 
46 bool
47 Configuration::init(int _no_start, int _initial,
48  int _initialstart)
49 {
50  // Check the start flag
51  if (_no_start)
52  globalData.theRestartFlag = initial_state;
53  else
54  globalData.theRestartFlag = perform_start;
55 
56  // Check the initial flag
57  if (_initial)
58  _initialStart = true;
59 
60  globalData.ownId= 0;
61 
62  if (_initialstart)
63  {
64  _initialStart = true;
65  g_start_type |= (1 << NodeState::ST_INITIAL_START);
66  }
67 
68  threadIdMutex = NdbMutex_Create();
69  if (!threadIdMutex)
70  {
71  g_eventLogger->error("Failed to create threadIdMutex");
72  return false;
73  }
74  initThreadArray();
75  return true;
76 }
77 
78 Configuration::Configuration()
79 {
80  _fsPath = 0;
81  _backupPath = 0;
82  _initialStart = false;
83  m_config_retriever= 0;
84  m_clusterConfig= 0;
85  m_clusterConfigIter= 0;
86  m_logLevel= 0;
87 }
88 
89 Configuration::~Configuration(){
90 
91  if(_fsPath != NULL)
92  free(_fsPath);
93 
94  if(_backupPath != NULL)
95  free(_backupPath);
96 
97  if (m_config_retriever) {
98  delete m_config_retriever;
99  }
100 
101  if(m_logLevel) {
102  delete m_logLevel;
103  }
104 }
105 
106 void
107 Configuration::closeConfiguration(bool end_session){
108  m_config_retriever->end_session(end_session);
109  if (m_config_retriever) {
110  delete m_config_retriever;
111  }
112  m_config_retriever= 0;
113 }
114 
115 void
116 Configuration::fetch_configuration(const char* _connect_string,
117  int force_nodeid,
118  const char* _bind_address,
119  NodeId allocated_nodeid)
120 {
124  if (m_config_retriever) {
125  delete m_config_retriever;
126  }
127 
128  m_config_retriever= new ConfigRetriever(_connect_string,
129  force_nodeid,
130  NDB_VERSION,
132  _bind_address);
133  if (!m_config_retriever)
134  {
135  ERROR_SET(fatal, NDBD_EXIT_MEMALLOC,
136  "Failed to create ConfigRetriever", "");
137  }
138 
139  if (m_config_retriever->hasError())
140  {
141  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
142  "Could not initialize handle to management server",
143  m_config_retriever->getErrorString());
144  }
145 
146  if(m_config_retriever->do_connect(12,5,1) == -1){
147  const char * s = m_config_retriever->getErrorString();
148  if(s == 0)
149  s = "No error given!";
150  /* Set stop on error to true otherwise NDB will
151  go into an restart loop...
152  */
153  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Could not connect to ndb_mgmd", s);
154  }
155 
156  ConfigRetriever &cr= *m_config_retriever;
157 
158  if (allocated_nodeid)
159  {
160  // The angel has already allocated the nodeid, no need to
161  // allocate it
162  globalData.ownId = allocated_nodeid;
163  }
164  else
165  {
166 
167  const int alloc_retries = 2;
168  const int alloc_delay = 3;
169  globalData.ownId = cr.allocNodeId(alloc_retries, alloc_delay);
170  if(globalData.ownId == 0)
171  {
172  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
173  "Unable to alloc node id",
174  m_config_retriever->getErrorString());
175  }
176  }
177  assert(globalData.ownId);
178 
179  ndb_mgm_configuration * p = cr.getConfig(globalData.ownId);
180  if(p == 0){
181  const char * s = cr.getErrorString();
182  if(s == 0)
183  s = "No error given!";
184 
185  /* Set stop on error to true otherwise NDB will
186  go into an restart loop...
187  */
188 
189  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Could not fetch configuration"
190  "/invalid configuration", s);
191  }
192  if(m_clusterConfig)
193  free(m_clusterConfig);
194 
195  m_clusterConfig = p;
196 
197  const ConfigValues * cfg = (ConfigValues*)m_clusterConfig;
198  cfg->pack(m_clusterConfigPacked);
199 
200  {
201  Uint32 generation;
202  ndb_mgm_configuration_iterator sys_iter(*p, CFG_SECTION_SYSTEM);
203  if (sys_iter.get(CFG_SYS_CONFIG_GENERATION, &generation))
204  {
205  g_eventLogger->info("Configuration fetched from '%s:%d', unknown generation!! (likely older ndb_mgmd)",
206  m_config_retriever->get_mgmd_host(),
207  m_config_retriever->get_mgmd_port());
208  }
209  else
210  {
211  g_eventLogger->info("Configuration fetched from '%s:%d', generation: %d",
212  m_config_retriever->get_mgmd_host(),
213  m_config_retriever->get_mgmd_port(),
214  generation);
215  }
216  }
217 
218  ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
219  if (iter.find(CFG_NODE_ID, globalData.ownId)){
220  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched", "DB missing");
221  }
222 
223  if(iter.get(CFG_DB_STOP_ON_ERROR, &_stopOnError)){
224  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
225  "StopOnError missing");
226  }
227 
228  const char * datadir;
229  if(iter.get(CFG_NODE_DATADIR, &datadir)){
230  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
231  "DataDir missing");
232  }
233  NdbConfig_SetPath(datadir);
234 
235 }
236 
237 static char * get_and_validate_path(ndb_mgm_configuration_iterator &iter,
238  Uint32 param, const char *param_string)
239 {
240  const char* path = NULL;
241  if(iter.get(param, &path)){
242  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched missing ",
243  param_string);
244  }
245 
246  if(path == 0 || strlen(path) == 0){
247  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
248  "Invalid configuration fetched. Configuration does not contain valid ",
249  param_string);
250  }
251 
252  // check that it is pointing on a valid directory
253  //
254  char buf2[PATH_MAX];
255  memset(buf2, 0,sizeof(buf2));
256 #ifdef NDB_WIN32
257  char* szFilePart;
258  if(!GetFullPathName(path, sizeof(buf2), buf2, &szFilePart) ||
259  (GetFileAttributes(buf2) & FILE_ATTRIBUTE_READONLY))
260 #else
261  if((::realpath(path, buf2) == NULL)||
262  (::access(buf2, W_OK) != 0))
263 #endif
264  {
265  ERROR_SET(fatal, NDBD_EXIT_AFS_INVALIDPATH, path, param_string);
266  }
267 
268  if (strcmp(&buf2[strlen(buf2) - 1], DIR_SEPARATOR))
269  strcat(buf2, DIR_SEPARATOR);
270 
271  return strdup(buf2);
272 }
273 
274 #include "../../common/util/parse_mask.hpp"
275 
276 void
278 
279  DBUG_ENTER("Configuration::setupConfiguration");
280 
281  ndb_mgm_configuration * p = m_clusterConfig;
282 
286  if (!globalTransporterRegistry.init(globalData.ownId))
287  {
288  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
289  "Invalid configuration fetched",
290  "Could not init transporter registry");
291  }
292 
293  if (!IPCConfig::configureTransporters(globalData.ownId,
294  * p,
295  globalTransporterRegistry))
296  {
297  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
298  "Invalid configuration fetched",
299  "Could not configure transporters");
300  }
301 
305  ndb_mgm_configuration_iterator iter(* p, CFG_SECTION_NODE);
306  if (iter.find(CFG_NODE_ID, globalData.ownId)){
307  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched", "DB missing");
308  }
309 
310  unsigned type;
311  if(!(iter.get(CFG_TYPE_OF_SECTION, &type) == 0 && type == NODE_TYPE_DB)){
312  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
313  "I'm wrong type of node");
314  }
315 
316  Uint32 total_send_buffer = 0;
317  iter.get(CFG_TOTAL_SEND_BUFFER_MEMORY, &total_send_buffer);
318  globalTransporterRegistry.allocate_send_buffers(total_send_buffer);
319 
320  if(iter.get(CFG_DB_NO_SAVE_MSGS, &_maxErrorLogs)){
321  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
322  "MaxNoOfSavedMessages missing");
323  }
324 
325  if(iter.get(CFG_DB_MEMLOCK, &_lockPagesInMainMemory)){
326  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
327  "LockPagesInMainMemory missing");
328  }
329 
330  if(iter.get(CFG_DB_WATCHDOG_INTERVAL, &_timeBetweenWatchDogCheck)){
331  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
332  "TimeBetweenWatchDogCheck missing");
333  }
334 
335  _schedulerExecutionTimer = 50;
336  iter.get(CFG_DB_SCHED_EXEC_TIME, &_schedulerExecutionTimer);
337 
338  _schedulerSpinTimer = 0;
339  iter.get(CFG_DB_SCHED_SPIN_TIME, &_schedulerSpinTimer);
340 
341  _realtimeScheduler = 0;
342  iter.get(CFG_DB_REALTIME_SCHEDULER, &_realtimeScheduler);
343 
344  if(iter.get(CFG_DB_WATCHDOG_INTERVAL_INITIAL,
345  &_timeBetweenWatchDogCheckInitial)){
346  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
347  "TimeBetweenWatchDogCheckInitial missing");
348  }
349 
353  if (_fsPath)
354  free(_fsPath);
355  _fsPath= get_and_validate_path(iter, CFG_DB_FILESYSTEM_PATH, "FileSystemPath");
356  if (_backupPath)
357  free(_backupPath);
358  _backupPath= get_and_validate_path(iter, CFG_DB_BACKUP_DATADIR, "BackupDataDir");
359 
360  if(iter.get(CFG_DB_STOP_ON_ERROR_INSERT, &m_restartOnErrorInsert)){
361  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
362  "RestartOnErrorInsert missing");
363  }
364 
368  {
369  if (_timeBetweenWatchDogCheckInitial < _timeBetweenWatchDogCheck)
370  _timeBetweenWatchDogCheckInitial = _timeBetweenWatchDogCheck;
371 
372  Uint32 t = _timeBetweenWatchDogCheckInitial;
373  t = globalEmulatorData.theWatchDog ->setCheckInterval(t);
374  _timeBetweenWatchDogCheckInitial = t;
375  }
376 
377  const char * lockmask = 0;
378  {
379  if (iter.get(CFG_DB_EXECUTE_LOCK_CPU, &lockmask) == 0)
380  {
381  int res = m_thr_config.setLockExecuteThreadToCPU(lockmask);
382  if (res < 0)
383  {
384  // Could not parse LockExecuteThreadToCPU mask
385  g_eventLogger->warning("Failed to parse 'LockExecuteThreadToCPU=%s' "
386  "(error: %d), ignoring it!",
387  lockmask, res);
388  }
389  }
390  }
391 
392  {
393  Uint32 maintCPU = NO_LOCK_CPU;
394  iter.get(CFG_DB_MAINT_LOCK_CPU, &maintCPU);
395  if (maintCPU == 65535)
396  maintCPU = NO_LOCK_CPU; // Ignore old default(may come from old mgmd)
397  if (maintCPU != NO_LOCK_CPU)
398  m_thr_config.setLockIoThreadsToCPU(maintCPU);
399  }
400 
401  const char * thrconfigstring = NdbEnv_GetEnv("NDB_MT_THREAD_CONFIG",
402  (char*)0, 0);
403  if (thrconfigstring ||
404  iter.get(CFG_DB_MT_THREAD_CONFIG, &thrconfigstring) == 0)
405  {
406  int res = m_thr_config.do_parse(thrconfigstring);
407  if (res != 0)
408  {
409  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
410  "Invalid configuration fetched, invalid ThreadConfig",
411  m_thr_config.getErrorMessage());
412  }
413  }
414  else
415  {
416  Uint32 mtthreads = 0;
417  iter.get(CFG_DB_MT_THREADS, &mtthreads);
418 
419  Uint32 classic = 0;
420  iter.get(CFG_NDBMT_CLASSIC, &classic);
421  const char* p = NdbEnv_GetEnv("NDB_MT_LQH", (char*)0, 0);
422  if (p != 0)
423  {
424  if (strstr(p, "NOPLEASE") != 0)
425  classic = 1;
426  }
427 
428  Uint32 lqhthreads = 0;
429  iter.get(CFG_NDBMT_LQH_THREADS, &lqhthreads);
430 
431  int res = m_thr_config.do_parse(mtthreads, lqhthreads, classic);
432  if (res != 0)
433  {
434  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
435  "Invalid configuration fetched, invalid thread configuration",
436  m_thr_config.getErrorMessage());
437  }
438  }
439  if (thrconfigstring)
440  {
441  ndbout_c("ThreadConfig: input: %s LockExecuteThreadToCPU: %s => parsed: %s",
442  thrconfigstring,
443  lockmask ? lockmask : "",
444  m_thr_config.getConfigString());
445  }
446  else
447  {
448  ndbout_c("ThreadConfig (old ndb_mgmd) LockExecuteThreadToCPU: %s => parsed: %s",
449  lockmask ? lockmask : "",
450  m_thr_config.getConfigString());
451  }
452 
453  ConfigValues* cf = ConfigValuesFactory::extractCurrentSection(iter.m_config);
454 
455  if(m_clusterConfigIter)
456  ndb_mgm_destroy_iterator(m_clusterConfigIter);
457  m_clusterConfigIter = ndb_mgm_create_configuration_iterator
458  (p, CFG_SECTION_NODE);
459 
460  calcSizeAlt(cf);
461 
462  DBUG_VOID_RETURN;
463 }
464 
465 Uint32
466 Configuration::lockPagesInMainMemory() const {
467  return _lockPagesInMainMemory;
468 }
469 
470 int
471 Configuration::schedulerExecutionTimer() const {
472  return _schedulerExecutionTimer;
473 }
474 
475 void
476 Configuration::schedulerExecutionTimer(int value) {
477  if (value < 11000)
478  _schedulerExecutionTimer = value;
479 }
480 
481 int
482 Configuration::schedulerSpinTimer() const {
483  return _schedulerSpinTimer;
484 }
485 
486 void
487 Configuration::schedulerSpinTimer(int value) {
488  if (value < 500)
489  value = 500;
490  _schedulerSpinTimer = value;
491 }
492 
493 bool
494 Configuration::realtimeScheduler() const
495 {
496  return (bool)_realtimeScheduler;
497 }
498 
499 void
500 Configuration::realtimeScheduler(bool realtime_on)
501 {
502  bool old_value = (bool)_realtimeScheduler;
503  _realtimeScheduler = (Uint32)realtime_on;
504  if (old_value != realtime_on)
505  setAllRealtimeScheduler();
506 }
507 
508 int
509 Configuration::timeBetweenWatchDogCheck() const {
510  return _timeBetweenWatchDogCheck;
511 }
512 
513 void
514 Configuration::timeBetweenWatchDogCheck(int value) {
515  _timeBetweenWatchDogCheck = value;
516 }
517 
518 int
519 Configuration::maxNoOfErrorLogs() const {
520  return _maxErrorLogs;
521 }
522 
523 void
524 Configuration::maxNoOfErrorLogs(int val){
525  _maxErrorLogs = val;
526 }
527 
528 bool
529 Configuration::stopOnError() const {
530  return _stopOnError;
531 }
532 
533 void
534 Configuration::stopOnError(bool val){
535  _stopOnError = val;
536 }
537 
538 int
539 Configuration::getRestartOnErrorInsert() const {
540  return m_restartOnErrorInsert;
541 }
542 
543 void
544 Configuration::setRestartOnErrorInsert(int i){
545  m_restartOnErrorInsert = i;
546 }
547 
549 Configuration::getOwnConfigIterator() const {
550  return m_ownConfigIterator;
551 }
552 
554 Configuration::getClusterConfigIterator() const {
555  return m_clusterConfigIter;
556 }
557 
558 Uint32
559 Configuration::get_config_generation() const {
560  Uint32 generation = ~0;
561  ndb_mgm_configuration_iterator sys_iter(*m_clusterConfig,
562  CFG_SECTION_SYSTEM);
563  sys_iter.get(CFG_SYS_CONFIG_GENERATION, &generation);
564  return generation;
565 }
566 
567 
568 void
569 Configuration::calcSizeAlt(ConfigValues * ownConfig){
570  const char * msg = "Invalid configuration fetched";
571  char buf[255];
572 
573  unsigned int noOfTables = 0;
574  unsigned int noOfUniqueHashIndexes = 0;
575  unsigned int noOfOrderedIndexes = 0;
576  unsigned int noOfTriggers = 0;
577  unsigned int noOfReplicas = 0;
578  unsigned int noOfDBNodes = 0;
579  unsigned int noOfAPINodes = 0;
580  unsigned int noOfMGMNodes = 0;
581  unsigned int noOfNodes = 0;
582  unsigned int noOfAttributes = 0;
583  unsigned int noOfOperations = 0;
584  unsigned int noOfLocalOperations = 0;
585  unsigned int noOfTransactions = 0;
586  unsigned int noOfIndexPages = 0;
587  unsigned int noOfDataPages = 0;
588  unsigned int noOfScanRecords = 0;
589  unsigned int noOfLocalScanRecords = 0;
590  unsigned int noBatchSize = 0;
591  m_logLevel = new LogLevel();
592  if (!m_logLevel)
593  {
594  ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, "Failed to create LogLevel", "");
595  }
596 
597  struct AttribStorage { int paramId; Uint32 * storage; bool computable; };
598  AttribStorage tmp[] = {
599  { CFG_DB_NO_SCANS, &noOfScanRecords, false },
600  { CFG_DB_NO_LOCAL_SCANS, &noOfLocalScanRecords, true },
601  { CFG_DB_BATCH_SIZE, &noBatchSize, false },
602  { CFG_DB_NO_TABLES, &noOfTables, false },
603  { CFG_DB_NO_ORDERED_INDEXES, &noOfOrderedIndexes, false },
604  { CFG_DB_NO_UNIQUE_HASH_INDEXES, &noOfUniqueHashIndexes, false },
605  { CFG_DB_NO_TRIGGERS, &noOfTriggers, true },
606  { CFG_DB_NO_REPLICAS, &noOfReplicas, false },
607  { CFG_DB_NO_ATTRIBUTES, &noOfAttributes, false },
608  { CFG_DB_NO_OPS, &noOfOperations, false },
609  { CFG_DB_NO_LOCAL_OPS, &noOfLocalOperations, true },
610  { CFG_DB_NO_TRANSACTIONS, &noOfTransactions, false }
611  };
612 
614 
615  const int sz = sizeof(tmp)/sizeof(AttribStorage);
616  for(int i = 0; i<sz; i++){
617  if(ndb_mgm_get_int_parameter(&db, tmp[i].paramId, tmp[i].storage)){
618  if (tmp[i].computable) {
619  *tmp[i].storage = 0;
620  } else {
621  BaseString::snprintf(buf, sizeof(buf),"ConfigParam: %d not found", tmp[i].paramId);
622  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
623  }
624  }
625  }
626 
627  Uint32 lqhInstances = 1;
628  if (globalData.isNdbMtLqh)
629  {
630  lqhInstances = globalData.ndbMtLqhWorkers;
631  }
632 
633  Uint64 indexMem = 0, dataMem = 0;
634  ndb_mgm_get_int64_parameter(&db, CFG_DB_DATA_MEM, &dataMem);
635  ndb_mgm_get_int64_parameter(&db, CFG_DB_INDEX_MEM, &indexMem);
636  if(dataMem == 0){
637  BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_DATA_MEM);
638  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
639  }
640 
641  if(indexMem == 0){
642  BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_INDEX_MEM);
643  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
644  }
645 
646 #define DO_DIV(x,y) (((x) + (y - 1)) / (y))
647 
648  noOfDataPages = (Uint32)(dataMem / 32768);
649  noOfIndexPages = (Uint32)(indexMem / 8192);
650  noOfIndexPages = DO_DIV(noOfIndexPages, lqhInstances);
651 
652  for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
653  Uint32 tmp;
654  if(!ndb_mgm_get_int_parameter(&db, CFG_MIN_LOGLEVEL+j, &tmp)){
655  m_logLevel->setLogLevel((LogLevel::EventCategory)j, tmp);
656  }
657  }
658 
659  // tmp
660  ndb_mgm_configuration_iterator * p = m_clusterConfigIter;
661 
662  Uint32 nodeNo = noOfNodes = 0;
663  NodeBitmask nodes;
664  for(ndb_mgm_first(p); ndb_mgm_valid(p); ndb_mgm_next(p), nodeNo++){
665 
666  Uint32 nodeId;
667  Uint32 nodeType;
668 
669  if(ndb_mgm_get_int_parameter(p, CFG_NODE_ID, &nodeId)){
670  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Id) missing");
671  }
672 
673  if(ndb_mgm_get_int_parameter(p, CFG_TYPE_OF_SECTION, &nodeType)){
674  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Type) missing");
675  }
676 
677  if(nodeId > MAX_NODES || nodeId == 0){
678  BaseString::snprintf(buf, sizeof(buf),
679  "Invalid node id: %d", nodeId);
680  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
681  }
682 
683  if(nodes.get(nodeId)){
684  BaseString::snprintf(buf, sizeof(buf), "Two node can not have the same node id: %d",
685  nodeId);
686  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
687  }
688  nodes.set(nodeId);
689 
690  switch(nodeType){
691  case NODE_TYPE_DB:
692  noOfDBNodes++; // No of NDB processes
693 
694  if(nodeId > MAX_NDB_NODES){
695  BaseString::snprintf(buf, sizeof(buf), "Maximum node id for a ndb node is: %d",
696  MAX_NDB_NODES);
697  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
698  }
699  break;
700  case NODE_TYPE_API:
701  noOfAPINodes++; // No of API processes
702  break;
703  case NODE_TYPE_MGM:
704  noOfMGMNodes++; // No of MGM processes
705  break;
706  default:
707  BaseString::snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
708  ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
709  }
710  }
711  noOfNodes = nodeNo;
712 
713  noOfTables+= 2; // Add System tables
714  noOfAttributes += 9; // Add System table attributes
715 
716  ConfigValues::Iterator it2(*ownConfig, db.m_config);
717  it2.set(CFG_DB_NO_TABLES, noOfTables);
718  it2.set(CFG_DB_NO_ATTRIBUTES, noOfAttributes);
719  {
720  Uint32 neededNoOfTriggers = /* types: Insert/Update/Delete/Custom */
721  3 * noOfUniqueHashIndexes + /* for unique hash indexes, I/U/D */
722  3 * NDB_MAX_ACTIVE_EVENTS + /* for events in suma, I/U/D */
723  3 * noOfTables + /* for backup, I/U/D */
724  noOfOrderedIndexes; /* for ordered indexes, C */
725  if (noOfTriggers < neededNoOfTriggers)
726  {
727  noOfTriggers= neededNoOfTriggers;
728  it2.set(CFG_DB_NO_TRIGGERS, noOfTriggers);
729  }
730  }
731 
735  ConfigValuesFactory cfg(ownConfig);
736 
737  Uint32 noOfMetaTables= noOfTables + noOfOrderedIndexes +
738  noOfUniqueHashIndexes;
739  Uint32 noOfMetaTablesDict= noOfMetaTables;
740  if (noOfMetaTablesDict > NDB_MAX_TABLES)
741  noOfMetaTablesDict= NDB_MAX_TABLES;
742 
743  {
747  cfg.put(CFG_DICT_ATTRIBUTE,
748  noOfAttributes);
749 
750  cfg.put(CFG_DICT_TABLE,
751  noOfMetaTablesDict);
752  }
753 
754 
755  if (noOfLocalScanRecords == 0) {
756 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
757  noOfLocalScanRecords = (noOfDBNodes * noOfScanRecords) +
758 #else
759  noOfLocalScanRecords = 4 * (noOfDBNodes * noOfScanRecords) +
760 #endif
761  1 /* NR */ +
762  1 /* LCP */;
763  }
764  if (noOfLocalOperations == 0) {
765  noOfLocalOperations= (11 * noOfOperations) / 10;
766  }
767 
768  Uint32 noOfTCScanRecords = noOfScanRecords;
769  Uint32 noOfTCLocalScanRecords = noOfLocalScanRecords;
770 
771  noOfLocalOperations = DO_DIV(noOfLocalOperations, lqhInstances);
772  noOfLocalScanRecords = DO_DIV(noOfLocalScanRecords, lqhInstances);
773 
774  {
775  Uint32 noOfAccTables= noOfMetaTables/*noOfTables+noOfUniqueHashIndexes*/;
779  // Can keep 65536 pages (= 0.5 GByte)
780  cfg.put(CFG_ACC_DIR_RANGE,
781  2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
782 
783  cfg.put(CFG_ACC_DIR_ARRAY,
784  (noOfIndexPages >> 8) +
785  2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
786 
787  cfg.put(CFG_ACC_FRAGMENT,
788  NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
789 
790  /*-----------------------------------------------------------------------*/
791  // The extra operation records added are used by the scan and node
792  // recovery process.
793  // Node recovery process will have its operations dedicated to ensure
794  // that they never have a problem with allocation of the operation record.
795  // The remainder are allowed for use by the scan processes.
796  /*-----------------------------------------------------------------------*/
797  cfg.put(CFG_ACC_OP_RECS,
798  (noOfLocalOperations + 50) +
799  (noOfLocalScanRecords * noBatchSize) +
800  NODE_RECOVERY_SCAN_OP_RECORDS);
801 
802  cfg.put(CFG_ACC_OVERFLOW_RECS,
803  noOfIndexPages +
804  NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
805 
806  cfg.put(CFG_ACC_PAGE8,
807  noOfIndexPages + 32);
808 
809  cfg.put(CFG_ACC_TABLE, noOfAccTables);
810 
811  cfg.put(CFG_ACC_SCAN, noOfLocalScanRecords);
812  }
813 
814  {
818  cfg.put(CFG_DIH_API_CONNECT,
819  2 * noOfTransactions);
820 
821  Uint32 noFragPerTable= (((noOfDBNodes * lqhInstances) +
822  NO_OF_FRAGS_PER_CHUNK - 1) >>
823  LOG_NO_OF_FRAGS_PER_CHUNK) <<
824  LOG_NO_OF_FRAGS_PER_CHUNK;
825 
826  cfg.put(CFG_DIH_FRAG_CONNECT,
827  noFragPerTable * noOfMetaTables);
828 
829  cfg.put(CFG_DIH_REPLICAS,
830  NO_OF_FRAG_PER_NODE * noOfMetaTables *
831  noOfDBNodes * noOfReplicas * lqhInstances);
832 
833  cfg.put(CFG_DIH_TABLE,
834  noOfMetaTables);
835  }
836 
837  {
841  cfg.put(CFG_LQH_FRAG,
842  NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas);
843 
844  cfg.put(CFG_LQH_TABLE,
845  noOfMetaTables);
846 
847  cfg.put(CFG_LQH_TC_CONNECT,
848  noOfLocalOperations + 50);
849 
850  cfg.put(CFG_LQH_SCAN,
851  noOfLocalScanRecords);
852  }
853 
854  {
858  cfg.put(CFG_TC_API_CONNECT,
859  3 * noOfTransactions);
860 
861  cfg.put(CFG_TC_TC_CONNECT,
862  (2 * noOfOperations) + 16 + noOfTransactions);
863 
864  cfg.put(CFG_TC_TABLE,
865  noOfMetaTables);
866 
867  cfg.put(CFG_TC_LOCAL_SCAN,
868  noOfTCLocalScanRecords);
869 
870  cfg.put(CFG_TC_SCAN,
871  noOfTCScanRecords);
872  }
873 
874  {
878  cfg.put(CFG_TUP_FRAG,
879  NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
880 
881  cfg.put(CFG_TUP_OP_RECS,
882  noOfLocalOperations + 50);
883 
884  cfg.put(CFG_TUP_PAGE,
885  noOfDataPages);
886 
887  cfg.put(CFG_TUP_TABLE,
888  noOfMetaTables);
889 
890  cfg.put(CFG_TUP_STORED_PROC,
891  noOfLocalScanRecords);
892  }
893 
894  {
898  cfg.put(CFG_TUX_INDEX,
899  noOfMetaTables /*noOfOrderedIndexes*/);
900 
901  cfg.put(CFG_TUX_FRAGMENT,
902  NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
903 
904  cfg.put(CFG_TUX_ATTRIBUTE,
905  noOfOrderedIndexes * 4);
906 
907  cfg.put(CFG_TUX_SCAN_OP, noOfLocalScanRecords);
908  }
909 
910  m_ownConfig = (ndb_mgm_configuration*)cfg.getConfigValues();
911  m_ownConfigIterator = ndb_mgm_create_configuration_iterator
912  (m_ownConfig, 0);
913 }
914 
915 void
916 Configuration::setAllRealtimeScheduler()
917 {
918  Uint32 i;
919  for (i = 0; i < threadInfo.size(); i++)
920  {
921  if (threadInfo[i].type != NotInUse)
922  {
923  if (setRealtimeScheduler(threadInfo[i].pThread,
924  threadInfo[i].type,
925  _realtimeScheduler,
926  FALSE))
927  return;
928  }
929  }
930 }
931 
932 void
933 Configuration::setAllLockCPU(bool exec_thread)
934 {
935  Uint32 i;
936  for (i = 0; i < threadInfo.size(); i++)
937  {
938  if (threadInfo[i].type == NotInUse)
939  continue;
940 
941  bool run =
942  (exec_thread && threadInfo[i].type == MainThread) ||
943  (!exec_thread && threadInfo[i].type != MainThread);
944 
945  if (run)
946  {
947  setLockCPU(threadInfo[i].pThread, threadInfo[i].type);
948  }
949  }
950 }
951 
952 int
953 Configuration::setRealtimeScheduler(NdbThread* pThread,
954  enum ThreadTypes type,
955  bool real_time,
956  bool init)
957 {
958  /*
959  We ignore thread characteristics on platforms where we cannot
960  determine the thread id.
961  */
962  if (!init || real_time)
963  {
964  int error_no;
965  if ((error_no = NdbThread_SetScheduler(pThread, real_time,
966  (type != MainThread))))
967  {
968  //Warning, no permission to set scheduler
969  return 1;
970  }
971  }
972  return 0;
973 }
974 
975 int
976 Configuration::setLockCPU(NdbThread * pThread,
977  enum ThreadTypes type)
978 {
979  int res = 0;
980  if (type != MainThread)
981  {
982  res = m_thr_config.do_bind_io(pThread);
983  }
984  else if (!NdbIsMultiThreaded())
985  {
986  BlockNumber list[] = { CMVMI };
987  res = m_thr_config.do_bind(pThread, list, 1);
988  }
989 
990  if (res != 0)
991  {
992  if (res > 0)
993  {
994  ndbout << "Locked to CPU ok" << endl;
995  return 0;
996  }
997  else
998  {
999  ndbout << "Failed to lock CPU, error_no = " << (-res) << endl;
1000  return 1;
1001  }
1002  }
1003 
1004  return 0;
1005 }
1006 
1007 Uint32
1008 Configuration::addThread(struct NdbThread* pThread, enum ThreadTypes type)
1009 {
1010  Uint32 i;
1011  NdbMutex_Lock(threadIdMutex);
1012  for (i = 0; i < threadInfo.size(); i++)
1013  {
1014  if (threadInfo[i].type == NotInUse)
1015  break;
1016  }
1017  if (i == threadInfo.size())
1018  {
1019  struct ThreadInfo tmp;
1020  threadInfo.push_back(tmp);
1021  }
1022  threadInfo[i].pThread = pThread;
1023  threadInfo[i].type = type;
1024  NdbMutex_Unlock(threadIdMutex);
1025  setRealtimeScheduler(pThread, type, _realtimeScheduler, TRUE);
1026  if (type != MainThread)
1027  {
1032  setLockCPU(pThread, type);
1033  }
1034  return i;
1035 }
1036 
1037 void
1038 Configuration::removeThreadId(Uint32 index)
1039 {
1040  NdbMutex_Lock(threadIdMutex);
1041  threadInfo[index].pThread = 0;
1042  threadInfo[index].type = NotInUse;
1043  NdbMutex_Unlock(threadIdMutex);
1044 }
1045 
1046 void
1047 Configuration::yield_main(Uint32 index, bool start)
1048 {
1049  if (_realtimeScheduler)
1050  {
1051  if (start)
1052  setRealtimeScheduler(threadInfo[index].pThread,
1053  threadInfo[index].type,
1054  FALSE,
1055  FALSE);
1056  else
1057  setRealtimeScheduler(threadInfo[index].pThread,
1058  threadInfo[index].type,
1059  TRUE,
1060  FALSE);
1061  }
1062 }
1063 
1064 void
1065 Configuration::initThreadArray()
1066 {
1067  NdbMutex_Lock(threadIdMutex);
1068  for (Uint32 i = 0; i < threadInfo.size(); i++)
1069  {
1070  threadInfo[i].pThread = 0;
1071  threadInfo[i].type = NotInUse;
1072  }
1073  NdbMutex_Unlock(threadIdMutex);
1074 }
1075 
1076 template class Vector<struct ThreadInfo>;
1077