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