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 #ifndef NDB_MGMAPI
27
28 #include <NdbTCP.h>
29 #include "ConfigInfo.hpp"
30 #include <mgmapi_config_parameters.h>
31 #include <ndb_limits.h>
32 #include "InitConfigFileParser.hpp"
33 #include <m_string.h>
34 #include <Bitmask.hpp>
35 #include <ndb_opts.h>
36 #include <ndb_version.h>
37
38 #else
39 #include "ConfigInfo.hpp"
40 #include <mgmapi_config_parameters.h>
41 #include <ndb_version.h>
42 #endif /* NDB_MGMAPI */
43
44 #define KEY_INTERNAL 0
45 #define MAX_INT_RNIL 0xfffffeff
46 #define MAX_INT32 0xffffffff
47 #define MAX_PORT_NO 65535
48
49 #define _STR_VALUE(x) #x
50 #define STR_VALUE(x) _STR_VALUE(x)
51
52 /****************************************************************************
53 * Section names
54 ****************************************************************************/
55
56 #define DB_TOKEN_PRINT "ndbd(DB)"
57 #define MGM_TOKEN_PRINT "ndb_mgmd(MGM)"
58 #define API_TOKEN_PRINT "mysqld(API)"
59
60 #define DB_TOKEN "DB"
61 #define MGM_TOKEN "MGM"
62 #define API_TOKEN "API"
63
64 #ifndef NDB_MGMAPI
65 const ConfigInfo::AliasPair
66 ConfigInfo::m_sectionNameAliases[]={
67 {API_TOKEN, "MYSQLD"},
68 {DB_TOKEN, "NDBD"},
69 {MGM_TOKEN, "NDB_MGMD"},
70 {0, 0}
71 };
72
73 const char*
74 ConfigInfo::m_sectionNames[]={
75 "SYSTEM",
76 "COMPUTER",
77
78 DB_TOKEN,
79 MGM_TOKEN,
80 API_TOKEN,
81
82 "TCP",
83 "SCI",
84 "SHM"
85 };
86 const int ConfigInfo::m_noOfSectionNames =
87 sizeof(m_sectionNames)/sizeof(char*);
88
89 /****************************************************************************
90 * Section Rules declarations
91 ****************************************************************************/
92 static bool transformComputer(InitConfigFileParser::Context & ctx, const char *);
93 static bool transformSystem(InitConfigFileParser::Context & ctx, const char *);
94 static bool transformNode(InitConfigFileParser::Context & ctx, const char *);
95 static bool checkConnectionSupport(InitConfigFileParser::Context & ctx, const char *);
96 static bool transformConnection(InitConfigFileParser::Context & ctx, const char *);
97 static bool uniqueConnection(InitConfigFileParser::Context & ctx, const char *);
98 static bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *);
99 static bool checkMandatory(InitConfigFileParser::Context & ctx, const char *);
100 static bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *);
101 static bool fixShmKey(InitConfigFileParser::Context & ctx, const char *);
102 static bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *);
103 static bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *);
104 static bool checkTCPConstraints(InitConfigFileParser::Context &, const char *);
105 static bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data);
106 static bool fixHostname(InitConfigFileParser::Context & ctx, const char * data);
107 static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data);
108 static bool fixDeprecated(InitConfigFileParser::Context & ctx, const char *);
109 static bool fixFileSystemPath(InitConfigFileParser::Context & ctx, const char * data);
110 static bool fixBackupDataDir(InitConfigFileParser::Context & ctx, const char * data);
111 static bool fixShmUniqueId(InitConfigFileParser::Context & ctx, const char * data);
112 static bool checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx, const char * data);
113 static bool checkThreadPrioSpec(InitConfigFileParser::Context & ctx, const char * data);
114 static bool checkThreadConfig(InitConfigFileParser::Context & ctx, const char * data);
115
116 const ConfigInfo::SectionRule
117 ConfigInfo::m_SectionRules[] = {
118 { "SYSTEM", transformSystem, 0 },
119 { "COMPUTER", transformComputer, 0 },
120
121 { DB_TOKEN, transformNode, 0 },
122 { API_TOKEN, transformNode, 0 },
123 { MGM_TOKEN, transformNode, 0 },
124
125 { MGM_TOKEN, fixShmUniqueId, 0 },
126
127 { "TCP", checkConnectionSupport, 0 },
128 { "SHM", checkConnectionSupport, 0 },
129 { "SCI", checkConnectionSupport, 0 },
130
131 { "TCP", transformConnection, 0 },
132 { "SHM", transformConnection, 0 },
133 { "SCI", transformConnection, 0 },
134
135 { DB_TOKEN, fixNodeHostname, 0 },
136 { API_TOKEN, fixNodeHostname, 0 },
137 { MGM_TOKEN, fixNodeHostname, 0 },
138
139 { "TCP", fixNodeId, "NodeId1" },
140 { "TCP", fixNodeId, "NodeId2" },
141 { "SHM", fixNodeId, "NodeId1" },
142 { "SHM", fixNodeId, "NodeId2" },
143 { "SCI", fixNodeId, "NodeId1" },
144 { "SCI", fixNodeId, "NodeId2" },
145
146 { "TCP", uniqueConnection, "TCP" },
147 { "SHM", uniqueConnection, "SHM" },
148 { "SCI", uniqueConnection, "SCI" },
149
150 { "TCP", fixHostname, "HostName1" },
151 { "TCP", fixHostname, "HostName2" },
152 { "SHM", fixHostname, "HostName1" },
153 { "SHM", fixHostname, "HostName2" },
154 { "SCI", fixHostname, "HostName1" },
155 { "SCI", fixHostname, "HostName2" },
156 { "SHM", fixHostname, "HostName1" },
157 { "SHM", fixHostname, "HostName2" },
158
159 { "TCP", fixPortNumber, 0 }, // has to come after fixHostName
160 { "SHM", fixPortNumber, 0 }, // has to come after fixHostName
161 { "SCI", fixPortNumber, 0 }, // has to come after fixHostName
162
163 { "*", applyDefaultValues, "user" },
164 { "*", fixDeprecated, 0 },
165 { "*", applyDefaultValues, "system" },
166
167 { "SHM", fixShmKey, 0 }, // has to come after apply default values
168
169 { DB_TOKEN, checkLocalhostHostnameMix, 0 },
170 { API_TOKEN, checkLocalhostHostnameMix, 0 },
171 { MGM_TOKEN, checkLocalhostHostnameMix, 0 },
172
173 { DB_TOKEN, fixFileSystemPath, 0 },
174 { DB_TOKEN, fixBackupDataDir, 0 },
175
176 { DB_TOKEN, checkDbConstraints, 0 },
177 { DB_TOKEN, checkThreadConfig, 0 },
178
179 { API_TOKEN, checkThreadPrioSpec, 0 },
180 { MGM_TOKEN, checkThreadPrioSpec, 0 },
181
182 { "TCP", checkConnectionConstraints, 0 },
183 { "SHM", checkConnectionConstraints, 0 },
184 { "SCI", checkConnectionConstraints, 0 },
185
186 { "TCP", checkTCPConstraints, "HostName1" },
187 { "TCP", checkTCPConstraints, "HostName2" },
188 { "SCI", checkTCPConstraints, "HostName1" },
189 { "SCI", checkTCPConstraints, "HostName2" },
190 { "SHM", checkTCPConstraints, "HostName1" },
191 { "SHM", checkTCPConstraints, "HostName2" },
192
193 { "*", checkMandatory, 0 }
194 };
195 const int ConfigInfo::m_NoOfRules = sizeof(m_SectionRules)/sizeof(SectionRule);
196
197 /****************************************************************************
198 * Config Rules declarations
199 ****************************************************************************/
200 static bool add_system_section(Vector<ConfigInfo::ConfigRuleSection>§ions,
201 struct InitConfigFileParser::Context &ctx,
202 const char * rule_data);
203 static bool sanity_checks(Vector<ConfigInfo::ConfigRuleSection>§ions,
204 struct InitConfigFileParser::Context &ctx,
205 const char * rule_data);
206 static bool add_node_connections(Vector<ConfigInfo::ConfigRuleSection>§ions,
207 struct InitConfigFileParser::Context &ctx,
208 const char * rule_data);
209 static bool set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection>§ions,
210 struct InitConfigFileParser::Context &ctx,
211 const char * rule_data);
212 static bool check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>§ions,
213 struct InitConfigFileParser::Context &ctx,
214 const char * rule_data);
215 static bool check_mutually_exclusive(Vector<ConfigInfo::ConfigRuleSection>§ions,
216 struct InitConfigFileParser::Context &ctx,
217 const char * rule_data);
218
219
220 static bool saveSectionsInConfigValues(Vector<ConfigInfo::ConfigRuleSection>&,
221 struct InitConfigFileParser::Context &,
222 const char * rule_data);
223
224 const ConfigInfo::ConfigRule
225 ConfigInfo::m_ConfigRules[] = {
226 { add_system_section, 0 },
227 { sanity_checks, 0 },
228 { add_node_connections, 0 },
229 { set_connection_priorities, 0 },
230 { check_node_vs_replicas, 0 },
231 { check_mutually_exclusive, 0 },
232 { saveSectionsInConfigValues, "SYSTEM,Node,Connection" },
233 { 0, 0 }
234 };
235
236 struct DeprecationTransform {
237 const char * m_section;
238 const char * m_oldName;
239 const char * m_newName;
240 double m_add;
241 double m_mul;
242 };
243
244 static
245 const DeprecationTransform f_deprecation[] = {
246 { DB_TOKEN, "Discless", "Diskless", 0, 1 },
247 { DB_TOKEN, "Id", "NodeId", 0, 1 },
248 { API_TOKEN, "Id", "NodeId", 0, 1 },
249 { MGM_TOKEN, "Id", "NodeId", 0, 1 },
250 { 0, 0, 0, 0, 0}
251 };
252 #endif /* NDB_MGMAPI */
253
254 static
255 const ConfigInfo::Typelib arbit_method_typelib[] = {
256 { "Disabled", ARBIT_METHOD_DISABLED },
257 { "Default", ARBIT_METHOD_DEFAULT },
258 { "WaitExternal", ARBIT_METHOD_WAITEXTERNAL },
259 { 0, 0 }
260 };
261
262 static
263 const ConfigInfo::Typelib default_operation_redo_problem_action_typelib [] = {
264 { "abort", OPERATION_REDO_PROBLEM_ACTION_ABORT },
265 { "queue", OPERATION_REDO_PROBLEM_ACTION_QUEUE },
266 { 0, 0 }
267 };
268
269 /**
270 * The default constructors create objects with suitable values for the
271 * configuration parameters.
272 *
273 * Some are however given the value MANDATORY which means that the value
274 * must be specified in the configuration file.
275 *
276 * Min and max values are also given for some parameters.
277 * - Attr1: Name in file (initial config file)
278 * - Attr2: Name in prop (properties object)
279 * - Attr3: Name of Section (in init config file)
280 * - Attr4: Updateable
281 * - Attr5: Type of parameter (INT or BOOL)
282 * - Attr6: Default Value (number only)
283 * - Attr7: Min value
284 * - Attr8: Max value
285 *
286 * Parameter constraints are coded in file Config.cpp.
287 *
288 * *******************************************************************
289 * Parameters used under development should be marked "NOTIMPLEMENTED"
290 * *******************************************************************
291 */
292
293 const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
294
295 /****************************************************************************
296 * COMPUTER
297 ***************************************************************************/
298 {
299 KEY_INTERNAL,
300 "COMPUTER",
301 "COMPUTER",
302 "Computer section",
303 ConfigInfo::CI_INTERNAL,
304 false,
305 ConfigInfo::CI_SECTION,
306 0,
307 0, 0 },
308
309 {
310 KEY_INTERNAL,
311 "Id",
312 "COMPUTER",
313 "Name of computer",
314 ConfigInfo::CI_USED,
315 false,
316 ConfigInfo::CI_STRING,
317 MANDATORY,
318 0, 0 },
319
320 {
321 KEY_INTERNAL,
322 "HostName",
323 "COMPUTER",
324 "Hostname of computer (e.g. mysql.com)",
325 ConfigInfo::CI_USED,
326 false,
327 ConfigInfo::CI_STRING,
328 MANDATORY,
329 0, 0 },
330
331 {
332 KEY_INTERNAL,
333 "ByteOrder",
334 "COMPUTER",
335 0, // No new parameter to use instead of deprecated
336 ConfigInfo::CI_DEPRECATED,
337 false,
338 ConfigInfo::CI_STRING,
339 0,
340 0,
341 0 },
342
343 /****************************************************************************
344 * SYSTEM
345 ***************************************************************************/
346 {
347 CFG_SECTION_SYSTEM,
348 "SYSTEM",
349 "SYSTEM",
350 "System section",
351 ConfigInfo::CI_USED,
352 false,
353 ConfigInfo::CI_SECTION,
354 (const char *)CFG_SECTION_SYSTEM,
355 0, 0 },
356
357 {
358 CFG_SYS_NAME,
359 "Name",
360 "SYSTEM",
361 "Name of system (NDB Cluster)",
362 ConfigInfo::CI_USED,
363 false,
364 ConfigInfo::CI_STRING,
365 MANDATORY,
366 0, 0 },
367
368 {
369 CFG_SYS_PRIMARY_MGM_NODE,
370 "PrimaryMGMNode",
371 "SYSTEM",
372 "Node id of Primary "MGM_TOKEN_PRINT" node",
373 ConfigInfo::CI_USED,
374 false,
375 ConfigInfo::CI_INT,
376 "0",
377 "0",
378 STR_VALUE(MAX_INT_RNIL) },
379
380 /***************************************************************************
381 * DB
382 ***************************************************************************/
383
384 {
385 CFG_SYS_CONFIG_GENERATION,
386 "ConfigGenerationNumber",
387 "SYSTEM",
388 "Configuration generation number",
389 ConfigInfo::CI_USED,
390 false,
391 ConfigInfo::CI_INT,
392 "0",
393 "0",
394 STR_VALUE(MAX_INT_RNIL) },
395
396 /***************************************************************************
397 * DB
398 ***************************************************************************/
399 {
400 CFG_SECTION_NODE,
401 DB_TOKEN,
402 DB_TOKEN,
403 "[DB] section",
404 ConfigInfo::CI_USED,
405 false,
406 ConfigInfo::CI_SECTION,
407 (const char *)NODE_TYPE_DB,
408 0, 0
409 },
410
411 {
412 CFG_DB_SUBSCRIPTIONS,
413 "MaxNoOfSubscriptions",
414 DB_TOKEN,
415 "Max no of subscriptions (default 0 == MaxNoOfTables)",
416 ConfigInfo::CI_USED,
417 false,
418 ConfigInfo::CI_INT,
419 "0",
420 "0",
421 STR_VALUE(MAX_INT_RNIL) },
422
423 {
424 CFG_DB_SUBSCRIBERS,
425 "MaxNoOfSubscribers",
426 DB_TOKEN,
427 "Max no of subscribers (default 0 == 2 * MaxNoOfTables)",
428 ConfigInfo::CI_USED,
429 false,
430 ConfigInfo::CI_INT,
431 "0",
432 "0",
433 STR_VALUE(MAX_INT_RNIL) },
434
435 {
436 CFG_DB_SUB_OPERATIONS,
437 "MaxNoOfConcurrentSubOperations",
438 DB_TOKEN,
439 "Max no of concurrent subscriber operations",
440 ConfigInfo::CI_USED,
441 false,
442 ConfigInfo::CI_INT,
443 "256",
444 "0",
445 STR_VALUE(MAX_INT_RNIL) },
446
447 {
448 KEY_INTERNAL,
449 "TcpBind_INADDR_ANY",
450 DB_TOKEN,
451 "Bind IP_ADDR_ANY so that connections can be made from anywhere (for autogenerated connections)",
452 ConfigInfo::CI_USED,
453 false,
454 ConfigInfo::CI_BOOL,
455 "false",
456 "false",
457 "true"},
458
459 {
460 CFG_NODE_HOST,
461 "HostName",
462 DB_TOKEN,
463 "Name of computer for this node",
464 ConfigInfo::CI_USED,
465 false,
466 ConfigInfo::CI_STRING,
467 "localhost",
468 0, 0 },
469
470 {
471 CFG_NODE_SYSTEM,
472 "System",
473 DB_TOKEN,
474 "Name of system for this node",
475 ConfigInfo::CI_INTERNAL,
476 false,
477 ConfigInfo::CI_STRING,
478 0,
479 0, 0 },
480
481 {
482 KEY_INTERNAL,
483 "Id",
484 DB_TOKEN,
485 "NodeId", // Name of new parameter to use instead of deprecated
486 ConfigInfo::CI_DEPRECATED,
487 false,
488 ConfigInfo::CI_INT,
489 MANDATORY,
490 "1",
491 STR_VALUE(MAX_DATA_NODE_ID) },
492
493 {
494 CFG_NODE_ID,
495 "NodeId",
496 DB_TOKEN,
497 "Number identifying the database node ("DB_TOKEN_PRINT")",
498 ConfigInfo::CI_USED,
499 false,
500 ConfigInfo::CI_INT,
501 MANDATORY,
502 "1",
503 STR_VALUE(MAX_DATA_NODE_ID) },
504
505 {
506 KEY_INTERNAL,
507 "ServerPort",
508 DB_TOKEN,
509 "Port used to setup transporter for incoming connections from API nodes",
510 ConfigInfo::CI_USED,
511 false,
512 ConfigInfo::CI_INT,
513 0,
514 "1",
515 STR_VALUE(MAX_PORT_NO) },
516
517 {
518 CFG_DB_NO_REPLICAS,
519 "NoOfReplicas",
520 DB_TOKEN,
521 "Number of copies of all data in the database (1-4)",
522 ConfigInfo::CI_USED,
523 CI_RESTART_SYSTEM | CI_RESTART_INITIAL,
524 ConfigInfo::CI_INT,
525 "2",
526 "1",
527 "4" },
528
529 {
530 CFG_DB_NO_ATTRIBUTES,
531 "MaxNoOfAttributes",
532 DB_TOKEN,
533 "Total number of attributes stored in database. I.e. sum over all tables",
534 ConfigInfo::CI_USED,
535 false,
536 ConfigInfo::CI_INT,
537 "1000",
538 "32",
539 STR_VALUE(MAX_INT_RNIL) },
540
541 {
542 CFG_DB_NO_TABLES,
543 "MaxNoOfTables",
544 DB_TOKEN,
545 "Total number of tables stored in the database",
546 ConfigInfo::CI_USED,
547 false,
548 ConfigInfo::CI_INT,
549 "128",
550 "8",
551 STR_VALUE(NDB_MAX_TABLES) },
552
553 {
554 CFG_DB_NO_ORDERED_INDEXES,
555 "MaxNoOfOrderedIndexes",
556 DB_TOKEN,
557 "Total number of ordered indexes that can be defined in the system",
558 ConfigInfo::CI_USED,
559 false,
560 ConfigInfo::CI_INT,
561 "128",
562 "0",
563 STR_VALUE(MAX_INT_RNIL) },
564
565 {
566 CFG_DB_NO_UNIQUE_HASH_INDEXES,
567 "MaxNoOfUniqueHashIndexes",
568 DB_TOKEN,
569 "Total number of unique hash indexes that can be defined in the system",
570 ConfigInfo::CI_USED,
571 false,
572 ConfigInfo::CI_INT,
573 "64",
574 "0",
575 STR_VALUE(MAX_INT_RNIL) },
576
577 {
578 CFG_DB_NO_INDEXES,
579 "MaxNoOfIndexes",
580 DB_TOKEN,
581 // The name of new parameter to use instead of deprecated
582 "MaxNoOfOrderedIndexes or MaxNoOfUniqueHashIndexes",
583 ConfigInfo::CI_DEPRECATED,
584 false,
585 ConfigInfo::CI_INT,
586 "128",
587 "0",
588 STR_VALUE(MAX_INT_RNIL) },
589
590 {
591 CFG_DB_NO_INDEX_OPS,
592 "MaxNoOfConcurrentIndexOperations",
593 DB_TOKEN,
594 "Total number of index operations that can execute simultaneously on one "DB_TOKEN_PRINT" node",
595 ConfigInfo::CI_USED,
596 false,
597 ConfigInfo::CI_INT,
598 "8K",
599 "0",
600 STR_VALUE(MAX_INT_RNIL)
601 },
602
603 {
604 CFG_DB_NO_TRIGGERS,
605 "MaxNoOfTriggers",
606 DB_TOKEN,
607 "Total number of triggers that can be defined in the system",
608 ConfigInfo::CI_USED,
609 false,
610 ConfigInfo::CI_INT,
611 "768",
612 "0",
613 STR_VALUE(MAX_INT_RNIL) },
614
615 {
616 CFG_DB_NO_TRIGGER_OPS,
617 "MaxNoOfFiredTriggers",
618 DB_TOKEN,
619 "Total number of triggers that can fire simultaneously in one "DB_TOKEN_PRINT" node",
620 ConfigInfo::CI_USED,
621 false,
622 ConfigInfo::CI_INT,
623 "4000",
624 "0",
625 STR_VALUE(MAX_INT_RNIL) },
626
627 {
628 KEY_INTERNAL,
629 "ExecuteOnComputer",
630 DB_TOKEN,
631 "String referencing an earlier defined COMPUTER",
632 ConfigInfo::CI_USED,
633 false,
634 ConfigInfo::CI_STRING,
635 0,
636 0, 0 },
637
638 {
639 CFG_DB_NO_SAVE_MSGS,
640 "MaxNoOfSavedMessages",
641 DB_TOKEN,
642 "Max number of error messages in error log and max number of trace files",
643 ConfigInfo::CI_USED,
644 0,
645 ConfigInfo::CI_INT,
646 "25",
647 "0",
648 STR_VALUE(MAX_INT_RNIL) },
649
650 {
651 CFG_DB_EXECUTE_LOCK_CPU,
652 "LockExecuteThreadToCPU",
653 DB_TOKEN,
654 "CPU list indicating which CPU will run the execution thread(s)",
655 ConfigInfo::CI_USED,
656 0,
657 ConfigInfo::CI_BITMASK,
658 0,
659 0,
660 "65535"
661 },
662
663 {
664 CFG_DB_MAINT_LOCK_CPU,
665 "LockMaintThreadsToCPU",
666 DB_TOKEN,
667 "CPU ID indicating which CPU will run the maintenance threads",
668 ConfigInfo::CI_USED,
669 0,
670 ConfigInfo::CI_INT,
671 0,
672 "0",
673 "65535" },
674
675 {
676 CFG_DB_REALTIME_SCHEDULER,
677 "RealtimeScheduler",
678 DB_TOKEN,
679 "If yes, then NDB Cluster threads will be scheduled as real-time threads",
680 ConfigInfo::CI_USED,
681 0,
682 ConfigInfo::CI_BOOL,
683 "false",
684 "false",
685 "true" },
686
687 {
688 CFG_DB_MEMLOCK,
689 "LockPagesInMainMemory",
690 DB_TOKEN,
691 "If set to yes, then NDB Cluster data will not be swapped out to disk",
692 ConfigInfo::CI_USED,
693 0,
694 ConfigInfo::CI_INT,
695 "0",
696 "0",
697 "2" },
698
699 {
700 CFG_DB_WATCHDOG_INTERVAL,
701 "TimeBetweenWatchDogCheck",
702 DB_TOKEN,
703 "Time between execution checks inside a database node",
704 ConfigInfo::CI_USED,
705 0,
706 ConfigInfo::CI_INT,
707 "6000",
708 "70",
709 STR_VALUE(MAX_INT_RNIL) },
710
711 {
712 CFG_DB_SCHED_EXEC_TIME,
713 "SchedulerExecutionTimer",
714 DB_TOKEN,
715 "Number of microseconds to execute in scheduler before sending",
716 ConfigInfo::CI_USED,
717 false,
718 ConfigInfo::CI_INT,
719 "50",
720 "0",
721 "11000" },
722
723 {
724 CFG_DB_SCHED_SPIN_TIME,
725 "SchedulerSpinTimer",
726 DB_TOKEN,
727 "Number of microseconds to execute in scheduler before sleeping",
728 ConfigInfo::CI_USED,
729 false,
730 ConfigInfo::CI_INT,
731 "0",
732 "0",
733 "500" },
734
735 {
736 CFG_DB_WATCHDOG_INTERVAL_INITIAL,
737 "TimeBetweenWatchDogCheckInitial",
738 DB_TOKEN,
739 "Time between execution checks inside a database node in the early start phases when memory is allocated",
740 ConfigInfo::CI_USED,
741 0,
742 ConfigInfo::CI_INT,
743 "6000",
744 "70",
745 STR_VALUE(MAX_INT_RNIL) },
746
747 {
748 CFG_DB_STOP_ON_ERROR,
749 "StopOnError",
750 DB_TOKEN,
751 "If set to N, "DB_TOKEN_PRINT" automatically restarts/recovers in case of node failure",
752 ConfigInfo::CI_USED,
753 0,
754 ConfigInfo::CI_BOOL,
755 "true",
756 "false",
757 "true" },
758
759 {
760 CFG_DB_STOP_ON_ERROR_INSERT,
761 "RestartOnErrorInsert",
762 DB_TOKEN,
763 "See src/kernel/vm/Emulator.hpp NdbRestartType for details",
764 ConfigInfo::CI_INTERNAL,
765 0,
766 ConfigInfo::CI_INT,
767 "2",
768 "0",
769 "4" },
770
771 {
772 CFG_DB_NO_OPS,
773 "MaxNoOfConcurrentOperations",
774 DB_TOKEN,
775 "Max number of operation records in transaction coordinator",
776 ConfigInfo::CI_USED,
777 false,
778 ConfigInfo::CI_INT,
779 "32k",
780 "32",
781 STR_VALUE(MAX_INT_RNIL) },
782
783 {
784 CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION,
785 "MaxDMLOperationsPerTransaction",
786 DB_TOKEN,
787 "Max DML-operations in one transaction (0 == no limit)",
788 ConfigInfo::CI_USED,
789 false,
790 ConfigInfo::CI_INT,
791 STR_VALUE(MAX_INT32),
792 "32",
793 STR_VALUE(MAX_INT32)
794 },
795
796 {
797 CFG_DB_NO_LOCAL_OPS,
798 "MaxNoOfLocalOperations",
799 DB_TOKEN,
800 "Max number of operation records defined in the local storage node",
801 ConfigInfo::CI_USED,
802 false,
803 ConfigInfo::CI_INT,
804 0,
805 "32",
806 STR_VALUE(MAX_INT_RNIL) },
807
808 {
809 CFG_DB_NO_LOCAL_SCANS,
810 "MaxNoOfLocalScans",
811 DB_TOKEN,
812 "Max number of fragment scans in parallel in the local storage node",
813 ConfigInfo::CI_USED,
814 false,
815 ConfigInfo::CI_INT,
816 0,
817 "32",
818 STR_VALUE(MAX_INT_RNIL) },
819
820 {
821 CFG_DB_BATCH_SIZE,
822 "BatchSizePerLocalScan",
823 DB_TOKEN,
824 "Used to calculate the number of lock records for scan with hold lock",
825 ConfigInfo::CI_USED,
826 false,
827 ConfigInfo::CI_INT,
828 STR_VALUE(DEF_BATCH_SIZE),
829 "1",
830 STR_VALUE(MAX_PARALLEL_OP_PER_SCAN) },
831
832 {
833 CFG_DB_NO_TRANSACTIONS,
834 "MaxNoOfConcurrentTransactions",
835 DB_TOKEN,
836 "Max number of transaction executing concurrently on the "DB_TOKEN_PRINT" node",
837 ConfigInfo::CI_USED,
838 false,
839 ConfigInfo::CI_INT,
840 "4096",
841 "32",
842 STR_VALUE(MAX_INT_RNIL) },
843
844 {
845 CFG_DB_NO_SCANS,
846 "MaxNoOfConcurrentScans",
847 DB_TOKEN,
848 "Max number of scans executing concurrently on the "DB_TOKEN_PRINT" node",
849 ConfigInfo::CI_USED,
850 false,
851 ConfigInfo::CI_INT,
852 "256",
853 "2",
854 "500" },
855
856 {
857 CFG_DB_TRANS_BUFFER_MEM,
858 "TransactionBufferMemory",
859 DB_TOKEN,
860 "Dynamic buffer space (in bytes) for key and attribute data allocated for each "DB_TOKEN_PRINT" node",
861 ConfigInfo::CI_USED,
862 false,
863 ConfigInfo::CI_INT,
864 "1M",
865 "1K",
866 STR_VALUE(MAX_INT_RNIL) },
867
868 {
869 CFG_DB_INDEX_MEM,
870 "IndexMemory",
871 DB_TOKEN,
872 "Number bytes on each "DB_TOKEN_PRINT" node allocated for storing indexes",
873 ConfigInfo::CI_USED,
874 false,
875 ConfigInfo::CI_INT64,
876 "18M",
877 "1M",
878 "1024G" },
879
880 {
881 CFG_DB_DATA_MEM,
882 "DataMemory",
883 DB_TOKEN,
884 "Number bytes on each "DB_TOKEN_PRINT" node allocated for storing data",
885 ConfigInfo::CI_USED,
886 false,
887 ConfigInfo::CI_INT64,
888 "80M",
889 "1M",
890 "1024G" },
891
892 {
893 CFG_DB_UNDO_INDEX_BUFFER,
894 "UndoIndexBuffer",
895 DB_TOKEN,
896 "Number bytes on each "DB_TOKEN_PRINT" node allocated for writing UNDO logs for index part",
897 ConfigInfo::CI_USED,
898 false,
899 ConfigInfo::CI_INT,
900 "2M",
901 "1M",
902 STR_VALUE(MAX_INT_RNIL)},
903
904 {
905 CFG_DB_UNDO_DATA_BUFFER,
906 "UndoDataBuffer",
907 DB_TOKEN,
908 "Number bytes on each "DB_TOKEN_PRINT" node allocated for writing UNDO logs for data part",
909 ConfigInfo::CI_USED,
910 false,
911 ConfigInfo::CI_INT,
912 "16M",
913 "1M",
914 STR_VALUE(MAX_INT_RNIL)},
915
916 {
917 CFG_DB_REDO_BUFFER,
918 "RedoBuffer",
919 DB_TOKEN,
920 "Number bytes on each "DB_TOKEN_PRINT" node allocated for writing REDO logs",
921 ConfigInfo::CI_USED,
922 false,
923 ConfigInfo::CI_INT,
924 "32M",
925 "1M",
926 STR_VALUE(MAX_INT_RNIL)},
927
928 {
929 CFG_DB_LONG_SIGNAL_BUFFER,
930 "LongMessageBuffer",
931 DB_TOKEN,
932 "Number bytes on each "DB_TOKEN_PRINT" node allocated for internal long messages",
933 ConfigInfo::CI_USED,
934 false,
935 ConfigInfo::CI_INT,
936 "4M",
937 "512k",
938 STR_VALUE(MAX_INT_RNIL)},
939
940 {
941 CFG_DB_DISK_PAGE_BUFFER_MEMORY,
942 "DiskPageBufferMemory",
943 DB_TOKEN,
944 "Number bytes on each "DB_TOKEN_PRINT" node allocated for disk page buffer cache",
945 ConfigInfo::CI_USED,
946 false,
947 ConfigInfo::CI_INT64,
948 "64M",
949 "4M",
950 "1024G" },
951
952 {
953 CFG_DB_SGA,
954 "SharedGlobalMemory",
955 DB_TOKEN,
956 "Total number bytes on each "DB_TOKEN_PRINT" node allocated for any use",
957 ConfigInfo::CI_USED,
958 false,
959 ConfigInfo::CI_INT64,
960 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
961 "20M",
962 #else
963 "128M",
964 #endif
965 "0",
966 "65536G" }, // 32k pages * 32-bit i value
967
968 {
969 CFG_DB_START_PARTIAL_TIMEOUT,
970 "StartPartialTimeout",
971 DB_TOKEN,
972 "Time to wait before trying to start wo/ all nodes. 0=Wait forever",
973 ConfigInfo::CI_USED,
974 0,
975 ConfigInfo::CI_INT,
976 "30000",
977 "0",
978 STR_VALUE(MAX_INT_RNIL) },
979
980 {
981 CFG_DB_START_PARTITION_TIMEOUT,
982 "StartPartitionedTimeout",
983 DB_TOKEN,
984 "Time to wait before trying to start partitioned. 0=Wait forever",
985 ConfigInfo::CI_USED,
986 0,
987 ConfigInfo::CI_INT,
988 "60000",
989 "0",
990 STR_VALUE(MAX_INT_RNIL) },
991
992 {
993 CFG_DB_START_FAILURE_TIMEOUT,
994 "StartFailureTimeout",
995 DB_TOKEN,
996 "Time to wait before terminating. 0=Wait forever",
997 ConfigInfo::CI_USED,
998 0,
999 ConfigInfo::CI_INT,
1000 "0",
1001 "0",
1002 STR_VALUE(MAX_INT_RNIL) },
1003
1004 {
1005 CFG_DB_START_NO_NODEGROUP_TIMEOUT,
1006 "StartNoNodegroupTimeout",
1007 DB_TOKEN,
1008 "Time to wait for nodes wo/ nodegroup before trying to start (0=forever)",
1009 ConfigInfo::CI_USED,
1010 0,
1011 ConfigInfo::CI_INT,
1012 "15000",
1013 "0",
1014 STR_VALUE(MAX_INT_RNIL) },
1015
1016 {
1017 CFG_DB_HEARTBEAT_INTERVAL,
1018 "HeartbeatIntervalDbDb",
1019 DB_TOKEN,
1020 "Time between "DB_TOKEN_PRINT"-"DB_TOKEN_PRINT" heartbeats. "DB_TOKEN_PRINT" considered dead after 3 missed HBs",
1021 ConfigInfo::CI_USED,
1022 0,
1023 ConfigInfo::CI_INT,
1024 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
1025 "1500",
1026 #else
1027 "5000",
1028 #endif
1029 "10",
1030 STR_VALUE(MAX_INT_RNIL) },
1031
1032 {
1033 CFG_DB_CONNECT_CHECK_DELAY,
1034 "ConnectCheckIntervalDelay",
1035 DB_TOKEN,
1036 "Time between "DB_TOKEN_PRINT" connectivity check stages. "DB_TOKEN_PRINT" considered suspect after 1 and dead after 2 intervals.",
1037 ConfigInfo::CI_USED,
1038 0,
1039 ConfigInfo::CI_INT,
1040 "0",
1041 "0",
1042 STR_VALUE(MAX_INT_RNIL) },
1043
1044 {
1045 CFG_DB_API_HEARTBEAT_INTERVAL,
1046 "HeartbeatIntervalDbApi",
1047 DB_TOKEN,
1048 "Time between "API_TOKEN_PRINT"-"DB_TOKEN_PRINT" heartbeats. "API_TOKEN_PRINT" connection closed after 3 missed HBs",
1049 ConfigInfo::CI_USED,
1050 0,
1051 ConfigInfo::CI_INT,
1052 "1500",
1053 "100",
1054 STR_VALUE(MAX_INT_RNIL) },
1055
1056 {
1057 CFG_DB_LCP_INTERVAL,
1058 "TimeBetweenLocalCheckpoints",
1059 DB_TOKEN,
1060 "Time between taking snapshots of the database (expressed in 2log of bytes)",
1061 ConfigInfo::CI_USED,
1062 0,
1063 ConfigInfo::CI_INT,
1064 "20",
1065 "0",
1066 "31" },
1067
1068 {
1069 CFG_DB_GCP_INTERVAL,
1070 "TimeBetweenGlobalCheckpoints",
1071 DB_TOKEN,
1072 "Time between doing group commit of transactions to disk",
1073 ConfigInfo::CI_USED,
1074 0,
1075 ConfigInfo::CI_INT,
1076 "2000",
1077 "20",
1078 "32000" },
1079
1080 {
1081 CFG_DB_MICRO_GCP_INTERVAL,
1082 "TimeBetweenEpochs",
1083 DB_TOKEN,
1084 "Time between epochs (syncronization used e.g for replication)",
1085 ConfigInfo::CI_USED,
1086 0,
1087 ConfigInfo::CI_INT,
1088 "100",
1089 "0",
1090 "32000" },
1091
1092 {
1093 CFG_DB_MICRO_GCP_TIMEOUT,
1094 "TimeBetweenEpochsTimeout",
1095 DB_TOKEN,
1096 "Timeout for time between epochs. Exceeding will cause node shutdown.",
1097 ConfigInfo::CI_USED,
1098 0,
1099 ConfigInfo::CI_INT,
1100 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
1101 "4000",
1102 #else
1103 "0",
1104 #endif
1105 "0",
1106 "256000" },
1107
1108 {
1109 CFG_DB_MAX_BUFFERED_EPOCHS,
1110 "MaxBufferedEpochs",
1111 DB_TOKEN,
1112 "Allowed numbered of epochs that a subscribing node can lag behind (unprocessed epochs). Exceeding will cause lagging subscribers to be disconnected.",
1113 ConfigInfo::CI_USED,
1114 0,
1115 ConfigInfo::CI_INT,
1116 "100",
1117 "0",
1118 "100000" },
1119
1120 {
1121 CFG_DB_NO_REDOLOG_FILES,
1122 "NoOfFragmentLogFiles",
1123 DB_TOKEN,
1124 "No of 16 Mbyte Redo log files in each of 4 file sets belonging to "DB_TOKEN_PRINT" node",
1125 ConfigInfo::CI_USED,
1126 CI_RESTART_INITIAL,
1127 ConfigInfo::CI_INT,
1128 "16",
1129 "3",
1130 STR_VALUE(MAX_INT_RNIL) },
1131
1132 {
1133 CFG_DB_REDOLOG_FILE_SIZE,
1134 "FragmentLogFileSize",
1135 DB_TOKEN,
1136 "Size of each Redo log file",
1137 ConfigInfo::CI_USED,
1138 CI_RESTART_INITIAL,
1139 ConfigInfo::CI_INT,
1140 "16M",
1141 "4M",
1142 "1G" },
1143
1144 {
1145 CFG_DB_INIT_REDO,
1146 "InitFragmentLogFiles",
1147 DB_TOKEN,
1148 "Initialize fragment logfiles (sparse/full)",
1149 ConfigInfo::CI_USED,
1150 CI_RESTART_INITIAL,
1151 ConfigInfo::CI_STRING,
1152 0,
1153 0, 0 },
1154
1155 {
1156 CFG_DB_THREAD_POOL,
1157 "DiskIOThreadPool",
1158 DB_TOKEN,
1159 "No of unbound threads for file access (currently only for DD)",
1160 ConfigInfo::CI_USED,
1161 false,
1162 ConfigInfo::CI_INT,
1163 "2",
1164 "0",
1165 STR_VALUE(MAX_INT_RNIL) },
1166
1167 {
1168 CFG_DB_MAX_OPEN_FILES,
1169 "MaxNoOfOpenFiles",
1170 DB_TOKEN,
1171 "Max number of files open per "DB_TOKEN_PRINT" node.(One thread is created per file)",
1172 ConfigInfo::CI_USED,
1173 false,
1174 ConfigInfo::CI_INT,
1175 0,
1176 "20",
1177 STR_VALUE(MAX_INT_RNIL) },
1178
1179 {
1180 CFG_DB_INITIAL_OPEN_FILES,
1181 "InitialNoOfOpenFiles",
1182 DB_TOKEN,
1183 "Initial number of files open per "DB_TOKEN_PRINT" node.(One thread is created per file)",
1184 ConfigInfo::CI_USED,
1185 false,
1186 ConfigInfo::CI_INT,
1187 "27",
1188 "20",
1189 STR_VALUE(MAX_INT_RNIL) },
1190
1191 {
1192 CFG_DB_TRANSACTION_CHECK_INTERVAL,
1193 "TimeBetweenInactiveTransactionAbortCheck",
1194 DB_TOKEN,
1195 "Time between inactive transaction checks",
1196 ConfigInfo::CI_USED,
1197 0,
1198 ConfigInfo::CI_INT,
1199 "1000",
1200 "1000",
1201 STR_VALUE(MAX_INT_RNIL) },
1202
1203 {
1204 CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
1205 "TransactionInactiveTimeout",
1206 DB_TOKEN,
1207 "Time application can wait before executing another transaction part (ms).\n"
1208 "This is the time the transaction coordinator waits for the application\n"
1209 "to execute or send another part (query, statement) of the transaction.\n"
1210 "If the application takes too long time, the transaction gets aborted.\n"
1211 "Timeout set to 0 means that we don't timeout at all on application wait.",
1212 ConfigInfo::CI_USED,
1213 0,
1214 ConfigInfo::CI_INT,
1215 STR_VALUE(MAX_INT_RNIL),
1216 "0",
1217 STR_VALUE(MAX_INT_RNIL) },
1218
1219 {
1220 CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
1221 "TransactionDeadlockDetectionTimeout",
1222 DB_TOKEN,
1223 "Time transaction can be executing in a DB node (ms).\n"
1224 "This is the time the transaction coordinator waits for each database node\n"
1225 "of the transaction to execute a request. If the database node takes too\n"
1226 "long time, the transaction gets aborted.",
1227 ConfigInfo::CI_USED,
1228 0,
1229 ConfigInfo::CI_INT,
1230 "1200",
1231 "50",
1232 STR_VALUE(MAX_INT_RNIL) },
1233
1234 {
1235 CFG_DB_LCP_DISC_PAGES_TUP_SR,
1236 "NoOfDiskPagesToDiskDuringRestartTUP",
1237 DB_TOKEN,
1238 "DiskCheckpointSpeedSr", // The new parameter name to use
1239 ConfigInfo::CI_DEPRECATED,
1240 0,
1241 ConfigInfo::CI_INT,
1242 "40",
1243 "1",
1244 STR_VALUE(MAX_INT_RNIL) },
1245
1246 {
1247 CFG_DB_LCP_DISC_PAGES_TUP,
1248 "NoOfDiskPagesToDiskAfterRestartTUP",
1249 DB_TOKEN,
1250 "DiskCheckpointSpeed", // The new parameter name to use
1251 ConfigInfo::CI_DEPRECATED,
1252 0,
1253 ConfigInfo::CI_INT,
1254 "40",
1255 "1",
1256 STR_VALUE(MAX_INT_RNIL) },
1257
1258 {
1259 CFG_DB_LCP_DISC_PAGES_ACC_SR,
1260 "NoOfDiskPagesToDiskDuringRestartACC",
1261 DB_TOKEN,
1262 "DiskCheckpointSpeedSr", // The new parameter name to use
1263 ConfigInfo::CI_DEPRECATED,
1264 0,
1265 ConfigInfo::CI_INT,
1266 "20",
1267 "1",
1268 STR_VALUE(MAX_INT_RNIL) },
1269
1270 {
1271 CFG_DB_LCP_DISC_PAGES_ACC,
1272 "NoOfDiskPagesToDiskAfterRestartACC",
1273 DB_TOKEN,
1274 "DiskCheckpointSpeed",
1275 ConfigInfo::CI_DEPRECATED, // The new parameter name to use
1276 0,
1277 ConfigInfo::CI_INT,
1278 "20",
1279 "1",
1280 STR_VALUE(MAX_INT_RNIL) },
1281
1282
1283 {
1284 CFG_DB_DISCLESS,
1285 "Diskless",
1286 DB_TOKEN,
1287 "Run wo/ disk",
1288 ConfigInfo::CI_USED,
1289 CI_RESTART_INITIAL | CI_RESTART_SYSTEM,
1290 ConfigInfo::CI_BOOL,
1291 "false",
1292 "false",
1293 "true"},
1294
1295 {
1296 KEY_INTERNAL,
1297 "Discless",
1298 DB_TOKEN,
1299 "Diskless", // The new parameter name to use
1300 ConfigInfo::CI_DEPRECATED,
1301 CI_RESTART_INITIAL | CI_RESTART_SYSTEM,
1302 ConfigInfo::CI_BOOL,
1303 "false",
1304 "false",
1305 "true"},
1306
1307
1308
1309 {
1310 CFG_DB_ARBIT_TIMEOUT,
1311 "ArbitrationTimeout",
1312 DB_TOKEN,
1313 "Max time (milliseconds) database partion waits for arbitration signal",
1314 ConfigInfo::CI_USED,
1315 false,
1316 ConfigInfo::CI_INT,
1317 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
1318 "3000",
1319 #else
1320 "7500",
1321 #endif
1322 "10",
1323 STR_VALUE(MAX_INT_RNIL) },
1324
1325 {
1326 CFG_DB_ARBIT_METHOD,
1327 "Arbitration",
1328 DB_TOKEN,
1329 "How to perform arbitration to avoid split-brain issue when node(s) fail",
1330 ConfigInfo::CI_USED,
1331 false,
1332 ConfigInfo::CI_ENUM,
1333 "Default", /* Default value */
1334 (const char*)arbit_method_typelib,
1335 0
1336 },
1337
1338 {
1339 CFG_NODE_DATADIR,
1340 "DataDir",
1341 DB_TOKEN,
1342 "Data directory for this node",
1343 ConfigInfo::CI_USED,
1344 CI_CHECK_WRITABLE | CI_RESTART_INITIAL,
1345 ConfigInfo::CI_STRING,
1346 ".",
1347 0, 0 },
1348
1349 {
1350 CFG_DB_FILESYSTEM_PATH,
1351 "FileSystemPath",
1352 DB_TOKEN,
1353 "Path to directory where the "DB_TOKEN_PRINT" node stores its data (directory must exist)",
1354 ConfigInfo::CI_USED,
1355 CI_CHECK_WRITABLE | CI_RESTART_INITIAL,
1356 ConfigInfo::CI_STRING,
1357 0,
1358 0, 0 },
1359
1360 {
1361 CFG_LOGLEVEL_STARTUP,
1362 "LogLevelStartup",
1363 DB_TOKEN,
1364 "Node startup info printed on stdout",
1365 ConfigInfo::CI_USED,
1366 false,
1367 ConfigInfo::CI_INT,
1368 "1",
1369 "0",
1370 "15" },
1371
1372 {
1373 CFG_LOGLEVEL_SHUTDOWN,
1374 "LogLevelShutdown",
1375 DB_TOKEN,
1376 "Node shutdown info printed on stdout",
1377 ConfigInfo::CI_USED,
1378 false,
1379 ConfigInfo::CI_INT,
1380 "0",
1381 "0",
1382 "15" },
1383
1384 {
1385 CFG_LOGLEVEL_STATISTICS,
1386 "LogLevelStatistic",
1387 DB_TOKEN,
1388 "Transaction, operation, transporter info printed on stdout",
1389 ConfigInfo::CI_USED,
1390 false,
1391 ConfigInfo::CI_INT,
1392 "0",
1393 "0",
1394 "15" },
1395
1396 {
1397 CFG_LOGLEVEL_CHECKPOINT,
1398 "LogLevelCheckpoint",
1399 DB_TOKEN,
1400 "Local and Global checkpoint info printed on stdout",
1401 ConfigInfo::CI_USED,
1402 false,
1403 ConfigInfo::CI_INT,
1404 "0",
1405 "0",
1406 "15" },
1407
1408 {
1409 CFG_LOGLEVEL_NODERESTART,
1410 "LogLevelNodeRestart",
1411 DB_TOKEN,
1412 "Node restart, node failure info printed on stdout",
1413 ConfigInfo::CI_USED,
1414 false,
1415 ConfigInfo::CI_INT,
1416 "0",
1417 "0",
1418 "15" },
1419
1420 {
1421 CFG_LOGLEVEL_CONNECTION,
1422 "LogLevelConnection",
1423 DB_TOKEN,
1424 "Node connect/disconnect info printed on stdout",
1425 ConfigInfo::CI_USED,
1426 false,
1427 ConfigInfo::CI_INT,
1428 "0",
1429 "0",
1430 "15" },
1431
1432 {
1433 CFG_LOGLEVEL_CONGESTION,
1434 "LogLevelCongestion",
1435 DB_TOKEN,
1436 "Congestion info printed on stdout",
1437 ConfigInfo::CI_USED,
1438 false,
1439 ConfigInfo::CI_INT,
1440 "0",
1441 "0",
1442 "15" },
1443
1444 {
1445 CFG_LOGLEVEL_ERROR,
1446 "LogLevelError",
1447 DB_TOKEN,
1448 "Transporter, heartbeat errors printed on stdout",
1449 ConfigInfo::CI_USED,
1450 false,
1451 ConfigInfo::CI_INT,
1452 "0",
1453 "0",
1454 "15" },
1455
1456 {
1457 CFG_LOGLEVEL_INFO,
1458 "LogLevelInfo",
1459 DB_TOKEN,
1460 "Heartbeat and log info printed on stdout",
1461 ConfigInfo::CI_USED,
1462 false,
1463 ConfigInfo::CI_INT,
1464 "0",
1465 "0",
1466 "15" },
1467
1468 /**
1469 * Backup
1470 */
1471 {
1472 CFG_DB_PARALLEL_BACKUPS,
1473 "ParallelBackups",
1474 DB_TOKEN,
1475 "Maximum number of parallel backups",
1476 ConfigInfo::CI_NOTIMPLEMENTED,
1477 false,
1478 ConfigInfo::CI_INT,
1479 "1",
1480 "1",
1481 "1" },
1482
1483 {
1484 CFG_DB_BACKUP_DATADIR,
1485 "BackupDataDir",
1486 DB_TOKEN,
1487 "Path to where to store backups",
1488 ConfigInfo::CI_USED,
1489 CI_CHECK_WRITABLE | CI_RESTART_INITIAL,
1490 ConfigInfo::CI_STRING,
1491 0,
1492 0, 0 },
1493
1494 {
1495 CFG_DB_DISK_SYNCH_SIZE,
1496 "DiskSyncSize",
1497 DB_TOKEN,
1498 "Data written to a file before a synch is forced",
1499 ConfigInfo::CI_USED,
1500 false,
1501 ConfigInfo::CI_INT,
1502 "4M",
1503 "32k",
1504 STR_VALUE(MAX_INT_RNIL) },
1505
1506 {
1507 CFG_DB_CHECKPOINT_SPEED,
1508 "DiskCheckpointSpeed",
1509 DB_TOKEN,
1510 "Bytes per second allowed to be written by checkpoint",
1511 ConfigInfo::CI_USED,
1512 false,
1513 ConfigInfo::CI_INT,
1514 "10M",
1515 "1M",
1516 STR_VALUE(MAX_INT_RNIL) },
1517
1518 {
1519 CFG_DB_CHECKPOINT_SPEED_SR,
1520 "DiskCheckpointSpeedInRestart",
1521 DB_TOKEN,
1522 "Bytes per second allowed to be written by checkpoint during restart",
1523 ConfigInfo::CI_USED,
1524 false,
1525 ConfigInfo::CI_INT,
1526 "100M",
1527 "1M",
1528 STR_VALUE(MAX_INT_RNIL) },
1529
1530 {
1531 CFG_DB_BACKUP_MEM,
1532 "BackupMemory",
1533 DB_TOKEN,
1534 "Total memory allocated for backups per node (in bytes)",
1535 ConfigInfo::CI_USED,
1536 false,
1537 ConfigInfo::CI_INT,
1538 "32M", // sum of BackupDataBufferSize and BackupLogBufferSize
1539 "0",
1540 STR_VALUE(MAX_INT_RNIL) },
1541
1542 {
1543 CFG_DB_BACKUP_DATA_BUFFER_MEM,
1544 "BackupDataBufferSize",
1545 DB_TOKEN,
1546 "Default size of databuffer for a backup (in bytes)",
1547 ConfigInfo::CI_USED,
1548 false,
1549 ConfigInfo::CI_INT,
1550 "16M", // remember to change BackupMemory
1551 "0",
1552 STR_VALUE(MAX_INT_RNIL) },
1553
1554 {
1555 CFG_DB_BACKUP_LOG_BUFFER_MEM,
1556 "BackupLogBufferSize",
1557 DB_TOKEN,
1558 "Default size of logbuffer for a backup (in bytes)",
1559 ConfigInfo::CI_USED,
1560 false,
1561 ConfigInfo::CI_INT,
1562 "16M", // remember to change BackupMemory
1563 "0",
1564 STR_VALUE(MAX_INT_RNIL) },
1565
1566 {
1567 CFG_DB_BACKUP_WRITE_SIZE,
1568 "BackupWriteSize",
1569 DB_TOKEN,
1570 "Default size of filesystem writes made by backup (in bytes)",
1571 ConfigInfo::CI_USED,
1572 false,
1573 ConfigInfo::CI_INT,
1574 "256K",
1575 "2K",
1576 STR_VALUE(MAX_INT_RNIL) },
1577
1578 {
1579 CFG_DB_BACKUP_MAX_WRITE_SIZE,
1580 "BackupMaxWriteSize",
1581 DB_TOKEN,
1582 "Max size of filesystem writes made by backup (in bytes)",
1583 ConfigInfo::CI_USED,
1584 false,
1585 ConfigInfo::CI_INT,
1586 "1M",
1587 "2K",
1588 STR_VALUE(MAX_INT_RNIL) },
1589
1590 {
1591 CFG_DB_STRING_MEMORY,
1592 "StringMemory",
1593 DB_TOKEN,
1594 "Default size of string memory (1-100 -> %of max, >100 -> actual bytes)",
1595 ConfigInfo::CI_USED,
1596 false,
1597 ConfigInfo::CI_INT,
1598 "25",
1599 "0",
1600 STR_VALUE(MAX_INT_RNIL) },
1601
1602 {
1603 CFG_DB_MAX_ALLOCATE,
1604 "MaxAllocate",
1605 DB_TOKEN,
1606 "Maximum size of allocation to use when allocating memory for tables",
1607 ConfigInfo::CI_USED,
1608 false,
1609 ConfigInfo::CI_INT,
1610 "32M",
1611 "1M",
1612 "1G" },
1613
1614 {
1615 CFG_DB_MEMREPORT_FREQUENCY,
1616 "MemReportFrequency",
1617 DB_TOKEN,
1618 "Frequency of mem reports in seconds, 0 = only when passing %-limits",
1619 ConfigInfo::CI_USED,
1620 false,
1621 ConfigInfo::CI_INT,
1622 "0",
1623 "0",
1624 STR_VALUE(MAX_INT_RNIL) },
1625
1626 {
1627 CFG_DB_BACKUP_REPORT_FREQUENCY,
1628 "BackupReportFrequency",
1629 DB_TOKEN,
1630 "Frequency of backup status reports during backup in seconds",
1631 ConfigInfo::CI_USED,
1632 false,
1633 ConfigInfo::CI_INT,
1634 "0",
1635 "0",
1636 STR_VALUE(MAX_INT_RNIL) },
1637
1638 {
1639 CFG_DB_STARTUP_REPORT_FREQUENCY,
1640 "StartupStatusReportFrequency",
1641 DB_TOKEN,
1642 "Frequency of various status reports during startup in seconds",
1643 ConfigInfo::CI_USED,
1644 false,
1645 ConfigInfo::CI_INT,
1646 "0",
1647 "0",
1648 STR_VALUE(MAX_INT_RNIL) },
1649
1650 {
1651 CFG_DB_O_DIRECT,
1652 "ODirect",
1653 DB_TOKEN,
1654 "Use O_DIRECT file write/read when possible",
1655 ConfigInfo::CI_USED,
1656 false,
1657 ConfigInfo::CI_BOOL,
1658 "false",
1659 "false",
1660 "true"},
1661 {
1662 CFG_DB_COMPRESSED_BACKUP,
1663 "CompressedBackup",
1664 DB_TOKEN,
1665 "Use zlib to compress BACKUPs as they are written",
1666 ConfigInfo::CI_USED,
1667 0,
1668 ConfigInfo::CI_BOOL,
1669 "false",
1670 "false",
1671 "true"},
1672 {
1673 CFG_DB_COMPRESSED_LCP,
1674 "CompressedLCP",
1675 DB_TOKEN,
1676 "Write compressed LCPs using zlib",
1677 ConfigInfo::CI_USED,
1678 CI_RESTART_INITIAL,
1679 ConfigInfo::CI_BOOL,
1680 "false",
1681 "false",
1682 "true"},
1683
1684 {
1685 CFG_TOTAL_SEND_BUFFER_MEMORY,
1686 "TotalSendBufferMemory",
1687 DB_TOKEN,
1688 "Total memory to use for send buffers in all transporters",
1689 ConfigInfo::CI_USED,
1690 false,
1691 ConfigInfo::CI_INT,
1692 "0",
1693 "256K",
1694 STR_VALUE(MAX_INT_RNIL)
1695 },
1696
1697 {
1698 CFG_RESERVED_SEND_BUFFER_MEMORY,
1699 "ReservedSendBufferMemory",
1700 DB_TOKEN,
1701 "Amount of bytes (out of TotalSendBufferMemory) to reserve for connection\n"
1702 "between data nodes. This memory will not be available for connections to\n"
1703 "management server or API nodes.",
1704 ConfigInfo::CI_USED,
1705 false,
1706 ConfigInfo::CI_INT,
1707 "0",
1708 "256K",
1709 STR_VALUE(MAX_INT_RNIL)
1710 },
1711
1712 {
1713 CFG_DB_NODEGROUP,
1714 "Nodegroup",
1715 DB_TOKEN,
1716 "Nodegroup for node, only used during initial cluster start",
1717 ConfigInfo::CI_USED,
1718 false,
1719 ConfigInfo::CI_INT,
1720 0,
1721 "0",
1722 STR_VALUE(NDB_NO_NODEGROUP)
1723 },
1724
1725 {
1726 CFG_DB_MT_THREADS,
1727 "MaxNoOfExecutionThreads",
1728 DB_TOKEN,
1729 "For ndbmtd, specify max no of execution threads",
1730 ConfigInfo::CI_USED,
1731 false,
1732 ConfigInfo::CI_INT,
1733 "0",
1734 "2",
1735 "8"
1736 },
1737
1738 {
1739 CFG_NDBMT_LQH_WORKERS,
1740 "__ndbmt_lqh_workers",
1741 DB_TOKEN,
1742 "For ndbmtd specify no of lqh workers",
1743 ConfigInfo::CI_USED,
1744 false,
1745 ConfigInfo::CI_INT,
1746 0,
1747 "1",
1748 "4"
1749 },
1750
1751 {
1752 CFG_NDBMT_LQH_THREADS,
1753 "__ndbmt_lqh_threads",
1754 DB_TOKEN,
1755 "For ndbmtd specify no of lqh threads",
1756 ConfigInfo::CI_USED,
1757 false,
1758 ConfigInfo::CI_INT,
1759 0,
1760 "1",
1761 "4"
1762 },
1763
1764 {
1765 CFG_NDBMT_CLASSIC,
1766 "__ndbmt_classic",
1767 DB_TOKEN,
1768 "For ndbmtd use mt-classic",
1769 ConfigInfo::CI_USED,
1770 false,
1771 ConfigInfo::CI_BOOL,
1772 0,
1773 "false",
1774 "true"
1775 },
1776
1777 {
1778 CFG_DB_MT_THREAD_CONFIG,
1779 "ThreadConfig",
1780 DB_TOKEN,
1781 "Thread configuration",
1782 ConfigInfo::CI_USED,
1783 false,
1784 ConfigInfo::CI_STRING,
1785 0,
1786 0,
1787 0
1788 },
1789
1790 {
1791 CFG_DB_DD_FILESYSTEM_PATH,
1792 "FileSystemPathDD",
1793 DB_TOKEN,
1794 "Path to directory where the "DB_TOKEN_PRINT" node stores its disk-data/undo-files",
1795 ConfigInfo::CI_USED,
1796 CI_CHECK_WRITABLE | CI_RESTART_INITIAL,
1797 ConfigInfo::CI_STRING,
1798 0,
1799 0, 0 },
1800
1801 {
1802 CFG_DB_DD_DATAFILE_PATH,
1803 "FileSystemPathDataFiles",
1804 DB_TOKEN,
1805 "Path to directory where the "DB_TOKEN_PRINT" node stores its disk-data-files",
1806 ConfigInfo::CI_USED,
1807 CI_CHECK_WRITABLE | CI_RESTART_INITIAL,
1808 ConfigInfo::CI_STRING,
1809 0,
1810 0, 0 },
1811
1812 {
1813 CFG_DB_DD_UNDOFILE_PATH,
1814 "FileSystemPathUndoFiles",
1815 DB_TOKEN,
1816 "Path to directory where the "DB_TOKEN_PRINT" node stores its disk-undo-files",
1817 ConfigInfo::CI_USED,
1818 CI_CHECK_WRITABLE | CI_RESTART_INITIAL,
1819 ConfigInfo::CI_STRING,
1820 0,
1821 0, 0 },
1822
1823 {
1824 CFG_DB_DD_LOGFILEGROUP_SPEC,
1825 "InitialLogfileGroup",
1826 DB_TOKEN,
1827 "Logfile group that will be created during initial start",
1828 ConfigInfo::CI_USED,
1829 CI_RESTART_SYSTEM | CI_RESTART_INITIAL,
1830 ConfigInfo::CI_STRING,
1831 0,
1832 0, 0 },
1833
1834 {
1835 CFG_DB_DD_TABLEPACE_SPEC,
1836 "InitialTablespace",
1837 DB_TOKEN,
1838 "Tablespace that will be created during initial start",
1839 ConfigInfo::CI_USED,
1840 CI_RESTART_SYSTEM | CI_RESTART_INITIAL,
1841 ConfigInfo::CI_STRING,
1842 0,
1843 0, 0 },
1844
1845 {
1846 CFG_DB_LCP_TRY_LOCK_TIMEOUT,
1847 "MaxLCPStartDelay",
1848 DB_TOKEN,
1849 "Time in seconds that LCP will poll for checkpoint mutex, before putting it self in lock-queue",
1850 ConfigInfo::CI_USED,
1851 false,
1852 ConfigInfo::CI_INT,
1853 "0",
1854 "0",
1855 "600" },
1856
1857 // 7.0 NodeGroup -> initial, system
1858
1859 {
1860 CFG_DB_MT_BUILD_INDEX,
1861 "BuildIndexThreads",
1862 DB_TOKEN,
1863 "No of threads to use for building ordered indexes during system/node restart",
1864 ConfigInfo::CI_USED,
1865 false,
1866 ConfigInfo::CI_INT,
1867 "0",
1868 "0",
1869 "128" },
1870
1871 {
1872 CFG_DB_HB_ORDER,
1873 "HeartbeatOrder",
1874 DB_TOKEN,
1875 "Heartbeat circle is ordered by the given values "
1876 "which must be non-zero and distinct",
1877 ConfigInfo::CI_USED,
1878 false,
1879 ConfigInfo::CI_INT,
1880 "0",
1881 "0",
1882 "65535" },
1883
1884 {
1885 CFG_DB_DICT_TRACE,
1886 "DictTrace",
1887 DB_TOKEN,
1888 "Tracelevel for ndbd's dictionary",
1889 ConfigInfo::CI_USED,
1890 false,
1891 ConfigInfo::CI_INT,
1892 0,
1893 "0",
1894 "100" },
1895
1896 {
1897 CFG_DB_MAX_START_FAIL,
1898 "MaxStartFailRetries",
1899 DB_TOKEN,
1900 "Maximum retries when Ndbd fails in startup, requires StopOnError=0. "
1901 "0 is infinite.",
1902 ConfigInfo::CI_USED,
1903 false,
1904 ConfigInfo::CI_INT,
1905 "3", /* Default */
1906 "0", /* Min */
1907 STR_VALUE(MAX_INT_RNIL) /* Max */
1908 },
1909
1910 {
1911 CFG_DB_START_FAIL_DELAY_SECS,
1912 "StartFailRetryDelay",
1913 DB_TOKEN,
1914 "Delay in seconds after start failure prior to retry. "
1915 "Requires StopOnError= 0",
1916 ConfigInfo::CI_USED,
1917 false,
1918 ConfigInfo::CI_INT,
1919 "0", /* Default */
1920 "0", /* Min */
1921 STR_VALUE(MAX_INT_RNIL) /* Max */
1922 },
1923
1924 {
1925 CFG_DB_EVENTLOG_BUFFER_SIZE,
1926 "EventLogBufferSize",
1927 DB_TOKEN,
1928 "Size of circular buffer of ndb_logevent (inside datanodes)",
1929 ConfigInfo::CI_USED,
1930 false,
1931 ConfigInfo::CI_INT,
1932 "4096", /* Default */
1933 "0", /* Min */
1934 "64k" /* Max : There is no flow control...so set limit*/
1935 },
1936
1937 {
1938 CFG_DB_NUMA,
1939 "Numa",
1940 DB_TOKEN,
1941 "Enable/disable numa support (currently linux only)",
1942 ConfigInfo::CI_USED,
1943 false,
1944 ConfigInfo::CI_INT,
1945 "1", /* Interleave on all numa nodes */
1946 "0", /* Min (no numa action at all) */
1947 "1" /* Max */
1948 },
1949
1950 {
1951 CFG_DB_REDO_OVERCOMMIT_LIMIT,
1952 "RedoOverCommitLimit",
1953 DB_TOKEN,
1954 "Limit for how long it will take to flush current "
1955 "RedoBuffer before action is taken (in seconds)",
1956 ConfigInfo::CI_USED,
1957 false,
1958 ConfigInfo::CI_INT,
1959 "20", /* Default */
1960 "0", /* Min */
1961 STR_VALUE(MAX_INT_RNIL) /* Max */
1962 },
1963
1964 {
1965 CFG_DB_REDO_OVERCOMMIT_COUNTER,
1966 "RedoOverCommitCounter",
1967 DB_TOKEN,
1968 "If RedoOverCommitLimit has been reached RedoOverCommitCounter"
1969 " in a row times, transactions will be aborted",
1970 ConfigInfo::CI_USED,
1971 false,
1972 ConfigInfo::CI_INT,
1973 "3", /* Default */
1974 "0", /* Min */
1975 STR_VALUE(MAX_INT_RNIL) /* Max */
1976 },
1977
1978 {
1979 CFG_DB_LATE_ALLOC,
1980 "LateAlloc",
1981 DB_TOKEN,
1982 "Allocate memory after connection to ndb_mgmd has been established",
1983 ConfigInfo::CI_USED,
1984 false,
1985 ConfigInfo::CI_INT,
1986 "1",
1987 "0", /* Min */
1988 "1" /* Max */
1989 },
1990
1991
1992 {
1993 CFG_DB_2PASS_INR,
1994 "TwoPassInitialNodeRestartCopy",
1995 DB_TOKEN,
1996 "Copy data in 2 passes for initial node restart, "
1997 "this enables multi-threaded-ordered index build for initial node restart",
1998 ConfigInfo::CI_USED,
1999 false,
2000 ConfigInfo::CI_BOOL,
2001 "false",
2002 "false", /* Min */
2003 "true" /* Max */
2004 },
2005
2006 {
2007 CFG_DB_PARALLEL_SCANS_PER_FRAG,
2008 "MaxParallelScansPerFragment",
2009 DB_TOKEN,
2010 "Max parallel scans per fragment (tup or tux). If this limit is reached "
2011 " scans will be serialized using a queue.",
2012 ConfigInfo::CI_USED,
2013 false,
2014 ConfigInfo::CI_INT,
2015 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
2016 "32",
2017 #else
2018 "256",
2019 #endif
2020 "1", /* Min */
2021 STR_VALUE(MAX_INT_RNIL) /* Max */
2022 },
2023
2024 /* ordered index stats */
2025
2026 {
2027 CFG_DB_INDEX_STAT_AUTO_CREATE,
2028 "IndexStatAutoCreate",
2029 DB_TOKEN,
2030 "Make create index also create initial index stats",
2031 ConfigInfo::CI_USED,
2032 0,
2033 ConfigInfo::CI_INT,
2034 "0",
2035 "0",
2036 "1"
2037 },
2038
2039 {
2040 CFG_DB_INDEX_STAT_AUTO_UPDATE,
2041 "IndexStatAutoUpdate",
2042 DB_TOKEN,
2043 "Monitor each index for changes and trigger automatic stats updates."
2044 " See IndexStatTrigger options",
2045 ConfigInfo::CI_USED,
2046 0,
2047 ConfigInfo::CI_INT,
2048 "0",
2049 "0",
2050 "1"
2051 },
2052
2053 {
2054 CFG_DB_INDEX_STAT_SAVE_SIZE,
2055 "IndexStatSaveSize",
2056 DB_TOKEN,
2057 "Maximum bytes allowed for the saved stats of one index."
2058 " At least 1 sample is produced regardless of size limit."
2059 " The size is scaled up by a factor from IndexStatSaveScale."
2060 " The value affects size of stats saved in NDB system tables"
2061 " and in mysqld memory cache",
2062 ConfigInfo::CI_USED,
2063 0,
2064 ConfigInfo::CI_INT,
2065 "32768",
2066 "0",
2067 STR_VALUE(MAX_INT_RNIL)
2068 },
2069
2070 {
2071 CFG_DB_INDEX_STAT_SAVE_SCALE,
2072 "IndexStatSaveScale",
2073 DB_TOKEN,
2074 "Factor to scale up IndexStatSaveSize for a large index."
2075 " Given in units of 0.01."
2076 " Multiplied by a logarithmic index size."
2077 " Value 0 disables scaling",
2078 ConfigInfo::CI_USED,
2079 0,
2080 ConfigInfo::CI_INT,
2081 "100",
2082 "0",
2083 STR_VALUE(MAX_INT_RNIL)
2084 },
2085
2086 {
2087 CFG_DB_INDEX_STAT_TRIGGER_PCT,
2088 "IndexStatTriggerPct",
2089 DB_TOKEN,
2090 "Percent change (in DML ops) to schedule index stats update."
2091 " The value is scaled down by a factor from IndexStatTriggerScale."
2092 " Value 0 disables the trigger",
2093 ConfigInfo::CI_USED,
2094 0,
2095 ConfigInfo::CI_INT,
2096 "100",
2097 "0",
2098 STR_VALUE(MAX_INT_RNIL)
2099 },
2100
2101 {
2102 CFG_DB_INDEX_STAT_TRIGGER_SCALE,
2103 "IndexStatTriggerScale",
2104 DB_TOKEN,
2105 "Factor to scale down IndexStatTriggerPct for a large index."
2106 " Given in units of 0.01."
2107 " Multiplied by a logarithmic index size."
2108 " Value 0 disables scaling",
2109 ConfigInfo::CI_USED,
2110 0,
2111 ConfigInfo::CI_INT,
2112 "100",
2113 "0",
2114 STR_VALUE(MAX_INT_RNIL)
2115 },
2116
2117 {
2118 CFG_DB_INDEX_STAT_UPDATE_DELAY,
2119 "IndexStatUpdateDelay",
2120 DB_TOKEN,
2121 "Minimum delay in seconds between automatic index stats updates"
2122 " for a given index."
2123 " Value 0 means no delay",
2124 ConfigInfo::CI_USED,
2125 0,
2126 ConfigInfo::CI_INT,
2127 "60",
2128 "0",
2129 STR_VALUE(MAX_INT_RNIL)
2130 },
2131
2132 /***************************************************************************
2133 * API
2134 ***************************************************************************/
2135 {
2136 CFG_SECTION_NODE,
2137 API_TOKEN,
2138 API_TOKEN,
2139 "Node section",
2140 ConfigInfo::CI_USED,
2141 false,
2142 ConfigInfo::CI_SECTION,
2143 (const char *)NODE_TYPE_API,
2144 0, 0
2145 },
2146
2147 {
2148 KEY_INTERNAL,
2149 "wan",
2150 API_TOKEN,
2151 "Use WAN TCP setting as default",
2152 ConfigInfo::CI_USED,
2153 false,
2154 ConfigInfo::CI_BOOL,
2155 "false",
2156 "false",
2157 "true"
2158 },
2159
2160 {
2161 CFG_NODE_HOST,
2162 "HostName",
2163 API_TOKEN,
2164 "Name of computer for this node",
2165 ConfigInfo::CI_USED,
2166 false,
2167 ConfigInfo::CI_STRING,
2168 "",
2169 0, 0 },
2170
2171 {
2172 CFG_NODE_SYSTEM,
2173 "System",
2174 API_TOKEN,
2175 "Name of system for this node",
2176 ConfigInfo::CI_INTERNAL,
2177 false,
2178 ConfigInfo::CI_STRING,
2179 0,
2180 0, 0 },
2181
2182 {
2183 KEY_INTERNAL,
2184 "Id",
2185 API_TOKEN,
2186 "NodeId", // Name of new parameter to use instead of deprecated
2187 ConfigInfo::CI_DEPRECATED,
2188 false,
2189 ConfigInfo::CI_INT,
2190 MANDATORY,
2191 "1",
2192 STR_VALUE(MAX_NODES_ID) },
2193
2194 {
2195 CFG_NODE_ID,
2196 "NodeId",
2197 API_TOKEN,
2198 "Number identifying application node ("API_TOKEN_PRINT")",
2199 ConfigInfo::CI_USED,
2200 false,
2201 ConfigInfo::CI_INT,
2202 MANDATORY,
2203 "1",
2204 STR_VALUE(MAX_NODES_ID) },
2205
2206 {
2207 KEY_INTERNAL,
2208 "ExecuteOnComputer",
2209 API_TOKEN,
2210 "String referencing an earlier defined COMPUTER",
2211 ConfigInfo::CI_USED,
2212 false,
2213 ConfigInfo::CI_STRING,
2214 0,
2215 0, 0 },
2216
2217 {
2218 CFG_NODE_ARBIT_RANK,
2219 "ArbitrationRank",
2220 API_TOKEN,
2221 "If 0, then "API_TOKEN_PRINT" is not arbitrator. Kernel selects arbitrators in order 1, 2",
2222 ConfigInfo::CI_USED,
2223 false,
2224 ConfigInfo::CI_INT,
2225 "0",
2226 "0",
2227 "2" },
2228
2229 {
2230 CFG_NODE_ARBIT_DELAY,
2231 "ArbitrationDelay",
2232 API_TOKEN,
2233 "When asked to arbitrate, arbitrator waits this long before voting (msec)",
2234 ConfigInfo::CI_USED,
2235 0,
2236 ConfigInfo::CI_INT,
2237 "0",
2238 "0",
2239 STR_VALUE(MAX_INT_RNIL) },
2240
2241 {
2242 CFG_MAX_SCAN_BATCH_SIZE,
2243 "MaxScanBatchSize",
2244 "API",
2245 "The maximum collective batch size for one scan",
2246 ConfigInfo::CI_USED,
2247 false,
2248 ConfigInfo::CI_INT,
2249 STR_VALUE(MAX_SCAN_BATCH_SIZE),
2250 "32k",
2251 "16M" },
2252
2253 {
2254 CFG_BATCH_BYTE_SIZE,
2255 "BatchByteSize",
2256 "API",
2257 "The default batch size in bytes",
2258 ConfigInfo::CI_USED,
2259 false,
2260 ConfigInfo::CI_INT,
2261 STR_VALUE(SCAN_BATCH_SIZE),
2262 "1k",
2263 "1M" },
2264
2265 {
2266 CFG_BATCH_SIZE,
2267 "BatchSize",
2268 "API",
2269 "The default batch size in number of records",
2270 ConfigInfo::CI_USED,
2271 false,
2272 ConfigInfo::CI_INT,
2273 STR_VALUE(DEF_BATCH_SIZE),
2274 "1",
2275 STR_VALUE(MAX_PARALLEL_OP_PER_SCAN) },
2276
2277 {
2278 KEY_INTERNAL,
2279 "ConnectionMap",
2280 "API",
2281 "Specifies which DB nodes to connect",
2282 ConfigInfo::CI_USED,
2283 false,
2284 ConfigInfo::CI_STRING,
2285 0,
2286 0,
2287 0
2288 },
2289
2290 {
2291 CFG_TOTAL_SEND_BUFFER_MEMORY,
2292 "TotalSendBufferMemory",
2293 "API",
2294 "Total memory to use for send buffers in all transporters",
2295 ConfigInfo::CI_USED,
2296 false,
2297 ConfigInfo::CI_INT,
2298 "0",
2299 "256K",
2300 STR_VALUE(MAX_INT_RNIL)
2301 },
2302
2303 {
2304 CFG_AUTO_RECONNECT,
2305 "AutoReconnect",
2306 "API",
2307 "Specifies if an api node should reconnect when fully disconnected from cluster",
2308 ConfigInfo::CI_USED,
2309 false,
2310 ConfigInfo::CI_BOOL,
2311 "true",
2312 "false",
2313 "true"
2314 },
2315
2316 {
2317 CFG_HB_THREAD_PRIO,
2318 "HeartbeatThreadPriority",
2319 API_TOKEN,
2320 "Specify thread properties of heartbeat thread",
2321 ConfigInfo::CI_USED,
2322 0,
2323 ConfigInfo::CI_STRING,
2324 0, 0, 0 },
2325
2326 {
2327 CFG_DEFAULT_OPERATION_REDO_PROBLEM_ACTION,
2328 "DefaultOperationRedoProblemAction",
2329 API_TOKEN,
2330 "If Redo-log is having problem, should operation default "
2331 "(unless overridden on transaction/operation level) abort "
2332 "or be put on queue",
2333 ConfigInfo::CI_USED,
2334 false,
2335 ConfigInfo::CI_ENUM,
2336 #if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,0)
2337 "abort", /* Default value */
2338 #else
2339 "queue", /* Default value */
2340 #endif
2341 (const char*)default_operation_redo_problem_action_typelib,
2342 0
2343 },
2344
2345 /****************************************************************************
2346 * MGM
2347 ***************************************************************************/
2348 {
2349 CFG_SECTION_NODE,
2350 MGM_TOKEN,
2351 MGM_TOKEN,
2352 "Node section",
2353 ConfigInfo::CI_USED,
2354 false,
2355 ConfigInfo::CI_SECTION,
2356 (const char *)NODE_TYPE_MGM,
2357 0, 0
2358 },
2359
2360 {
2361 KEY_INTERNAL,
2362 "wan",
2363 MGM_TOKEN,
2364 "Use WAN TCP setting as default",
2365 ConfigInfo::CI_USED,
2366 false,
2367 ConfigInfo::CI_BOOL,
2368 "false",
2369 "false",
2370 "true"
2371 },
2372
2373 {
2374 CFG_NODE_HOST,
2375 "HostName",
2376 MGM_TOKEN,
2377 "Name of computer for this node",
2378 ConfigInfo::CI_USED,
2379 false,
2380 ConfigInfo::CI_STRING,
2381 "",
2382 0, 0 },
2383
2384 {
2385 CFG_NODE_DATADIR,
2386 "DataDir",
2387 MGM_TOKEN,
2388 "Data directory for this node",
2389 ConfigInfo::CI_USED,
2390 CI_CHECK_WRITABLE,
2391 ConfigInfo::CI_STRING,
2392 "",
2393 0, 0 },
2394
2395 {
2396 CFG_NODE_SYSTEM,
2397 "System",
2398 MGM_TOKEN,
2399 "Name of system for this node",
2400 ConfigInfo::CI_INTERNAL,
2401 false,
2402 ConfigInfo::CI_STRING,
2403 0,
2404 0, 0 },
2405
2406 {
2407 KEY_INTERNAL,
2408 "Id",
2409 MGM_TOKEN,
2410 "NodeId", // Name of new parameter to use instead of deprecated
2411 ConfigInfo::CI_DEPRECATED,
2412 false,
2413 ConfigInfo::CI_INT,
2414 MANDATORY,
2415 "1",
2416 STR_VALUE(MAX_NODES_ID) },
2417
2418 {
2419 CFG_NODE_ID,
2420 "NodeId",
2421 MGM_TOKEN,
2422 "Number identifying the management server node ("MGM_TOKEN_PRINT")",
2423 ConfigInfo::CI_USED,
2424 false,
2425 ConfigInfo::CI_INT,
2426 MANDATORY,
2427 "1",
2428 STR_VALUE(MAX_NODES_ID) },
2429
2430 {
2431 CFG_LOG_DESTINATION,
2432 "LogDestination",
2433 MGM_TOKEN,
2434 "String describing where logmessages are sent",
2435 ConfigInfo::CI_USED,
2436 false,
2437 ConfigInfo::CI_STRING,
2438 0,
2439 0, 0 },
2440
2441 {
2442 KEY_INTERNAL,
2443 "ExecuteOnComputer",
2444 MGM_TOKEN,
2445 "String referencing an earlier defined COMPUTER",
2446 ConfigInfo::CI_USED,
2447 false,
2448 ConfigInfo::CI_STRING,
2449 0,
2450 0, 0 },
2451
2452 {
2453 KEY_INTERNAL,
2454 "MaxNoOfSavedEvents",
2455 MGM_TOKEN,
2456 "",
2457 ConfigInfo::CI_USED,
2458 false,
2459 ConfigInfo::CI_INT,
2460 "100",
2461 "0",
2462 STR_VALUE(MAX_INT_RNIL) },
2463
2464 {
2465 CFG_MGM_PORT,
2466 "PortNumber",
2467 MGM_TOKEN,
2468 "Port number to give commands to/fetch configurations from management server",
2469 ConfigInfo::CI_USED,
2470 false,
2471 ConfigInfo::CI_INT,
2472 STR_VALUE(NDB_PORT),
2473 "0",
2474 STR_VALUE(MAX_PORT_NO) },
2475
2476 {
2477 KEY_INTERNAL,
2478 "PortNumberStats",
2479 MGM_TOKEN,
2480 "Port number used to get statistical information from a management server",
2481 ConfigInfo::CI_USED,
2482 false,
2483 ConfigInfo::CI_INT,
2484 0,
2485 "0",
2486 STR_VALUE(MAX_PORT_NO) },
2487
2488 {
2489 CFG_NODE_ARBIT_RANK,
2490 "ArbitrationRank",
2491 MGM_TOKEN,
2492 "If 0, then "MGM_TOKEN_PRINT" is not arbitrator. Kernel selects arbitrators in order 1, 2",
2493 ConfigInfo::CI_USED,
2494 false,
2495 ConfigInfo::CI_INT,
2496 "1",
2497 "0",
2498 "2" },
2499
2500 {
2501 CFG_NODE_ARBIT_DELAY,
2502 "ArbitrationDelay",
2503 MGM_TOKEN,
2504 "",
2505 ConfigInfo::CI_USED,
2506 false,
2507 ConfigInfo::CI_INT,
2508 "0",
2509 "0",
2510 STR_VALUE(MAX_INT_RNIL) },
2511
2512 {
2513 CFG_TOTAL_SEND_BUFFER_MEMORY,
2514 "TotalSendBufferMemory",
2515 MGM_TOKEN,
2516 "Total memory to use for send buffers in all transporters",
2517 ConfigInfo::CI_USED,
2518 false,
2519 ConfigInfo::CI_INT,
2520 "0",
2521 "256K",
2522 STR_VALUE(MAX_INT_RNIL)
2523 },
2524
2525 {
2526 CFG_HB_THREAD_PRIO,
2527 "HeartbeatThreadPriority",
2528 MGM_TOKEN,
2529 "Specify thread properties of heartbeat thread",
2530 ConfigInfo::CI_USED,
2531 0,
2532 ConfigInfo::CI_STRING,
2533 0, 0, 0
2534 },
2535
2536 /****************************************************************************
2537 * TCP
2538 ***************************************************************************/
2539 {
2540 CFG_SECTION_CONNECTION,
2541 "TCP",
2542 "TCP",
2543 "Connection section",
2544 ConfigInfo::CI_USED,
2545 false,
2546 ConfigInfo::CI_SECTION,
2547 (const char *)CONNECTION_TYPE_TCP,
2548 0, 0
2549 },
2550
2551 {
2552 CFG_CONNECTION_HOSTNAME_1,
2553 "HostName1",
2554 "TCP",
2555 "Name/IP of computer on one side of the connection",
2556 ConfigInfo::CI_USED,
2557 false,
2558 ConfigInfo::CI_STRING,
2559 0,
2560 0, 0 },
2561
2562 {
2563 CFG_CONNECTION_HOSTNAME_2,
2564 "HostName2",
2565 "TCP",
2566 "Name/IP of computer on one side of the connection",
2567 ConfigInfo::CI_USED,
2568 false,
2569 ConfigInfo::CI_STRING,
2570 0,
2571 0, 0 },
2572
2573 {
2574 CFG_CONNECTION_NODE_1,
2575 "NodeId1",
2576 "TCP",
2577 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2578 ConfigInfo::CI_USED,
2579 false,
2580 ConfigInfo::CI_STRING,
2581 MANDATORY,
2582 0, 0 },
2583
2584 {
2585 CFG_CONNECTION_NODE_2,
2586 "NodeId2",
2587 "TCP",
2588 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2589 ConfigInfo::CI_USED,
2590 false,
2591 ConfigInfo::CI_STRING,
2592 MANDATORY,
2593 0, 0 },
2594
2595 {
2596 CFG_CONNECTION_GROUP,
2597 "Group",
2598 "TCP",
2599 "",
2600 ConfigInfo::CI_USED,
2601 false,
2602 ConfigInfo::CI_INT,
2603 "55",
2604 "0", "200" },
2605
2606 {
2607 CFG_CONNECTION_NODE_ID_SERVER,
2608 "NodeIdServer",
2609 "TCP",
2610 "",
2611 ConfigInfo::CI_USED,
2612 false,
2613 ConfigInfo::CI_INT,
2614 MANDATORY,
2615 "1", "63" },
2616
2617 {
2618 CFG_CONNECTION_SEND_SIGNAL_ID,
2619 "SendSignalId",
2620 "TCP",
2621 "Sends id in each signal. Used in trace files.",
2622 ConfigInfo::CI_USED,
2623 false,
2624 ConfigInfo::CI_BOOL,
2625 "true",
2626 "false",
2627 "true" },
2628
2629
2630 {
2631 CFG_CONNECTION_CHECKSUM,
2632 "Checksum",
2633 "TCP",
2634 "If checksum is enabled, all signals between nodes are checked for errors",
2635 ConfigInfo::CI_USED,
2636 false,
2637 ConfigInfo::CI_BOOL,
2638 "false",
2639 "false",
2640 "true" },
2641
2642 {
2643 CFG_CONNECTION_SERVER_PORT,
2644 "PortNumber",
2645 "TCP",
2646 0, // No new parameter to use instead of deprecated
2647 ConfigInfo::CI_DEPRECATED,
2648 false,
2649 ConfigInfo::CI_INT,
2650 MANDATORY,
2651 "0",
2652 STR_VALUE(MAX_PORT_NO) },
2653
2654 {
2655 CFG_TCP_SEND_BUFFER_SIZE,
2656 "SendBufferMemory",
2657 "TCP",
2658 "Bytes of buffer for signals sent from this node",
2659 ConfigInfo::CI_USED,
2660 false,
2661 ConfigInfo::CI_INT,
2662 "2M",
2663 "64K",
2664 STR_VALUE(MAX_INT_RNIL) },
2665
2666 {
2667 CFG_TCP_RECEIVE_BUFFER_SIZE,
2668 "ReceiveBufferMemory",
2669 "TCP",
2670 "Bytes of buffer for signals received by this node",
2671 ConfigInfo::CI_USED,
2672 false,
2673 ConfigInfo::CI_INT,
2674 "2M",
2675 "16K",
2676 STR_VALUE(MAX_INT_RNIL) },
2677
2678 {
2679 CFG_TCP_PROXY,
2680 "Proxy",
2681 "TCP",
2682 "",
2683 ConfigInfo::CI_USED,
2684 false,
2685 ConfigInfo::CI_STRING,
2686 0,
2687 0, 0 },
2688
2689 {
2690 CFG_CONNECTION_NODE_1_SYSTEM,
2691 "NodeId1_System",
2692 "TCP",
2693 "System for node 1 in connection",
2694 ConfigInfo::CI_INTERNAL,
2695 false,
2696 ConfigInfo::CI_STRING,
2697 0,
2698 0, 0 },
2699
2700 {
2701 CFG_CONNECTION_NODE_2_SYSTEM,
2702 "NodeId2_System",
2703 "TCP",
2704 "System for node 2 in connection",
2705 ConfigInfo::CI_INTERNAL,
2706 false,
2707 ConfigInfo::CI_STRING,
2708 0,
2709 0, 0 },
2710
2711 {
2712 CFG_TCP_SND_BUF_SIZE,
2713 "TCP_SND_BUF_SIZE",
2714 "TCP",
2715 "Value used for SO_SNDBUF",
2716 ConfigInfo::CI_USED,
2717 false,
2718 ConfigInfo::CI_INT,
2719 "71540",
2720 "1",
2721 "2G"
2722 },
2723
2724 {
2725 CFG_TCP_RCV_BUF_SIZE,
2726 "TCP_RCV_BUF_SIZE",
2727 "TCP",
2728 "Value used for SO_RCVBUF",
2729 ConfigInfo::CI_USED,
2730 false,
2731 ConfigInfo::CI_INT,
2732 "70080",
2733 "1",
2734 "2G"
2735 },
2736
2737 {
2738 CFG_TCP_MAXSEG_SIZE,
2739 "TCP_MAXSEG_SIZE",
2740 "TCP",
2741 "Value used for TCP_MAXSEG",
2742 ConfigInfo::CI_USED,
2743 false,
2744 ConfigInfo::CI_INT,
2745 "0",
2746 "0",
2747 "2G"
2748 },
2749
2750 {
2751 CFG_TCP_BIND_INADDR_ANY,
2752 "TcpBind_INADDR_ANY",
2753 "TCP",
2754 "Bind InAddrAny instead of hostname for server part of connection",
2755 ConfigInfo::CI_USED,
2756 false,
2757 ConfigInfo::CI_BOOL,
2758 "false",
2759 "false", "true" },
2760
2761 {
2762 CFG_CONNECTION_OVERLOAD,
2763 "OverloadLimit",
2764 "TCP",
2765 "Number of unsent bytes that must be in the send buffer before the\n"
2766 "connection is considered overloaded",
2767 ConfigInfo::CI_USED,
2768 false,
2769 ConfigInfo::CI_INT,
2770 "0",
2771 "0",
2772 STR_VALUE(MAX_INT_RNIL)
2773 },
2774
2775 /****************************************************************************
2776 * SHM
2777 ***************************************************************************/
2778 {
2779 CFG_SECTION_CONNECTION,
2780 "SHM",
2781 "SHM",
2782 "Connection section",
2783 ConfigInfo::CI_EXPERIMENTAL,
2784 false,
2785 ConfigInfo::CI_SECTION,
2786 (const char *)CONNECTION_TYPE_SHM,
2787 0, 0 },
2788
2789 {
2790 CFG_CONNECTION_HOSTNAME_1,
2791 "HostName1",
2792 "SHM",
2793 "Name/IP of computer on one side of the connection",
2794 ConfigInfo::CI_USED,
2795 false,
2796 ConfigInfo::CI_STRING,
2797 0,
2798 0, 0 },
2799
2800 {
2801 CFG_CONNECTION_HOSTNAME_2,
2802 "HostName2",
2803 "SHM",
2804 "Name/IP of computer on one side of the connection",
2805 ConfigInfo::CI_USED,
2806 false,
2807 ConfigInfo::CI_STRING,
2808 0,
2809 0, 0 },
2810
2811 {
2812 CFG_CONNECTION_SERVER_PORT,
2813 "PortNumber",
2814 "SHM",
2815 0, // No new parameter to use instead of deprecated
2816 ConfigInfo::CI_DEPRECATED,
2817 false,
2818 ConfigInfo::CI_INT,
2819 MANDATORY,
2820 "0",
2821 STR_VALUE(MAX_PORT_NO) },
2822
2823 {
2824 CFG_SHM_SIGNUM,
2825 "Signum",
2826 "SHM",
2827 "Signum to be used for signalling",
2828 ConfigInfo::CI_EXPERIMENTAL,
2829 false,
2830 ConfigInfo::CI_INT,
2831 0,
2832 "0",
2833 STR_VALUE(MAX_INT_RNIL) },
2834
2835 {
2836 CFG_CONNECTION_NODE_1,
2837 "NodeId1",
2838 "SHM",
2839 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2840 ConfigInfo::CI_EXPERIMENTAL,
2841 false,
2842 ConfigInfo::CI_STRING,
2843 MANDATORY,
2844 0, 0 },
2845
2846 {
2847 CFG_CONNECTION_NODE_2,
2848 "NodeId2",
2849 "SHM",
2850 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2851 ConfigInfo::CI_EXPERIMENTAL,
2852 false,
2853 ConfigInfo::CI_STRING,
2854 MANDATORY,
2855 0, 0 },
2856
2857 {
2858 CFG_CONNECTION_GROUP,
2859 "Group",
2860 "SHM",
2861 "",
2862 ConfigInfo::CI_EXPERIMENTAL,
2863 false,
2864 ConfigInfo::CI_INT,
2865 "35",
2866 "0", "200" },
2867
2868 {
2869 CFG_CONNECTION_NODE_ID_SERVER,
2870 "NodeIdServer",
2871 "SHM",
2872 "",
2873 ConfigInfo::CI_EXPERIMENTAL,
2874 false,
2875 ConfigInfo::CI_INT,
2876 MANDATORY,
2877 "1", "63" },
2878
2879 {
2880 CFG_CONNECTION_SEND_SIGNAL_ID,
2881 "SendSignalId",
2882 "SHM",
2883 "Sends id in each signal. Used in trace files.",
2884 ConfigInfo::CI_EXPERIMENTAL,
2885 false,
2886 ConfigInfo::CI_BOOL,
2887 "false",
2888 "false",
2889 "true" },
2890
2891
2892 {
2893 CFG_CONNECTION_CHECKSUM,
2894 "Checksum",
2895 "SHM",
2896 "If checksum is enabled, all signals between nodes are checked for errors",
2897 ConfigInfo::CI_EXPERIMENTAL,
2898 false,
2899 ConfigInfo::CI_BOOL,
2900 "true",
2901 "false",
2902 "true" },
2903
2904 {
2905 CFG_SHM_KEY,
2906 "ShmKey",
2907 "SHM",
2908 "A shared memory key",
2909 ConfigInfo::CI_EXPERIMENTAL,
2910 false,
2911 ConfigInfo::CI_INT,
2912 0,
2913 "0",
2914 STR_VALUE(MAX_INT_RNIL) },
2915
2916 {
2917 CFG_SHM_BUFFER_MEM,
2918 "ShmSize",
2919 "SHM",
2920 "Size of shared memory segment",
2921 ConfigInfo::CI_EXPERIMENTAL,
2922 false,
2923 ConfigInfo::CI_INT,
2924 "1M",
2925 "64K",
2926 STR_VALUE(MAX_INT_RNIL) },
2927
2928 {
2929 CFG_CONNECTION_NODE_1_SYSTEM,
2930 "NodeId1_System",
2931 "SHM",
2932 "System for node 1 in connection",
2933 ConfigInfo::CI_INTERNAL,
2934 false,
2935 ConfigInfo::CI_STRING,
2936 0,
2937 0, 0 },
2938
2939 {
2940 CFG_CONNECTION_NODE_2_SYSTEM,
2941 "NodeId2_System",
2942 "SHM",
2943 "System for node 2 in connection",
2944 ConfigInfo::CI_INTERNAL,
2945 false,
2946 ConfigInfo::CI_STRING,
2947 0,
2948 0, 0 },
2949
2950 {
2951 CFG_CONNECTION_OVERLOAD,
2952 "OverloadLimit",
2953 "SHM",
2954 "Number of unsent bytes that must be in the send buffer before the\n"
2955 "connection is considered overloaded",
2956 ConfigInfo::CI_USED,
2957 false,
2958 ConfigInfo::CI_INT,
2959 "0",
2960 "0",
2961 STR_VALUE(MAX_INT_RNIL)
2962 },
2963
2964 /****************************************************************************
2965 * SCI
2966 ***************************************************************************/
2967 {
2968 CFG_SECTION_CONNECTION,
2969 "SCI",
2970 "SCI",
2971 "Connection section",
2972 ConfigInfo::CI_EXPERIMENTAL,
2973 false,
2974 ConfigInfo::CI_SECTION,
2975 (const char *)CONNECTION_TYPE_SCI,
2976 0, 0
2977 },
2978
2979 {
2980 CFG_CONNECTION_NODE_1,
2981 "NodeId1",
2982 "SCI",
2983 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2984 ConfigInfo::CI_EXPERIMENTAL,
2985 false,
2986 ConfigInfo::CI_STRING,
2987 MANDATORY,
2988 0, 0 },
2989
2990 {
2991 CFG_CONNECTION_NODE_2,
2992 "NodeId2",
2993 "SCI",
2994 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2995 ConfigInfo::CI_EXPERIMENTAL,
2996 false,
2997 ConfigInfo::CI_STRING,
2998 MANDATORY,
2999 0, 0 },
3000
3001 {
3002 CFG_CONNECTION_GROUP,
3003 "Group",
3004 "SCI",
3005 "",
3006 ConfigInfo::CI_EXPERIMENTAL,
3007 false,
3008 ConfigInfo::CI_INT,
3009 "15",
3010 "0", "200" },
3011
3012 {
3013 CFG_CONNECTION_NODE_ID_SERVER,
3014 "NodeIdServer",
3015 "SCI",
3016 "",
3017 ConfigInfo::CI_EXPERIMENTAL,
3018 false,
3019 ConfigInfo::CI_INT,
3020 MANDATORY,
3021 "1", "63" },
3022
3023 {
3024 CFG_CONNECTION_HOSTNAME_1,
3025 "HostName1",
3026 "SCI",
3027 "Name/IP of computer on one side of the connection",
3028 ConfigInfo::CI_USED,
3029 false,
3030 ConfigInfo::CI_STRING,
3031 0,
3032 0, 0 },
3033
3034 {
3035 CFG_CONNECTION_HOSTNAME_2,
3036 "HostName2",
3037 "SCI",
3038 "Name/IP of computer on one side of the connection",
3039 ConfigInfo::CI_USED,
3040 false,
3041 ConfigInfo::CI_STRING,
3042 0,
3043 0, 0 },
3044
3045 {
3046 CFG_CONNECTION_SERVER_PORT,
3047 "PortNumber",
3048 "SCI",
3049 0, // No new parameter to use instead of deprecated
3050 ConfigInfo::CI_DEPRECATED,
3051 false,
3052 ConfigInfo::CI_INT,
3053 MANDATORY,
3054 "0",
3055 STR_VALUE(MAX_PORT_NO) },
3056
3057 {
3058 CFG_SCI_HOST1_ID_0,
3059 "Host1SciId0",
3060 "SCI",
3061 "SCI-node id for adapter 0 on Host1 (a computer can have two adapters)",
3062 ConfigInfo::CI_EXPERIMENTAL,
3063 false,
3064 ConfigInfo::CI_INT,
3065 MANDATORY,
3066 "0",
3067 STR_VALUE(MAX_INT_RNIL) },
3068
3069 {
3070 CFG_SCI_HOST1_ID_1,
3071 "Host1SciId1",
3072 "SCI",
3073 "SCI-node id for adapter 1 on Host1 (a computer can have two adapters)",
3074 ConfigInfo::CI_EXPERIMENTAL,
3075 false,
3076 ConfigInfo::CI_INT,
3077 "0",
3078 "0",
3079 STR_VALUE(MAX_INT_RNIL) },
3080
3081 {
3082 CFG_SCI_HOST2_ID_0,
3083 "Host2SciId0",
3084 "SCI",
3085 "SCI-node id for adapter 0 on Host2 (a computer can have two adapters)",
3086 ConfigInfo::CI_EXPERIMENTAL,
3087 false,
3088 ConfigInfo::CI_INT,
3089 MANDATORY,
3090 "0",
3091 STR_VALUE(MAX_INT_RNIL) },
3092
3093 {
3094 CFG_SCI_HOST2_ID_1,
3095 "Host2SciId1",
3096 "SCI",
3097 "SCI-node id for adapter 1 on Host2 (a computer can have two adapters)",
3098 ConfigInfo::CI_EXPERIMENTAL,
3099 false,
3100 ConfigInfo::CI_INT,
3101 "0",
3102 "0",
3103 STR_VALUE(MAX_INT_RNIL) },
3104
3105 {
3106 CFG_CONNECTION_SEND_SIGNAL_ID,
3107 "SendSignalId",
3108 "SCI",
3109 "Sends id in each signal. Used in trace files.",
3110 ConfigInfo::CI_EXPERIMENTAL,
3111 false,
3112 ConfigInfo::CI_BOOL,
3113 "true",
3114 "false",
3115 "true" },
3116
3117 {
3118 CFG_CONNECTION_CHECKSUM,
3119 "Checksum",
3120 "SCI",
3121 "If checksum is enabled, all signals between nodes are checked for errors",
3122 ConfigInfo::CI_EXPERIMENTAL,
3123 false,
3124 ConfigInfo::CI_BOOL,
3125 "false",
3126 "false",
3127 "true" },
3128
3129 {
3130 CFG_SCI_SEND_LIMIT,
3131 "SendLimit",
3132 "SCI",
3133 "Transporter send buffer contents are sent when this no of bytes is buffered",
3134 ConfigInfo::CI_EXPERIMENTAL,
3135 false,
3136 ConfigInfo::CI_INT,
3137 "8K",
3138 "128",
3139 "32K" },
3140
3141 {
3142 CFG_SCI_BUFFER_MEM,
3143 "SharedBufferSize",
3144 "SCI",
3145 "Size of shared memory segment",
3146 ConfigInfo::CI_EXPERIMENTAL,
3147 false,
3148 ConfigInfo::CI_INT,
3149 "1M",
3150 "64K",
3151 STR_VALUE(MAX_INT_RNIL) },
3152
3153 {
3154 CFG_CONNECTION_NODE_1_SYSTEM,
3155 "NodeId1_System",
3156 "SCI",
3157 "System for node 1 in connection",
3158 ConfigInfo::CI_INTERNAL,
3159 false,
3160 ConfigInfo::CI_STRING,
3161 0,
3162 0, 0 },
3163
3164 {
3165 CFG_CONNECTION_NODE_2_SYSTEM,
3166 "NodeId2_System",
3167 "SCI",
3168 "System for node 2 in connection",
3169 ConfigInfo::CI_INTERNAL,
3170 false,
3171 ConfigInfo::CI_STRING,
3172 0,
3173 0, 0 },
3174
3175 {
3176 CFG_CONNECTION_OVERLOAD,
3177 "OverloadLimit",
3178 "SCI",
3179 "Number of unsent bytes that must be in the send buffer before the\n"
3180 "connection is considered overloaded",
3181 ConfigInfo::CI_EXPERIMENTAL,
3182 false,
3183 ConfigInfo::CI_INT,
3184 "0",
3185 "0",
3186 STR_VALUE(MAX_INT_RNIL)
3187 }
3188
3189 };
3190
3191 const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo);
3192
3193 #ifndef NDB_MGMAPI
3194 /****************************************************************************
3195 * Ctor
3196 ****************************************************************************/
3197 #undef require
3198 #define require(x) require_exit_or_core(x, -1)
3199
ConfigInfo()3200 ConfigInfo::ConfigInfo()
3201 : m_info(true), m_systemDefaults(true)
3202 {
3203 int i;
3204 Properties *section;
3205 const Properties *oldpinfo;
3206
3207 for (i=0; i<m_NoOfParams; i++) {
3208 const ParamInfo & param = m_ParamInfo[i];
3209 Uint64 default_uint64;
3210 bool default_bool;
3211
3212 // Create new section if it did not exist
3213 if (!m_info.getCopy(param._section, §ion)) {
3214 Properties newsection(true);
3215 m_info.put(param._section, &newsection);
3216
3217 // Get copy of section
3218 m_info.getCopy(param._section, §ion);
3219 }
3220
3221 // Create pinfo (parameter info) entry
3222 Properties pinfo(true);
3223 pinfo.put("Id", param._paramId);
3224 pinfo.put("Fname", param._fname);
3225 pinfo.put("Description", param._description);
3226
3227 /*
3228 Check that flags are set according to current rules
3229 */
3230 const Uint32 flags = param._flags;
3231 const Uint32 allowed_flags = (CI_ONLINE_UPDATEABLE | CI_CHECK_WRITABLE |
3232 CI_RESTART_SYSTEM | CI_RESTART_INITIAL);
3233 // Check that no other flags then the defined are set
3234 require((flags & ~allowed_flags) == 0);
3235
3236 if (flags & CI_ONLINE_UPDATEABLE)
3237 {
3238 // Check that online updateable parameter does
3239 // not have any CI_RESTART_* flag(s)
3240 require((flags & CI_RESTART_INITIAL) == 0 &&
3241 (flags & CI_RESTART_SYSTEM) == 0);
3242
3243 // Currently no online updatable parameters have been implemented
3244 require(false);
3245 }
3246
3247 // only DB nodes should have CI_RESTART_*
3248 if ((flags & CI_RESTART_INITIAL) || (flags & CI_RESTART_SYSTEM))
3249 require(strcmp(param._section, DB_TOKEN) == 0);
3250
3251 pinfo.put("Flags", flags);
3252
3253 pinfo.put("Type", param._type);
3254
3255 const Status status = param._status;
3256 require(status == CI_USED ||
3257 status == CI_EXPERIMENTAL ||
3258 status == CI_DEPRECATED ||
3259 status == CI_NOTIMPLEMENTED ||
3260 status == CI_INTERNAL);
3261 pinfo.put("Status", status);
3262
3263 switch (param._type) {
3264 case CI_BOOL:
3265 {
3266 bool tmp_bool;
3267 require(InitConfigFileParser::convertStringToBool(param._min, tmp_bool));
3268 pinfo.put64("Min", tmp_bool);
3269 require(InitConfigFileParser::convertStringToBool(param._max, tmp_bool));
3270 pinfo.put64("Max", tmp_bool);
3271
3272 if(param._default == MANDATORY)
3273 pinfo.put("Mandatory", (Uint32)1);
3274 else if(param._default)
3275 {
3276 require(InitConfigFileParser::convertStringToBool(param._default,
3277 tmp_bool));
3278 pinfo.put("Default", tmp_bool);
3279 }
3280
3281 break;
3282 }
3283 case CI_INT:
3284 case CI_INT64:
3285 {
3286 Uint64 tmp_uint64;
3287 require(InitConfigFileParser::convertStringToUint64(param._min, tmp_uint64));
3288 pinfo.put64("Min", tmp_uint64);
3289 require(InitConfigFileParser::convertStringToUint64(param._max, tmp_uint64));
3290 pinfo.put64("Max", tmp_uint64);
3291
3292 if(param._default == MANDATORY)
3293 pinfo.put("Mandatory", (Uint32)1);
3294 else if(param._default)
3295 {
3296 require(InitConfigFileParser::convertStringToUint64(param._default,
3297 tmp_uint64));
3298 pinfo.put64("Default", tmp_uint64);
3299 }
3300 break;
3301 }
3302 case CI_SECTION:
3303 pinfo.put("SectionType", (Uint32)UintPtr(param._default));
3304 break;
3305 case CI_ENUM:
3306 {
3307 assert(param._min); // Enums typelib pointer is stored in _min
3308 assert(param._max == 0); // Enums can't have max
3309
3310 Properties values(true); // case insensitive
3311 // Put the list of allowed enum values in pinfo
3312 for (const Typelib* entry = ConfigInfo::getTypelibPtr(param);
3313 entry->name != 0; entry++)
3314 values.put(entry->name, entry->value);
3315 require(pinfo.put("values", &values));
3316
3317 if(param._default == MANDATORY)
3318 pinfo.put("Mandatory", (Uint32)1);
3319 else if(param._default)
3320 {
3321 /*
3322 Map default value of enum from string to int since
3323 enum is stored as int internally
3324 */
3325 Uint32 default_value;
3326 require(values.get(param._default, &default_value));
3327 require(pinfo.put("Default", default_value));
3328
3329 /* Also store the default as string */
3330 require(pinfo.put("DefaultString", param._default));
3331 }
3332 break;
3333 }
3334 case CI_STRING:
3335 assert(param._min == 0); // String can't have min value
3336 assert(param._max == 0); // String can't have max value
3337
3338 if(param._default == MANDATORY)
3339 pinfo.put("Mandatory", (Uint32)1);
3340 else if(param._default)
3341 pinfo.put("Default", param._default);
3342 break;
3343
3344 case CI_BITMASK:
3345 assert(param._min == 0); // Bitmask can't have min value
3346
3347 Uint64 tmp_uint64;
3348 require(InitConfigFileParser::convertStringToUint64(param._max,
3349 tmp_uint64));
3350 pinfo.put64("Max", tmp_uint64);
3351
3352 if(param._default == MANDATORY)
3353 pinfo.put("Mandatory", (Uint32)1);
3354 else if(param._default)
3355 pinfo.put("Default", param._default);
3356 break;
3357 }
3358
3359 // Check that pinfo is really new
3360 if (section->get(param._fname, &oldpinfo)) {
3361 ndbout << "Error: Parameter " << param._fname
3362 << " defined twice in section " << param._section
3363 << "." << endl;
3364 require(false);
3365 }
3366
3367 // Add new pinfo to section
3368 section->put(param._fname, &pinfo);
3369
3370 // Replace section with modified section
3371 m_info.put(param._section, section, true);
3372 delete section;
3373
3374 if(param._type != ConfigInfo::CI_SECTION){
3375 Properties * p;
3376 if(!m_systemDefaults.getCopy(param._section, &p)){
3377 p = new Properties(true);
3378 }
3379 if(param._default &&
3380 param._default != MANDATORY){
3381 switch (param._type)
3382 {
3383 case CI_SECTION:
3384 break;
3385 case CI_STRING:
3386 case CI_BITMASK:
3387 require(p->put(param._fname, param._default));
3388 break;
3389 case CI_BOOL:
3390 {
3391 require(InitConfigFileParser::convertStringToBool(param._default, default_bool));
3392 require(p->put(param._fname, default_bool));
3393
3394 break;
3395 }
3396 case CI_INT:
3397 case CI_INT64:
3398 {
3399 require(InitConfigFileParser::convertStringToUint64(param._default, default_uint64));
3400 require(p->put64(param._fname, Uint64(default_uint64)));
3401 break;
3402 }
3403 case CI_ENUM:
3404 {
3405 /*
3406 Map default value of enum from string to int since
3407 enum is stored as int internally
3408 */
3409 Uint32 default_value;
3410 require(verify_enum(getInfo(param._section),
3411 param._fname, param._default,
3412 default_value));
3413 require(p->put(param._fname, default_value));
3414 break;
3415 }
3416
3417 }
3418 }
3419 require(m_systemDefaults.put(param._section, p, true));
3420 delete p;
3421 }
3422 }
3423
3424 for (i=0; i<m_NoOfParams; i++) {
3425 if(m_ParamInfo[i]._section == NULL){
3426 ndbout << "Check that each entry has a section failed." << endl;
3427 ndbout << "Parameter \"" << m_ParamInfo[i]._fname << endl;
3428 ndbout << "Edit file " << __FILE__ << "." << endl;
3429 require(false);
3430 }
3431
3432 if(m_ParamInfo[i]._type == ConfigInfo::CI_SECTION)
3433 continue;
3434
3435 const Properties * p = getInfo(m_ParamInfo[i]._section);
3436 if (!p || !p->contains(m_ParamInfo[i]._fname)) {
3437 ndbout << "Check that each pname has an fname failed." << endl;
3438 ndbout << "Parameter \"" << m_ParamInfo[i]._fname
3439 << "\" does not exist in section \""
3440 << m_ParamInfo[i]._section << "\"." << endl;
3441 ndbout << "Edit file " << __FILE__ << "." << endl;
3442 require(false);
3443 }
3444 }
3445
3446 }
3447
3448 /****************************************************************************
3449 * Getters
3450 ****************************************************************************/
warning(const char * src,const char * arg)3451 inline void warning(const char * src, const char * arg){
3452 ndbout << "Illegal call to ConfigInfo::" << src << "() - " << arg << endl;
3453 require(false);
3454 }
3455
3456 const Properties *
getInfo(const char * section) const3457 ConfigInfo::getInfo(const char * section) const {
3458 const Properties * p;
3459 if(!m_info.get(section, &p)){
3460 return 0;
3461 // warning("getInfo", section);
3462 }
3463 return p;
3464 }
3465
3466 const Properties *
getDefaults(const char * section) const3467 ConfigInfo::getDefaults(const char * section) const {
3468 const Properties * p;
3469 if(!m_systemDefaults.get(section, &p)){
3470 return 0;
3471 //warning("getDefaults", section);
3472 }
3473 return p;
3474 }
3475
3476 static
3477 Uint64
getInfoInt(const Properties * section,const char * fname,const char * type)3478 getInfoInt(const Properties * section,
3479 const char* fname, const char * type){
3480 Uint32 val32;
3481 const Properties * p;
3482 if (section->get(fname, &p) && p->get(type, &val32)) {
3483 return val32;
3484 }
3485
3486 Uint64 val64;
3487 if(p && p->get(type, &val64)){
3488 return val64;
3489 }
3490
3491 section->print();
3492 if(section->get(fname, &p)){
3493 p->print();
3494 }
3495
3496 warning(type, fname);
3497 return 0;
3498 }
3499
3500 static
3501 const char *
getInfoString(const Properties * section,const char * fname,const char * type)3502 getInfoString(const Properties * section,
3503 const char* fname, const char * type){
3504 const char* val;
3505 const Properties * p;
3506 if (section->get(fname, &p) && p->get(type, &val)) {
3507 return val;
3508 }
3509 warning(type, fname);
3510 return val;
3511 }
3512
3513 Uint64
getMax(const Properties * section,const char * fname) const3514 ConfigInfo::getMax(const Properties * section, const char* fname) const {
3515 return getInfoInt(section, fname, "Max");
3516 }
3517
3518 Uint64
getMin(const Properties * section,const char * fname) const3519 ConfigInfo::getMin(const Properties * section, const char* fname) const {
3520 return getInfoInt(section, fname, "Min");
3521 }
3522
3523 Uint64
getDefault(const Properties * section,const char * fname) const3524 ConfigInfo::getDefault(const Properties * section, const char* fname) const {
3525 return getInfoInt(section, fname, "Default");
3526 }
3527
3528 const char*
getDefaultString(const Properties * section,const char * fname) const3529 ConfigInfo::getDefaultString(const Properties * section,
3530 const char* fname) const
3531 {
3532 switch (getType(section, fname))
3533 {
3534 case ConfigInfo::CI_BITMASK:
3535 case ConfigInfo::CI_STRING:
3536 return getInfoString(section, fname, "Default");
3537
3538 case ConfigInfo::CI_ENUM:
3539 {
3540 /*
3541 Default value for enum are stored as int internally
3542 but also stores the orignal string, use different
3543 key to get at the default value as string
3544 */
3545 return getInfoString(section, fname, "DefaultString");
3546 }
3547
3548 default:
3549 require(false);
3550 }
3551
3552 return NULL;
3553 }
3554
3555 bool
hasDefault(const Properties * section,const char * fname) const3556 ConfigInfo::hasDefault(const Properties * section, const char* fname) const {
3557 const Properties * p;
3558 require(section->get(fname, &p));
3559 return p->contains("Default");
3560 }
3561
3562 bool
getMandatory(const Properties * section,const char * fname) const3563 ConfigInfo::getMandatory(const Properties * section, const char* fname) const {
3564 const Properties * p;
3565 require(section->get(fname, &p));
3566 return p->contains("Mandatory");
3567 }
3568
3569 const char*
getDescription(const Properties * section,const char * fname) const3570 ConfigInfo::getDescription(const Properties * section,
3571 const char* fname) const {
3572 return getInfoString(section, fname, "Description");
3573 }
3574
3575 bool
isSection(const char * section) const3576 ConfigInfo::isSection(const char * section) const {
3577 for (int i = 0; i<m_noOfSectionNames; i++) {
3578 if(!strcasecmp(section, m_sectionNames[i])) return true;
3579 }
3580 return false;
3581 }
3582
3583 const char*
nameToAlias(const char * name)3584 ConfigInfo::nameToAlias(const char * name) {
3585 for (int i = 0; m_sectionNameAliases[i].name != 0; i++)
3586 if(!strcasecmp(name, m_sectionNameAliases[i].name))
3587 return m_sectionNameAliases[i].alias;
3588 return 0;
3589 }
3590
3591 const char*
getAlias(const char * section)3592 ConfigInfo::getAlias(const char * section) {
3593 for (int i = 0; m_sectionNameAliases[i].name != 0; i++)
3594 if(!strcasecmp(section, m_sectionNameAliases[i].alias))
3595 return m_sectionNameAliases[i].name;
3596 return 0;
3597 }
3598
3599 const char*
sectionName(Uint32 section_type,Uint32 type) const3600 ConfigInfo::sectionName(Uint32 section_type, Uint32 type) const {
3601
3602 switch (section_type){
3603 case CFG_SECTION_SYSTEM:
3604 return "SYSTEM";
3605 break;
3606
3607 case CFG_SECTION_NODE:
3608 switch(type){
3609 case NODE_TYPE_DB:
3610 return DB_TOKEN_PRINT;
3611 break;
3612 case NODE_TYPE_MGM:
3613 return MGM_TOKEN_PRINT;
3614 break;
3615 case NODE_TYPE_API:
3616 return API_TOKEN_PRINT;
3617 break;
3618 default:
3619 assert(false);
3620 break;
3621 }
3622 break;
3623
3624 case CFG_SECTION_CONNECTION:
3625 switch(type){
3626 case CONNECTION_TYPE_TCP:
3627 return "TCP";
3628 break;
3629 case CONNECTION_TYPE_SHM:
3630 return "SHM";
3631 break;
3632 case CONNECTION_TYPE_SCI:
3633 return "SCI";
3634 break;
3635 default:
3636 assert(false);
3637 break;
3638 }
3639 break;
3640
3641 default:
3642 assert(false);
3643 break;
3644 }
3645
3646 return "<unknown section>";
3647 }
3648
3649 const ConfigInfo::AliasPair
3650 section2PrimaryKeys[]={
3651 {API_TOKEN, "NodeId"},
3652 {DB_TOKEN, "NodeId"},
3653 {MGM_TOKEN, "NodeId"},
3654 {"TCP", "NodeId1,NodeId2"},
3655 {"SCI", "NodeId1,NodeId2"},
3656 {"SHM", "NodeId1,NodeId2"},
3657 {0, 0}
3658 };
3659
3660 static const char*
sectionPrimaryKeys(const char * name)3661 sectionPrimaryKeys(const char * name) {
3662 for (int i = 0; section2PrimaryKeys[i].name != 0; i++)
3663 if(!strcasecmp(name, section2PrimaryKeys[i].name))
3664 return section2PrimaryKeys[i].alias;
3665 return 0;
3666 }
3667
3668 bool
verify(const Properties * section,const char * fname,Uint64 value) const3669 ConfigInfo::verify(const Properties * section, const char* fname,
3670 Uint64 value) const {
3671 Uint64 min, max;
3672
3673 min = getInfoInt(section, fname, "Min");
3674 max = getInfoInt(section, fname, "Max");
3675 if(min > max){
3676 warning("verify", fname);
3677 }
3678 if (value >= min && value <= max)
3679 return true;
3680 else
3681 return false;
3682 }
3683
3684
3685 bool
verify_enum(const Properties * section,const char * fname,const char * value,Uint32 & value_int) const3686 ConfigInfo::verify_enum(const Properties * section, const char* fname,
3687 const char* value, Uint32& value_int) const {
3688 const Properties * p;
3689 const Properties * values;
3690 require(section->get(fname, &p));
3691 require(p->get("values", &values));
3692
3693 if (values->get(value, &value_int))
3694 return true;
3695 return false;
3696 }
3697
3698
3699 void
get_enum_values(const Properties * section,const char * fname,BaseString & list) const3700 ConfigInfo::get_enum_values(const Properties * section, const char* fname,
3701 BaseString& list) const {
3702 const Properties * p;
3703 const Properties * values;
3704 require(section->get(fname, &p));
3705 require(p->get("values", &values));
3706
3707 const char* separator = "";
3708 Properties::Iterator it(values);
3709 for (const char* name = it.first(); name != NULL; name = it.next())
3710 {
3711 list.appfmt("%s%s", separator, name);
3712 separator = " ";
3713 }
3714 }
3715
3716
3717 ConfigInfo::Type
getType(const Properties * section,const char * fname) const3718 ConfigInfo::getType(const Properties * section, const char* fname) const {
3719 return (ConfigInfo::Type) getInfoInt(section, fname, "Type");
3720 }
3721
3722 ConfigInfo::Status
getStatus(const Properties * section,const char * fname) const3723 ConfigInfo::getStatus(const Properties * section, const char* fname) const {
3724 return (ConfigInfo::Status) getInfoInt(section, fname, "Status");
3725 }
3726
3727 Uint32
getFlags(const Properties * section,const char * fname) const3728 ConfigInfo::getFlags(const Properties* section, const char* fname) const {
3729 return (Uint32)getInfoInt(section, fname, "Flags");
3730 }
3731
3732 /****************************************************************************
3733 * Printers
3734 ****************************************************************************/
3735
3736 class ConfigPrinter {
3737 protected:
3738 FILE* m_out;
3739 public:
ConfigPrinter(FILE * out=stdout)3740 ConfigPrinter(FILE* out = stdout) :
3741 m_out(out)
3742 {}
~ConfigPrinter()3743 virtual ~ConfigPrinter() {};
3744
start()3745 virtual void start() {}
end()3746 virtual void end() {}
3747
section_start(const char * name,const char * alias,const char * primarykeys=NULL)3748 virtual void section_start(const char* name, const char* alias,
3749 const char* primarykeys = NULL) {}
section_end(const char * name)3750 virtual void section_end(const char* name) {}
3751
parameter(const char * section_name,const Properties * section,const char * param_name,const ConfigInfo & info)3752 virtual void parameter(const char* section_name,
3753 const Properties* section,
3754 const char* param_name,
3755 const ConfigInfo& info){}
3756 };
3757
3758
3759 class PrettyPrinter : public ConfigPrinter {
3760 public:
PrettyPrinter(FILE * out=stdout)3761 PrettyPrinter(FILE* out = stdout) : ConfigPrinter(out) {}
~PrettyPrinter()3762 virtual ~PrettyPrinter() {}
3763
section_start(const char * name,const char * alias,const char * primarykeys=NULL)3764 virtual void section_start(const char* name, const char* alias,
3765 const char* primarykeys = NULL) {
3766 fprintf(m_out, "****** %s ******\n\n", name);
3767 }
3768
parameter(const char * section_name,const Properties * section,const char * param_name,const ConfigInfo & info)3769 virtual void parameter(const char* section_name,
3770 const Properties* section,
3771 const char* param_name,
3772 const ConfigInfo& info){
3773 switch (info.getType(section, param_name)) {
3774 case ConfigInfo::CI_BOOL:
3775 fprintf(m_out, "%s (Boolean value)\n", param_name);
3776 fprintf(m_out, "%s\n", info.getDescription(section, param_name));
3777
3778 if (info.getMandatory(section, param_name))
3779 fprintf(m_out, "MANDATORY (Legal values: Y, N)\n");
3780 else if (info.hasDefault(section, param_name))
3781 {
3782 if (info.getDefault(section, param_name) == false)
3783 fprintf(m_out, "Default: N (Legal values: Y, N)\n");
3784 else if (info.getDefault(section, param_name) == true)
3785 fprintf(m_out, "Default: Y (Legal values: Y, N)\n");
3786 else
3787 fprintf(m_out, "UNKNOWN\n");
3788 }
3789 fprintf(m_out, "\n");
3790 break;
3791
3792 case ConfigInfo::CI_INT:
3793 case ConfigInfo::CI_INT64:
3794 fprintf(m_out, "%s (Non-negative Integer)\n", param_name);
3795 fprintf(m_out, "%s\n", info.getDescription(section, param_name));
3796 if (info.getMandatory(section, param_name))
3797 fprintf(m_out, "MANDATORY (");
3798 else if (info.hasDefault(section, param_name))
3799 fprintf(m_out, "Default: %llu (",
3800 info.getDefault(section, param_name));
3801 else
3802 fprintf(m_out, "(");
3803 fprintf(m_out, "Min: %llu, ", info.getMin(section, param_name));
3804 fprintf(m_out, "Max: %llu)\n", info.getMax(section, param_name));
3805 fprintf(m_out, "\n");
3806 break;
3807
3808 case ConfigInfo::CI_BITMASK:
3809 case ConfigInfo::CI_ENUM:
3810 case ConfigInfo::CI_STRING:
3811 fprintf(m_out, "%s (String)\n", param_name);
3812 fprintf(m_out, "%s\n", info.getDescription(section, param_name));
3813 if (info.getMandatory(section, param_name))
3814 fprintf(m_out, "MANDATORY\n");
3815 else if (info.hasDefault(section, param_name))
3816 fprintf(m_out, "Default: %s\n",
3817 info.getDefaultString(section, param_name));
3818 fprintf(m_out, "\n");
3819 break;
3820 case ConfigInfo::CI_SECTION:
3821 break;
3822 }
3823 }
3824 };
3825
3826
3827 class XMLPrinter : public ConfigPrinter {
3828 int m_indent;
3829
print_xml(const char * name,const Properties & pairs,bool close=true)3830 void print_xml(const char* name, const Properties& pairs,
3831 bool close = true) {
3832 const char* value;
3833 Properties::Iterator it(&pairs);
3834 for (int i= 0; i < m_indent; i++)
3835 fprintf(m_out, " ");
3836 fprintf(m_out, "<%s", name);
3837 for (const char* name = it.first(); name != NULL; name = it.next()) {
3838 require(pairs.get(name, &value));
3839 fprintf(m_out, " %s=\"%s\"", name, value);
3840 }
3841 if (close)
3842 fprintf(m_out, "/");
3843 fprintf(m_out, ">\n");
3844 }
3845
3846 public:
XMLPrinter(FILE * out=stdout)3847 XMLPrinter(FILE* out = stdout) : ConfigPrinter(out), m_indent(0) {}
~XMLPrinter()3848 virtual ~XMLPrinter() {
3849 assert(m_indent == 0);
3850 }
3851
start()3852 virtual void start() {
3853 BaseString buf;
3854 Properties pairs;
3855 pairs.put("protocolversion", "1");
3856 pairs.put("ndbversionstring", ndbGetOwnVersionString());
3857 Uint32 ndbversion = ndbGetOwnVersion();
3858 buf.assfmt("%u", ndbversion);
3859 pairs.put("ndbversion", buf.c_str());
3860 buf.assfmt("%u", ndbGetMajor(ndbversion));
3861 pairs.put("ndbversionmajor", buf.c_str());
3862 buf.assfmt("%u", ndbGetMinor(ndbversion));
3863 pairs.put("ndbversionminor", buf.c_str());
3864 buf.assfmt("%u", ndbGetBuild(ndbversion));
3865 pairs.put("ndbversionbuild", buf.c_str());
3866
3867 print_xml("configvariables", pairs, false);
3868 m_indent++;
3869 }
end()3870 virtual void end() {
3871 m_indent--;
3872 Properties pairs;
3873 print_xml("/configvariables", pairs, false);
3874 }
3875
section_start(const char * name,const char * alias,const char * primarykeys=NULL)3876 virtual void section_start(const char* name, const char* alias,
3877 const char* primarykeys = NULL) {
3878 Properties pairs;
3879 pairs.put("name", alias ? alias : name);
3880 if (primarykeys)
3881 pairs.put("primarykeys", primarykeys);
3882 print_xml("section", pairs, false);
3883 m_indent++;
3884 }
section_end(const char * name)3885 virtual void section_end(const char* name) {
3886 m_indent--;
3887 Properties pairs;
3888 print_xml("/section", pairs, false);
3889 }
3890
parameter(const char * section_name,const Properties * section,const char * param_name,const ConfigInfo & info)3891 virtual void parameter(const char* section_name,
3892 const Properties* section,
3893 const char* param_name,
3894 const ConfigInfo& info){
3895 BaseString buf;
3896 Properties pairs;
3897 pairs.put("name", param_name);
3898 pairs.put("comment", info.getDescription(section, param_name));
3899
3900 switch (info.getType(section, param_name)) {
3901 case ConfigInfo::CI_BOOL:
3902 pairs.put("type", "bool");
3903
3904 if (info.getMandatory(section, param_name))
3905 pairs.put("mandatory", "true");
3906 else if (info.hasDefault(section, param_name))
3907 {
3908 if (info.getDefault(section, param_name) == false)
3909 pairs.put("default", "false");
3910 else if (info.getDefault(section, param_name) == true)
3911 pairs.put("default", "true");
3912 }
3913 break;
3914
3915 case ConfigInfo::CI_INT:
3916 case ConfigInfo::CI_INT64:
3917 pairs.put("type", "unsigned");
3918
3919 if (info.getMandatory(section, param_name))
3920 pairs.put("mandatory", "true");
3921 else if (info.hasDefault(section, param_name))
3922 {
3923 buf.assfmt("%llu", info.getDefault(section, param_name));
3924 pairs.put("default", buf.c_str());
3925 }
3926 buf.assfmt("%llu", info.getMin(section, param_name));
3927 pairs.put("min", buf.c_str());
3928 buf.assfmt("%llu", info.getMax(section, param_name));
3929 pairs.put("max", buf.c_str());
3930 break;
3931
3932 case ConfigInfo::CI_BITMASK:
3933 case ConfigInfo::CI_ENUM:
3934 case ConfigInfo::CI_STRING:
3935 pairs.put("type", "string");
3936
3937 if (info.getMandatory(section, param_name))
3938 pairs.put("mandatory", "true");
3939 else if (info.hasDefault(section, param_name))
3940 pairs.put("default", info.getDefaultString(section, param_name));
3941 break;
3942
3943 case ConfigInfo::CI_SECTION:
3944 return; // Don't print anything for the section itself
3945 }
3946
3947 // Get "check" flag(s)
3948 Uint32 flags = info.getFlags(section, param_name);
3949 buf.clear();
3950 if (flags & ConfigInfo::CI_CHECK_WRITABLE)
3951 buf.append("writable");
3952
3953 if (buf.length())
3954 pairs.put("check", buf.c_str());
3955
3956 // Get "restart" flag
3957 if (flags & ConfigInfo::CI_RESTART_SYSTEM)
3958 pairs.put("restart", "system");
3959
3960 // Get "initial" flag
3961 if (flags & ConfigInfo::CI_RESTART_INITIAL)
3962 pairs.put("initial", "true");
3963
3964 // Get "supported" flag
3965 Uint32 status = info.getStatus(section, param_name);
3966 buf.clear();
3967 if (status & ConfigInfo::CI_EXPERIMENTAL)
3968 buf.append("experimental");
3969
3970 if (buf.length())
3971 pairs.put("supported", buf.c_str());
3972
3973 print_xml("param", pairs);
3974 }
3975 };
3976
print(const char * section) const3977 void ConfigInfo::print(const char* section) const {
3978 PrettyPrinter pretty_printer;
3979 print_impl(section, pretty_printer);
3980 }
3981
print_xml(const char * section) const3982 void ConfigInfo::print_xml(const char* section) const {
3983 XMLPrinter xml_printer;
3984 print_impl(section, xml_printer);
3985 }
3986
3987
3988 bool
is_internal_section(const Properties * sec) const3989 ConfigInfo::is_internal_section(const Properties* sec) const
3990 {
3991 /* Check if the section is marked as internal */
3992 Properties::Iterator it(sec);
3993 for (const char* n = it.first(); n != NULL; n = it.next()) {
3994 if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL &&
3995 getType(sec, n) == ConfigInfo:: CI_SECTION)
3996 return true;
3997 }
3998 return false;
3999 }
4000
4001
print_impl(const char * section_filter,ConfigPrinter & printer) const4002 void ConfigInfo::print_impl(const char* section_filter,
4003 ConfigPrinter& printer) const {
4004 printer.start();
4005 /* Iterate through all sections */
4006 Properties::Iterator it(&m_info);
4007 for (const char* s = it.first(); s != NULL; s = it.next()) {
4008 if (section_filter && strcmp(section_filter, s))
4009 continue; // Skip this section
4010
4011 const Properties * sec = getInfo(s);
4012
4013 if (is_internal_section(sec))
4014 continue; // Skip whole section
4015
4016 const char* section_alias = nameToAlias(s);
4017 printer.section_start(s, section_alias, sectionPrimaryKeys(s));
4018
4019 /* Iterate through all parameters in section */
4020 Properties::Iterator it(sec);
4021 for (const char* n = it.first(); n != NULL; n = it.next()) {
4022 // Skip entries with different F- and P-names
4023 if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL) continue;
4024 if (getStatus(sec, n) == ConfigInfo::CI_DEPRECATED) continue;
4025 if (getStatus(sec, n) == ConfigInfo::CI_NOTIMPLEMENTED) continue;
4026 printer.parameter(s, sec, n, *this);
4027 }
4028 printer.section_end(s);
4029
4030 // Print [<section> DEFAULT] for all sections but SYSTEM
4031 if (strcmp(s, "SYSTEM") == 0)
4032 continue; // Skip SYSTEM section
4033
4034 BaseString default_section_name;
4035 default_section_name.assfmt("%s %s",
4036 section_alias ? section_alias : s,
4037 "DEFAULT");
4038 printer.section_start(s, default_section_name.c_str());
4039
4040 /* Iterate through all parameters in section */
4041 for (const char* n = it.first(); n != NULL; n = it.next()) {
4042 // Skip entries with different F- and P-names
4043 if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL) continue;
4044 if (getStatus(sec, n) == ConfigInfo::CI_DEPRECATED) continue;
4045 if (getStatus(sec, n) == ConfigInfo::CI_NOTIMPLEMENTED) continue;
4046 printer.parameter(s, sec, n, *this);
4047 }
4048 printer.section_end(s);
4049
4050 }
4051 printer.end();
4052 }
4053
4054
4055
4056 /****************************************************************************
4057 * Section Rules
4058 ****************************************************************************/
4059
4060 /**
4061 * Node rule: Add "Type" and update "NoOfNodes"
4062 */
4063 bool
transformNode(InitConfigFileParser::Context & ctx,const char * data)4064 transformNode(InitConfigFileParser::Context & ctx, const char * data){
4065
4066 Uint32 id, line;
4067 if(!ctx.m_currentSection->get("NodeId", &id) && !ctx.m_currentSection->get("Id", &id)){
4068 Uint32 nextNodeId= 1;
4069 ctx.m_userProperties.get("NextNodeId", &nextNodeId);
4070 id= nextNodeId;
4071 while (ctx.m_userProperties.get("AllocatedNodeId_", id, &line))
4072 id++;
4073 if (id != nextNodeId)
4074 {
4075 fprintf(stderr,"Cluster configuration warning line %d: "
4076 "Could not use next node id %d for section [%s], "
4077 "using next unused node id %d.\n",
4078 ctx.m_sectionLineno, nextNodeId, ctx.fname, id);
4079 }
4080 ctx.m_currentSection->put("NodeId", id);
4081 } else if(ctx.m_userProperties.get("AllocatedNodeId_", id, &line)) {
4082 ctx.reportError("Duplicate nodeid in section "
4083 "[%s] starting at line: %d. Previously used on line %d.",
4084 ctx.fname, ctx.m_sectionLineno, line);
4085 return false;
4086 }
4087
4088 if(id >= MAX_NODES)
4089 {
4090 ctx.reportError("too many nodes configured, only up to %d nodes supported.",
4091 MAX_NODES);
4092 return false;
4093 }
4094
4095 // next node id _always_ next numbers after last used id
4096 ctx.m_userProperties.put("NextNodeId", id+1, true);
4097
4098 ctx.m_userProperties.put("AllocatedNodeId_", id, ctx.m_sectionLineno);
4099 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id);
4100
4101 ctx.m_currentSection->put("Type", ctx.fname);
4102
4103 Uint32 nodes = 0;
4104 ctx.m_userProperties.get("NoOfNodes", &nodes);
4105 ctx.m_userProperties.put("NoOfNodes", ++nodes, true);
4106
4107 /**
4108 * Update count (per type)
4109 */
4110 nodes = 0;
4111 ctx.m_userProperties.get(ctx.fname, &nodes);
4112 ctx.m_userProperties.put(ctx.fname, ++nodes, true);
4113
4114 return true;
4115 }
4116
checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx,const char * data)4117 static bool checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx, const char * data)
4118 {
4119 DBUG_ENTER("checkLocalhostHostnameMix");
4120 const char * hostname= 0;
4121 ctx.m_currentSection->get("HostName", &hostname);
4122 if (hostname == 0 || hostname[0] == 0)
4123 DBUG_RETURN(true);
4124
4125 Uint32 localhost_used= 0;
4126 if(!strcmp(hostname, "localhost") || !strcmp(hostname, "127.0.0.1")){
4127 localhost_used= 1;
4128 ctx.m_userProperties.put("$computer-localhost-used", localhost_used);
4129 if(!ctx.m_userProperties.get("$computer-localhost", &hostname))
4130 DBUG_RETURN(true);
4131 } else {
4132 ctx.m_userProperties.get("$computer-localhost-used", &localhost_used);
4133 ctx.m_userProperties.put("$computer-localhost", hostname);
4134 }
4135
4136 if (localhost_used) {
4137 ctx.reportError("Mixing of localhost (default for [NDBD]HostName) with other hostname(%s) is illegal",
4138 hostname);
4139 DBUG_RETURN(false);
4140 }
4141
4142 DBUG_RETURN(true);
4143 }
4144
4145 bool
fixNodeHostname(InitConfigFileParser::Context & ctx,const char * data)4146 fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data)
4147 {
4148 const char * hostname;
4149 DBUG_ENTER("fixNodeHostname");
4150
4151 if (ctx.m_currentSection->get("HostName", &hostname))
4152 DBUG_RETURN(checkLocalhostHostnameMix(ctx,0));
4153
4154 const char * compId;
4155 if(!ctx.m_currentSection->get("ExecuteOnComputer", &compId))
4156 DBUG_RETURN(true);
4157
4158 const Properties * computer;
4159 char tmp[255];
4160 BaseString::snprintf(tmp, sizeof(tmp), "Computer_%s", compId);
4161 if(!ctx.m_config->get(tmp, &computer)){
4162 ctx.reportError("Computer \"%s\" not declared"
4163 "- [%s] starting at line: %d",
4164 compId, ctx.fname, ctx.m_sectionLineno);
4165 DBUG_RETURN(false);
4166 }
4167
4168 if(!computer->get("HostName", &hostname)){
4169 ctx.reportError("HostName missing in [COMPUTER] (Id: %s) "
4170 " - [%s] starting at line: %d",
4171 compId, ctx.fname, ctx.m_sectionLineno);
4172 DBUG_RETURN(false);
4173 }
4174
4175 require(ctx.m_currentSection->put("HostName", hostname));
4176 DBUG_RETURN(checkLocalhostHostnameMix(ctx,0));
4177 }
4178
4179 bool
fixFileSystemPath(InitConfigFileParser::Context & ctx,const char * data)4180 fixFileSystemPath(InitConfigFileParser::Context & ctx, const char * data){
4181 DBUG_ENTER("fixFileSystemPath");
4182
4183 const char * path;
4184 if (ctx.m_currentSection->get("FileSystemPath", &path))
4185 DBUG_RETURN(true);
4186
4187 if (ctx.m_currentSection->get("DataDir", &path)) {
4188 require(ctx.m_currentSection->put("FileSystemPath", path));
4189 DBUG_RETURN(true);
4190 }
4191
4192 require(false);
4193 DBUG_RETURN(false);
4194 }
4195
4196 bool
fixBackupDataDir(InitConfigFileParser::Context & ctx,const char * data)4197 fixBackupDataDir(InitConfigFileParser::Context & ctx, const char * data){
4198
4199 const char * path;
4200 if (ctx.m_currentSection->get("BackupDataDir", &path))
4201 return true;
4202
4203 if (ctx.m_currentSection->get("FileSystemPath", &path)) {
4204 require(ctx.m_currentSection->put("BackupDataDir", path));
4205 return true;
4206 }
4207
4208 require(false);
4209 return false;
4210 }
4211
4212 /**
4213 * Connection rule: Check support of connection
4214 */
4215 bool
checkConnectionSupport(InitConfigFileParser::Context & ctx,const char * data)4216 checkConnectionSupport(InitConfigFileParser::Context & ctx, const char * data)
4217 {
4218 int error= 0;
4219 if (strcasecmp("TCP",ctx.fname) == 0)
4220 {
4221 // always enabled
4222 }
4223 else if (strcasecmp("SHM",ctx.fname) == 0)
4224 {
4225 #ifndef NDB_SHM_TRANSPORTER
4226 error= 1;
4227 #endif
4228 }
4229 else if (strcasecmp("SCI",ctx.fname) == 0)
4230 {
4231 #ifndef NDB_SCI_TRANSPORTER
4232 error= 1;
4233 #endif
4234 }
4235
4236 if (error)
4237 {
4238 ctx.reportError("Binary not compiled with this connection support, "
4239 "[%s] starting at line: %d",
4240 ctx.fname, ctx.m_sectionLineno);
4241 return false;
4242 }
4243 return true;
4244 }
4245
4246 /**
4247 * Connection rule: Update "NoOfConnections"
4248 */
4249 bool
transformConnection(InitConfigFileParser::Context & ctx,const char * data)4250 transformConnection(InitConfigFileParser::Context & ctx, const char * data)
4251 {
4252 Uint32 connections = 0;
4253 ctx.m_userProperties.get("NoOfConnections", &connections);
4254 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Connection_%d", connections);
4255 ctx.m_userProperties.put("NoOfConnections", ++connections, true);
4256
4257 ctx.m_currentSection->put("Type", ctx.fname);
4258 return true;
4259 }
4260
4261 /**
4262 * System rule: Just add it
4263 */
4264 bool
transformSystem(InitConfigFileParser::Context & ctx,const char * data)4265 transformSystem(InitConfigFileParser::Context & ctx, const char * data){
4266
4267 const char * name;
4268 if(!ctx.m_currentSection->get("Name", &name)){
4269 ctx.reportError("Mandatory parameter Name missing from section "
4270 "[%s] starting at line: %d",
4271 ctx.fname, ctx.m_sectionLineno);
4272 return false;
4273 }
4274
4275 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name);
4276
4277 ctx.m_currentSection->put("Type", ctx.fname);
4278
4279 return true;
4280 }
4281
4282 /**
4283 * Computer rule: Update "NoOfComputers", add "Type"
4284 */
4285 bool
transformComputer(InitConfigFileParser::Context & ctx,const char * data)4286 transformComputer(InitConfigFileParser::Context & ctx, const char * data){
4287 const char * id;
4288 if(!ctx.m_currentSection->get("Id", &id)){
4289 ctx.reportError("Mandatory parameter Id missing from section "
4290 "[%s] starting at line: %d",
4291 ctx.fname, ctx.m_sectionLineno);
4292 return false;
4293 }
4294 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Computer_%s", id);
4295
4296 Uint32 computers = 0;
4297 ctx.m_userProperties.get("NoOfComputers", &computers);
4298 ctx.m_userProperties.put("NoOfComputers", ++computers, true);
4299
4300 const char * hostname = 0;
4301 ctx.m_currentSection->get("HostName", &hostname);
4302 if(!hostname){
4303 return true;
4304 }
4305
4306 return checkLocalhostHostnameMix(ctx,0);
4307 }
4308
4309 /**
4310 * Apply default values
4311 */
4312 void
applyDefaultValues(InitConfigFileParser::Context & ctx,const Properties * defaults)4313 applyDefaultValues(InitConfigFileParser::Context & ctx,
4314 const Properties * defaults)
4315 {
4316 DBUG_ENTER("applyDefaultValues");
4317 if(defaults != NULL){
4318 Properties::Iterator it(defaults);
4319
4320 for(const char * name = it.first(); name != NULL; name = it.next()){
4321 (void) ctx.m_info->getStatus(ctx.m_currentInfo, name);
4322 if(!ctx.m_currentSection->contains(name)){
4323 switch (ctx.m_info->getType(ctx.m_currentInfo, name)){
4324 case ConfigInfo::CI_ENUM:
4325 case ConfigInfo::CI_INT:
4326 case ConfigInfo::CI_BOOL:{
4327 Uint32 val = 0;
4328 require(defaults->get(name, &val));
4329 ctx.m_currentSection->put(name, val);
4330 DBUG_PRINT("info",("%s=%d #default",name,val));
4331 break;
4332 }
4333 case ConfigInfo::CI_INT64:{
4334 Uint64 val = 0;
4335 require(defaults->get(name, &val));
4336 ctx.m_currentSection->put64(name, val);
4337 DBUG_PRINT("info",("%s=%lld #default",name,val));
4338 break;
4339 }
4340 case ConfigInfo::CI_BITMASK:
4341 case ConfigInfo::CI_STRING:{
4342 const char * val;
4343 require(defaults->get(name, &val));
4344 ctx.m_currentSection->put(name, val);
4345 DBUG_PRINT("info",("%s=%s #default",name,val));
4346 break;
4347 }
4348 case ConfigInfo::CI_SECTION:
4349 break;
4350 }
4351 }
4352 #ifndef DBUG_OFF
4353 else
4354 {
4355 switch (ctx.m_info->getType(ctx.m_currentInfo, name)){
4356 case ConfigInfo::CI_ENUM:
4357 case ConfigInfo::CI_INT:
4358 case ConfigInfo::CI_BOOL:{
4359 Uint32 val = 0;
4360 require(ctx.m_currentSection->get(name, &val));
4361 DBUG_PRINT("info",("%s=%d",name,val));
4362 break;
4363 }
4364 case ConfigInfo::CI_INT64:{
4365 Uint64 val = 0;
4366 require(ctx.m_currentSection->get(name, &val));
4367 DBUG_PRINT("info",("%s=%lld",name,val));
4368 break;
4369 }
4370 case ConfigInfo::CI_BITMASK:
4371 case ConfigInfo::CI_STRING:{
4372 const char * val;
4373 require(ctx.m_currentSection->get(name, &val));
4374 DBUG_PRINT("info",("%s=%s",name,val));
4375 break;
4376 }
4377 case ConfigInfo::CI_SECTION:
4378 break;
4379 }
4380 }
4381 #endif
4382 }
4383 }
4384 DBUG_VOID_RETURN;
4385 }
4386
4387 bool
applyDefaultValues(InitConfigFileParser::Context & ctx,const char * data)4388 applyDefaultValues(InitConfigFileParser::Context & ctx, const char * data){
4389
4390 if(strcmp(data, "user") == 0)
4391 applyDefaultValues(ctx, ctx.m_userDefaults);
4392 else if (strcmp(data, "system") == 0)
4393 applyDefaultValues(ctx, ctx.m_systemDefaults);
4394 else
4395 return false;
4396
4397 return true;
4398 }
4399
4400 /**
4401 * Check that a section contains all MANDATORY parameters
4402 */
4403 bool
checkMandatory(InitConfigFileParser::Context & ctx,const char * data)4404 checkMandatory(InitConfigFileParser::Context & ctx, const char * data){
4405
4406 Properties::Iterator it(ctx.m_currentInfo);
4407 for(const char * name = it.first(); name != NULL; name = it.next()){
4408 const Properties * info = NULL;
4409 require(ctx.m_currentInfo->get(name, &info));
4410 Uint32 val;
4411 if(info->get("Mandatory", &val)){
4412 const char * fname;
4413 require(info->get("Fname", &fname));
4414 if(!ctx.m_currentSection->contains(fname)){
4415 ctx.reportError("Mandatory parameter %s missing from section "
4416 "[%s] starting at line: %d",
4417 fname, ctx.fname, ctx.m_sectionLineno);
4418 return false;
4419 }
4420 }
4421 }
4422 return true;
4423 }
4424
4425 /**
4426 * Connection rule: Fix node id
4427 *
4428 * Transform a string "NodeidX" (e.g. "uppsala.32")
4429 * into a Uint32 "NodeIdX" (e.g. 32) and a string "SystemX" (e.g. "uppsala").
4430 */
fixNodeId(InitConfigFileParser::Context & ctx,const char * data)4431 static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
4432 {
4433 char buf[] = "NodeIdX"; buf[6] = data[sizeof("NodeI")];
4434 char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("NodeI")];
4435 const char* nodeId;
4436 if(!ctx.m_currentSection->get(buf, &nodeId))
4437 {
4438 ctx.reportError("Mandatory parameter %s missing from section"
4439 "[%s] starting at line: %d",
4440 buf, ctx.fname, ctx.m_sectionLineno);
4441 return false;
4442 }
4443
4444 BaseString str(nodeId);
4445 Vector<BaseString> token_list;
4446 int tokens = str.split(token_list, ".", 2);
4447
4448 Uint32 id;
4449
4450 if (tokens == 0)
4451 {
4452 ctx.reportError("Value for mandatory parameter %s missing from section "
4453 "[%s] starting at line: %d",
4454 buf, ctx.fname, ctx.m_sectionLineno);
4455 return false;
4456 }
4457
4458 const char* token1 = token_list[0].c_str();
4459 if (tokens == 1) { // Only a number given
4460 errno = 0;
4461 char* p;
4462 id = strtol(token1, &p, 10);
4463 if (errno != 0 || id <= 0x0 || id > MAX_NODES)
4464 {
4465 ctx.reportError("Illegal value for mandatory parameter %s from section "
4466 "[%s] starting at line: %d",
4467 buf, ctx.fname, ctx.m_sectionLineno);
4468 return false;
4469 }
4470 require(ctx.m_currentSection->put(buf, id, true));
4471 } else { // A pair given (e.g. "uppsala.32")
4472 assert(tokens == 2 && token_list.size() == 2);
4473 const char* token2 = token_list[1].c_str();
4474
4475 errno = 0;
4476 char* p;
4477 id = strtol(token2, &p, 10);
4478 if (errno != 0 || id <= 0x0 || id > MAX_NODES)
4479 {
4480 ctx.reportError("Illegal value for mandatory parameter %s from section "
4481 "[%s] starting at line: %d",
4482 buf, ctx.fname, ctx.m_sectionLineno);
4483 return false;
4484 }
4485 require(ctx.m_currentSection->put(buf, id, true));
4486 require(ctx.m_currentSection->put(sysbuf, token1));
4487 }
4488 return true;
4489 }
4490
4491 /**
4492 * Connection rule: Fix hostname
4493 *
4494 * Unless Hostname is not already specified, do steps:
4495 * -# Via Connection's NodeId lookup Node
4496 * -# Via Node's ExecuteOnComputer lookup Hostname
4497 * -# Add HostName to Connection
4498 */
4499 static bool
fixHostname(InitConfigFileParser::Context & ctx,const char * data)4500 fixHostname(InitConfigFileParser::Context & ctx, const char * data){
4501
4502 char buf[] = "NodeIdX"; buf[6] = data[sizeof("HostNam")];
4503 char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("HostNam")];
4504
4505 if(!ctx.m_currentSection->contains(data)){
4506 Uint32 id = 0;
4507 require(ctx.m_currentSection->get(buf, &id));
4508
4509 const Properties * node;
4510 if(!ctx.m_config->get("Node", id, &node))
4511 {
4512 ctx.reportError("Unknown node: \"%d\" specified in connection "
4513 "[%s] starting at line: %d",
4514 id, ctx.fname, ctx.m_sectionLineno);
4515 return false;
4516 }
4517
4518 const char * hostname;
4519 require(node->get("HostName", &hostname));
4520 require(ctx.m_currentSection->put(data, hostname));
4521 }
4522 return true;
4523 }
4524
4525 /**
4526 * Connection rule: Fix port number (using a port number adder)
4527 */
4528 static bool
fixPortNumber(InitConfigFileParser::Context & ctx,const char * data)4529 fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
4530
4531 DBUG_ENTER("fixPortNumber");
4532
4533 Uint32 id1, id2;
4534 const char *hostName1;
4535 const char *hostName2;
4536 require(ctx.m_currentSection->get("NodeId1", &id1));
4537 require(ctx.m_currentSection->get("NodeId2", &id2));
4538 require(ctx.m_currentSection->get("HostName1", &hostName1));
4539 require(ctx.m_currentSection->get("HostName2", &hostName2));
4540 DBUG_PRINT("info",("NodeId1=%d HostName1=\"%s\"",id1,hostName1));
4541 DBUG_PRINT("info",("NodeId2=%d HostName2=\"%s\"",id2,hostName2));
4542
4543 const Properties *node1, *node2;
4544 require(ctx.m_config->get("Node", id1, &node1));
4545 require(ctx.m_config->get("Node", id2, &node2));
4546
4547 const char *type1, *type2;
4548 require(node1->get("Type", &type1));
4549 require(node2->get("Type", &type2));
4550
4551 /* add NodeIdServer info */
4552 {
4553 Uint32 nodeIdServer = id1 < id2 ? id1 : id2;
4554 if(strcmp(type1, API_TOKEN) == 0 || strcmp(type2, MGM_TOKEN) == 0)
4555 nodeIdServer = id2;
4556 else if(strcmp(type2, API_TOKEN) == 0 || strcmp(type1, MGM_TOKEN) == 0)
4557 nodeIdServer = id1;
4558 ctx.m_currentSection->put("NodeIdServer", nodeIdServer);
4559
4560 if (id2 == nodeIdServer) {
4561 {
4562 const char *tmp= hostName1;
4563 hostName1= hostName2;
4564 hostName2= tmp;
4565 }
4566 {
4567 Uint32 tmp= id1;
4568 id1= id2;
4569 id2= tmp;
4570 }
4571 {
4572 const Properties *tmp= node1;
4573 node1= node2;
4574 node2= tmp;
4575 }
4576 {
4577 const char *tmp= type1;
4578 type1= type2;
4579 type2= tmp;
4580 }
4581 }
4582 }
4583
4584 BaseString hostname(hostName1);
4585
4586 if (hostname.c_str()[0] == 0) {
4587 ctx.reportError("Hostname required on nodeid %d since it will "
4588 "act as server.", id1);
4589 DBUG_RETURN(false);
4590 }
4591
4592 Uint32 bindAnyAddr = 0;
4593 node1->get("TcpBind_INADDR_ANY", &bindAnyAddr);
4594 if (bindAnyAddr)
4595 {
4596 ctx.m_currentSection->put("TcpBind_INADDR_ANY", 1, true);
4597 }
4598
4599 Uint32 port= 0;
4600 if(strcmp(type1, MGM_TOKEN)==0)
4601 node1->get("PortNumber",&port);
4602 else if(strcmp(type2, MGM_TOKEN)==0)
4603 node2->get("PortNumber",&port);
4604
4605 if (!port &&
4606 !node1->get("ServerPort", &port) &&
4607 !ctx.m_userProperties.get("ServerPort_", id1, &port))
4608 {
4609 Uint32 base= 0;
4610 /*
4611 * If the connection doesn't involve an mgm server,
4612 * and a default port number has been set, behave the old
4613 * way of allocating port numbers for transporters.
4614 */
4615 if(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base))
4616 {
4617 Uint32 adder= 0;
4618 {
4619 BaseString server_port_adder(hostname);
4620 server_port_adder.append("_ServerPortAdder");
4621 ctx.m_userProperties.get(server_port_adder.c_str(), &adder);
4622 ctx.m_userProperties.put(server_port_adder.c_str(), adder+1, true);
4623 }
4624
4625 port= base + adder;
4626 ctx.m_userProperties.put("ServerPort_", id1, port);
4627 }
4628 }
4629
4630 if(ctx.m_currentSection->contains("PortNumber")) {
4631 ndbout << "PortNumber should no longer be specificied "
4632 << "per connection, please remove from config. "
4633 << "Will be changed to " << port << endl;
4634 ctx.m_currentSection->put("PortNumber", port, true);
4635 }
4636 else
4637 {
4638 ctx.m_currentSection->put("PortNumber", port);
4639 }
4640
4641 DBUG_PRINT("info", ("connection %d-%d port %d host %s",
4642 id1, id2, port, hostname.c_str()));
4643
4644 DBUG_RETURN(true);
4645 }
4646
4647 static bool
fixShmUniqueId(InitConfigFileParser::Context & ctx,const char * data)4648 fixShmUniqueId(InitConfigFileParser::Context & ctx, const char * data)
4649 {
4650 DBUG_ENTER("fixShmUniqueId");
4651 Uint32 nodes= 0;
4652 ctx.m_userProperties.get(ctx.fname, &nodes);
4653 if (nodes == 1) // first management server
4654 {
4655 Uint32 portno= NDB_PORT;
4656 ctx.m_currentSection->get("PortNumber", &portno);
4657 ctx.m_userProperties.put("ShmUniqueId", portno);
4658 }
4659 DBUG_RETURN(true);
4660 }
4661
4662 static
4663 bool
fixShmKey(InitConfigFileParser::Context & ctx,const char *)4664 fixShmKey(InitConfigFileParser::Context & ctx, const char *)
4665 {
4666 DBUG_ENTER("fixShmKey");
4667 {
4668 static int last_signum= -1;
4669 Uint32 signum = 0;
4670 if(!ctx.m_currentSection->get("Signum", &signum))
4671 {
4672 if (signum <= 0)
4673 {
4674 ctx.reportError("Unable to set default parameter for [SHM]Signum"
4675 " please specify [SHM DEFAULT]Signum");
4676 return false;
4677 }
4678 ctx.m_currentSection->put("Signum", signum);
4679 DBUG_PRINT("info",("Added Signum=%u", signum));
4680 }
4681 if ( last_signum != (int)signum && last_signum >= 0 )
4682 {
4683 ctx.reportError("All shared memory transporters must have same [SHM]Signum defined."
4684 " Use [SHM DEFAULT]Signum");
4685 return false;
4686 }
4687 last_signum= (int)signum;
4688 }
4689 {
4690 Uint32 id1= 0, id2= 0, key= 0;
4691 require(ctx.m_currentSection->get("NodeId1", &id1));
4692 require(ctx.m_currentSection->get("NodeId2", &id2));
4693 if(!ctx.m_currentSection->get("ShmKey", &key))
4694 {
4695 require(ctx.m_userProperties.get("ShmUniqueId", &key));
4696 key= key << 16 | (id1 > id2 ? id1 << 8 | id2 : id2 << 8 | id1);
4697 ctx.m_currentSection->put("ShmKey", key);
4698 DBUG_PRINT("info",("Added ShmKey=0x%x", key));
4699 }
4700 }
4701 DBUG_RETURN(true);
4702 }
4703
4704 /**
4705 * DB Node rule: Check various constraints
4706 */
4707 static bool
checkDbConstraints(InitConfigFileParser::Context & ctx,const char *)4708 checkDbConstraints(InitConfigFileParser::Context & ctx, const char *){
4709
4710 Uint32 t1 = 0, t2 = 0;
4711 ctx.m_currentSection->get("MaxNoOfConcurrentOperations", &t1);
4712 ctx.m_currentSection->get("MaxNoOfConcurrentTransactions", &t2);
4713
4714 if (t1 < t2) {
4715 ctx.reportError("MaxNoOfConcurrentOperations must be greater than "
4716 "MaxNoOfConcurrentTransactions - [%s] starting at line: %d",
4717 ctx.fname, ctx.m_sectionLineno);
4718 return false;
4719 }
4720
4721 Uint32 replicas = 0, otherReplicas;
4722 ctx.m_currentSection->get("NoOfReplicas", &replicas);
4723 if(ctx.m_userProperties.get("NoOfReplicas", &otherReplicas)){
4724 if(replicas != otherReplicas){
4725 ctx.reportError("NoOfReplicas defined differently on different nodes"
4726 " - [%s] starting at line: %d",
4727 ctx.fname, ctx.m_sectionLineno);
4728 return false;
4729 }
4730 } else {
4731 ctx.m_userProperties.put("NoOfReplicas", replicas);
4732 }
4733
4734 /**
4735 * In kernel, will calculate the MaxNoOfMeataTables use the following sum:
4736 * Uint32 noOfMetaTables = noOfTables + noOfOrderedIndexes +
4737 * noOfUniqueHashIndexes + 2
4738 * 2 is the number of the SysTables.
4739 * So must check that the sum does't exceed the max value of Uint32.
4740 */
4741 Uint32 noOfTables = 0,
4742 noOfOrderedIndexes = 0,
4743 noOfUniqueHashIndexes = 0;
4744 ctx.m_currentSection->get("MaxNoOfTables", &noOfTables);
4745 ctx.m_currentSection->get("MaxNoOfOrderedIndexes", &noOfOrderedIndexes);
4746 ctx.m_currentSection->get("MaxNoOfUniqueHashIndexes", &noOfUniqueHashIndexes);
4747
4748 Uint64 sum= (Uint64)noOfTables + noOfOrderedIndexes + noOfUniqueHashIndexes;
4749
4750 if (sum > ((Uint32)~0 - 2)) {
4751 ctx.reportError("The sum of MaxNoOfTables, MaxNoOfOrderedIndexes and"
4752 " MaxNoOfUniqueHashIndexes must not exceed %u - [%s]"
4753 " starting at line: %d",
4754 ((Uint32)~0 - 2), ctx.fname, ctx.m_sectionLineno);
4755 return false;
4756 }
4757
4758 return true;
4759 }
4760
4761 #include <NdbThread.h>
4762
4763 static
4764 bool
checkThreadPrioSpec(InitConfigFileParser::Context & ctx,const char * unused)4765 checkThreadPrioSpec(InitConfigFileParser::Context & ctx, const char * unused)
4766 {
4767 (void)unused;
4768 const char * spec = 0;
4769 if (ctx.m_currentSection->get("HeartbeatThreadPriority", &spec))
4770 {
4771 int ret = NdbThread_SetHighPrioProperties(spec);
4772 NdbThread_SetHighPrioProperties(0); // reset
4773 if (ret)
4774 {
4775 ctx.reportError("Unable to parse HeartbeatThreadPriority: %s", spec);
4776 return false;
4777 }
4778 return true;
4779 }
4780 return true;
4781 }
4782
4783 #include "../kernel/vm/mt_thr_config.hpp"
4784
4785 static
4786 bool
checkThreadConfig(InitConfigFileParser::Context & ctx,const char * unused)4787 checkThreadConfig(InitConfigFileParser::Context & ctx, const char * unused)
4788 {
4789 (void)unused;
4790 Uint32 maxExecuteThreads = 0;
4791 Uint32 lqhThreads = 0;
4792 Uint32 classic = 0;
4793 const char * thrconfig = 0;
4794 const char * locktocpu = 0;
4795
4796 THRConfig tmp;
4797 if (ctx.m_currentSection->get("LockExecuteThreadToCPU", &locktocpu))
4798 {
4799 tmp.setLockExecuteThreadToCPU(locktocpu);
4800 }
4801
4802 ctx.m_currentSection->get("MaxNoOfExecutionThreads", &maxExecuteThreads);
4803 ctx.m_currentSection->get("__ndbmt_lqh_threads", &lqhThreads);
4804 ctx.m_currentSection->get("__ndbmt_classic", &classic);
4805
4806 if (ctx.m_currentSection->get("ThreadConfig", &thrconfig))
4807 {
4808 int ret = tmp.do_parse(thrconfig);
4809 if (ret)
4810 {
4811 ctx.reportError("Unable to parse ThreadConfig: %s",
4812 tmp.getErrorMessage());
4813 return false;
4814 }
4815
4816 if (maxExecuteThreads)
4817 {
4818 ctx.reportWarning("ThreadConfig overrides MaxNoOfExecutionThreads");
4819 }
4820
4821 if (lqhThreads)
4822 {
4823 ctx.reportWarning("ThreadConfig overrides __ndbmt_lqh_threads");
4824 }
4825
4826 if (classic)
4827 {
4828 ctx.reportWarning("ThreadConfig overrides __ndbmt_classic");
4829 }
4830 }
4831 else if (maxExecuteThreads || lqhThreads || classic)
4832 {
4833 int ret = tmp.do_parse(maxExecuteThreads, lqhThreads, classic);
4834 if (ret)
4835 {
4836 ctx.reportError("Unable to set thread configuration: %s",
4837 tmp.getErrorMessage());
4838 return false;
4839 }
4840 }
4841
4842 if (tmp.getInfoMessage())
4843 {
4844 ctx.reportWarning("%s", tmp.getInfoMessage());
4845 }
4846
4847 if (thrconfig == 0)
4848 {
4849 ctx.m_currentSection->put("ThreadConfig", tmp.getConfigString());
4850 }
4851
4852 return true;
4853 }
4854
4855 /**
4856 * Connection rule: Check varius constraints
4857 */
4858 static bool
checkConnectionConstraints(InitConfigFileParser::Context & ctx,const char *)4859 checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
4860
4861 Uint32 id1 = 0, id2 = 0;
4862 ctx.m_currentSection->get("NodeId1", &id1);
4863 ctx.m_currentSection->get("NodeId2", &id2);
4864
4865 if(id1 == id2){
4866 ctx.reportError("Illegal connection from node to itself"
4867 " - [%s] starting at line: %d",
4868 ctx.fname, ctx.m_sectionLineno);
4869 return false;
4870 }
4871
4872 const Properties * node1;
4873 if(!ctx.m_config->get("Node", id1, &node1)){
4874 ctx.reportError("Connection refering to undefined node: %d"
4875 " - [%s] starting at line: %d",
4876 id1, ctx.fname, ctx.m_sectionLineno);
4877 return false;
4878 }
4879
4880 const Properties * node2;
4881 if(!ctx.m_config->get("Node", id2, &node2)){
4882 ctx.reportError("Connection refering to undefined node: %d"
4883 " - [%s] starting at line: %d",
4884 id2, ctx.fname, ctx.m_sectionLineno);
4885 return false;
4886 }
4887
4888 const char * type1;
4889 const char * type2;
4890 require(node1->get("Type", &type1));
4891 require(node2->get("Type", &type2));
4892
4893 /**
4894 * Report error if the following are true
4895 * -# None of the nodes is of type DB
4896 * -# Not both of them are MGMs
4897 */
4898 if((strcmp(type1, DB_TOKEN) != 0 && strcmp(type2, DB_TOKEN) != 0) &&
4899 !(strcmp(type1, MGM_TOKEN) == 0 && strcmp(type2, MGM_TOKEN) == 0))
4900 {
4901 ctx.reportError("Invalid connection between node %d (%s) and node %d (%s)"
4902 " - [%s] starting at line: %d",
4903 id1, type1, id2, type2,
4904 ctx.fname, ctx.m_sectionLineno);
4905 return false;
4906 }
4907
4908 return true;
4909 }
4910
4911 /**
4912 * Connection rule: allow only one connection between each node pair.
4913 */
4914 static bool
uniqueConnection(InitConfigFileParser::Context & ctx,const char * data)4915 uniqueConnection(InitConfigFileParser::Context & ctx, const char * data)
4916 {
4917 Uint32 lo_node, hi_node;
4918 BaseString key; /* Properties key to identify this link */
4919 BaseString defn; /* Value stored at key (used in error msgs) */
4920
4921 /* This rule runs *after* fixNodeId, so it is guaranteed that the
4922 NodeId1 and NodeId2 properties exist and contain integers */
4923 require(ctx.m_currentSection->get("NodeId1", &lo_node) == true);
4924 require(ctx.m_currentSection->get("NodeId2", &hi_node) == true);
4925
4926 if(lo_node > hi_node) /* sort the node ids, low-node-first */
4927 {
4928 const Uint32 tmp_node = hi_node;
4929 hi_node = lo_node;
4930 lo_node = tmp_node;
4931 }
4932
4933 key.assfmt("Link_%d_%d", lo_node, hi_node);
4934
4935 /* The property must not already exist */
4936 if(ctx.m_userProperties.contains(key.c_str()))
4937 {
4938 const char * old_defn;
4939 if(ctx.m_userProperties.get(key.c_str(), &old_defn))
4940 ctx.reportError("%s connection is a duplicate of the existing %s",
4941 data, old_defn);
4942 return false;
4943 }
4944
4945 /* Set the unique link identifier property */
4946 defn.assfmt("%s link from line %d", data, ctx.m_sectionLineno);
4947 ctx.m_userProperties.put(key.c_str(), defn.c_str());
4948
4949 return true;
4950 }
4951
4952 static bool
checkTCPConstraints(InitConfigFileParser::Context & ctx,const char * data)4953 checkTCPConstraints(InitConfigFileParser::Context & ctx, const char * data){
4954
4955 const char * host;
4956 struct in_addr addr;
4957 if(ctx.m_currentSection->get(data, &host) && strlen(host) &&
4958 Ndb_getInAddr(&addr, host)){
4959 ctx.reportError("Unable to lookup/illegal hostname %s"
4960 " - [%s] starting at line: %d",
4961 host, ctx.fname, ctx.m_sectionLineno);
4962 return false;
4963 }
4964 return true;
4965 }
4966
4967 static
4968 bool
transform(InitConfigFileParser::Context & ctx,Properties & dst,const char * oldName,const char * newName,double add,double mul)4969 transform(InitConfigFileParser::Context & ctx,
4970 Properties & dst,
4971 const char * oldName,
4972 const char * newName,
4973 double add, double mul){
4974
4975 if(ctx.m_currentSection->contains(newName)){
4976 ctx.reportError("Both %s and %s specified"
4977 " - [%s] starting at line: %d",
4978 oldName, newName,
4979 ctx.fname, ctx.m_sectionLineno);
4980 return false;
4981 }
4982
4983 PropertiesType oldType;
4984 require(ctx.m_currentSection->getTypeOf(oldName, &oldType));
4985 ConfigInfo::Type newType = ctx.m_info->getType(ctx.m_currentInfo, newName);
4986
4987 if(!((oldType == PropertiesType_Uint32 || oldType == PropertiesType_Uint64)
4988 && (newType == ConfigInfo::CI_INT || newType == ConfigInfo::CI_INT64 || newType == ConfigInfo::CI_BOOL))){
4989 ndbout << "oldType: " << (int)oldType << ", newType: " << (int)newType << endl;
4990 ctx.reportError("Unable to handle type conversion w.r.t deprecation %s %s"
4991 "- [%s] starting at line: %d",
4992 oldName, newName,
4993 ctx.fname, ctx.m_sectionLineno);
4994 return false;
4995 }
4996 Uint64 oldVal;
4997 require(ctx.m_currentSection->get(oldName, &oldVal));
4998
4999 Uint64 newVal = (Uint64)((Int64)oldVal * mul + add);
5000 if(!ctx.m_info->verify(ctx.m_currentInfo, newName, newVal)){
5001 ctx.reportError("Unable to handle deprecation, new value not within bounds"
5002 "%s %s - [%s] starting at line: %d",
5003 oldName, newName,
5004 ctx.fname, ctx.m_sectionLineno);
5005 return false;
5006 }
5007
5008 if(newType == ConfigInfo::CI_INT || newType == ConfigInfo::CI_BOOL){
5009 require(dst.put(newName, (Uint32)newVal));
5010 } else if(newType == ConfigInfo::CI_INT64) {
5011 require(dst.put64(newName, newVal));
5012 }
5013 return true;
5014 }
5015
5016 static bool
fixDeprecated(InitConfigFileParser::Context & ctx,const char * data)5017 fixDeprecated(InitConfigFileParser::Context & ctx, const char * data){
5018 const char * name;
5019 /**
5020 * Transform old values to new values
5021 * Transform new values to old values (backward compatible)
5022 */
5023 Properties tmp(true);
5024 Properties::Iterator it(ctx.m_currentSection);
5025 for (name = it.first(); name != NULL; name = it.next()) {
5026 const DeprecationTransform * p = &f_deprecation[0];
5027 while(p->m_section != 0){
5028 if(strcmp(p->m_section, ctx.fname) == 0){
5029 double mul = p->m_mul;
5030 double add = p->m_add;
5031 if(strcasecmp(name, p->m_oldName) == 0){
5032 if(!transform(ctx, tmp, name, p->m_newName, add, mul)){
5033 return false;
5034 }
5035 } else if(strcasecmp(name, p->m_newName) == 0) {
5036 if(!transform(ctx, tmp, name, p->m_oldName, -add/mul,1.0/mul)){
5037 return false;
5038 }
5039 }
5040 }
5041 p++;
5042 }
5043 }
5044
5045 Properties::Iterator it2(&tmp);
5046 for (name = it2.first(); name != NULL; name = it2.next()) {
5047 PropertiesType type;
5048 require(tmp.getTypeOf(name, &type));
5049 switch(type){
5050 case PropertiesType_Uint32:{
5051 Uint32 val;
5052 require(tmp.get(name, &val));
5053 require(ctx.m_currentSection->put(name, val));
5054 break;
5055 }
5056 case PropertiesType_char:{
5057 const char * val;
5058 require(tmp.get(name, &val));
5059 require(ctx.m_currentSection->put(name, val));
5060 break;
5061 }
5062 case PropertiesType_Uint64:{
5063 Uint64 val;
5064 require(tmp.get(name, &val));
5065 require(ctx.m_currentSection->put64(name, val));
5066 break;
5067 }
5068 case PropertiesType_Properties:
5069 default:
5070 require(false);
5071 }
5072 }
5073 return true;
5074 }
5075
5076 static bool
saveInConfigValues(InitConfigFileParser::Context & ctx,const char * data)5077 saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){
5078 const Properties * sec;
5079 if(!ctx.m_currentInfo->get(ctx.fname, &sec)){
5080 require(false);
5081 return false;
5082 }
5083
5084 do {
5085 const char *secName;
5086 Uint32 id, status, typeVal;
5087 require(sec->get("Fname", &secName));
5088 require(sec->get("Id", &id));
5089 require(sec->get("Status", &status));
5090 require(sec->get("SectionType", &typeVal));
5091
5092 if(id == KEY_INTERNAL || status == ConfigInfo::CI_INTERNAL){
5093 ndbout_c("skipping section %s", ctx.fname);
5094 break;
5095 }
5096
5097 Uint32 no = 0;
5098 ctx.m_userProperties.get("$Section", id, &no);
5099 ctx.m_userProperties.put("$Section", id, no+1, true);
5100
5101 ctx.m_configValues.openSection(id, no);
5102 ctx.m_configValues.put(CFG_TYPE_OF_SECTION, typeVal);
5103
5104 Properties::Iterator it(ctx.m_currentSection);
5105 for (const char* n = it.first(); n != NULL; n = it.next()) {
5106 const Properties * info;
5107 if(!ctx.m_currentInfo->get(n, &info))
5108 continue;
5109
5110 id = 0;
5111 info->get("Id", &id);
5112
5113 if(id == KEY_INTERNAL)
5114 continue;
5115
5116 bool ok = true;
5117 PropertiesType type;
5118 require(ctx.m_currentSection->getTypeOf(n, &type));
5119 switch(type){
5120 case PropertiesType_Uint32:{
5121 Uint32 val;
5122 require(ctx.m_currentSection->get(n, &val));
5123 ok = ctx.m_configValues.put(id, val);
5124 break;
5125 }
5126 case PropertiesType_Uint64:{
5127 Uint64 val;
5128 require(ctx.m_currentSection->get(n, &val));
5129 ok = ctx.m_configValues.put64(id, val);
5130 break;
5131 }
5132 case PropertiesType_char:{
5133 const char * val;
5134 require(ctx.m_currentSection->get(n, &val));
5135 ok = ctx.m_configValues.put(id, val);
5136 break;
5137 }
5138 default:
5139 require(false);
5140 }
5141 require(ok);
5142 }
5143 ctx.m_configValues.closeSection();
5144 } while(0);
5145 return true;
5146 }
5147
5148
5149 static bool
add_system_section(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)5150 add_system_section(Vector<ConfigInfo::ConfigRuleSection>§ions,
5151 struct InitConfigFileParser::Context &ctx,
5152 const char * rule_data)
5153 {
5154 if (!ctx.m_userProperties.contains("SYSTEM")) {
5155 ConfigInfo::ConfigRuleSection s;
5156
5157 // Generate a unique name for this new cluster
5158 time_t now = ::time((time_t*)NULL);
5159 struct tm* tm_now = ::localtime(&now);
5160
5161 char name_buf[18];
5162 BaseString::snprintf(name_buf, sizeof(name_buf),
5163 "MC_%d%.2d%.2d%.2d%.2d%.2d",
5164 tm_now->tm_year + 1900,
5165 tm_now->tm_mon + 1,
5166 tm_now->tm_mday,
5167 tm_now->tm_hour,
5168 tm_now->tm_min,
5169 tm_now->tm_sec);
5170
5171 s.m_sectionType = BaseString("SYSTEM");
5172 s.m_sectionData = new Properties(true);
5173 s.m_sectionData->put("Name", name_buf);
5174 s.m_sectionData->put("Type", "SYSTEM");
5175
5176 // ndbout_c("Generated new SYSTEM section with name '%s'", name_buf);
5177
5178 sections.push_back(s);
5179 }
5180 return true;
5181 }
5182
5183
5184 static bool
sanity_checks(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)5185 sanity_checks(Vector<ConfigInfo::ConfigRuleSection>§ions,
5186 struct InitConfigFileParser::Context &ctx,
5187 const char * rule_data)
5188 {
5189 Uint32 db_nodes = 0;
5190 Uint32 mgm_nodes = 0;
5191 Uint32 api_nodes = 0;
5192 if (!ctx.m_userProperties.get("DB", &db_nodes)) {
5193 ctx.reportError("At least one database node (ndbd) should be defined in config file");
5194 return false;
5195 }
5196 if (!ctx.m_userProperties.get("MGM", &mgm_nodes)) {
5197 ctx.reportError("At least one management server node (ndb_mgmd) should be defined in config file");
5198 return false;
5199 }
5200 if (!ctx.m_userProperties.get("API", &api_nodes)) {
5201 ctx.reportError("At least one application node (for the mysqld) should be defined in config file");
5202 return false;
5203 }
5204 return true;
5205 }
5206
5207 static
5208 int
check_connection(struct InitConfigFileParser::Context & ctx,const char * map,Uint32 nodeId1,const char * hostname,Uint32 nodeId2)5209 check_connection(struct InitConfigFileParser::Context &ctx,
5210 const char * map,
5211 Uint32 nodeId1, const char * hostname,
5212 Uint32 nodeId2)
5213 {
5214 Bitmask<(MAX_NODES+31)/32> bitmap;
5215
5216 BaseString str(map);
5217 Vector<BaseString> arr;
5218 str.split(arr, ",");
5219 for (Uint32 i = 0; i<arr.size(); i++)
5220 {
5221 char *endptr = 0;
5222 long val = strtol(arr[i].c_str(), &endptr, 10);
5223 if (*endptr)
5224 {
5225 ctx.reportError("Unable to parse ConnectionMap(\"%s\" for "
5226 "node: %d, hostname: %s",
5227 map, nodeId1, hostname);
5228 return -1;
5229 }
5230 if (! (val > 0 && val < MAX_NDB_NODES))
5231 {
5232 ctx.reportError("Invalid node in in ConnectionMap(\"%s\" for "
5233 "node: %d, hostname: %s",
5234 map, nodeId1, hostname);
5235 return -1;
5236 }
5237 bitmap.set(val);
5238 }
5239 return bitmap.get(nodeId2);
5240 }
5241
5242 static
5243 bool
add_a_connection(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,Uint32 nodeId1,Uint32 nodeId2,bool use_shm)5244 add_a_connection(Vector<ConfigInfo::ConfigRuleSection>§ions,
5245 struct InitConfigFileParser::Context &ctx,
5246 Uint32 nodeId1, Uint32 nodeId2, bool use_shm)
5247 {
5248 int ret;
5249 ConfigInfo::ConfigRuleSection s;
5250 const char * map = 0;
5251 const char *hostname1= 0, *hostname2= 0;
5252 const Properties *tmp;
5253
5254 Uint32 wan = 0;
5255 require(ctx.m_config->get("Node", nodeId1, &tmp));
5256 tmp->get("HostName", &hostname1);
5257 if (!wan)
5258 {
5259 tmp->get("wan", &wan);
5260 }
5261
5262 if (tmp->get("ConnectionMap", &map))
5263 {
5264 if ((ret = check_connection(ctx, map, nodeId1, hostname1, nodeId2)) != 1)
5265 {
5266 return ret == 0 ? true : false;
5267 }
5268 }
5269
5270 require(ctx.m_config->get("Node", nodeId2, &tmp));
5271 tmp->get("HostName", &hostname2);
5272 if (!wan)
5273 {
5274 tmp->get("wan", &wan);
5275 }
5276
5277 if (tmp->get("ConnectionMap", &map))
5278 {
5279 if ((ret = check_connection(ctx, map, nodeId2, hostname2, nodeId1)) != 1)
5280 {
5281 return ret == 0 ? true : false;
5282 }
5283 }
5284
5285 char buf[16];
5286 s.m_sectionData= new Properties(true);
5287 BaseString::snprintf(buf, sizeof(buf), "%u", nodeId1);
5288 s.m_sectionData->put("NodeId1", buf);
5289 BaseString::snprintf(buf, sizeof(buf), "%u", nodeId2);
5290 s.m_sectionData->put("NodeId2", buf);
5291
5292 if (use_shm &&
5293 hostname1 && hostname1[0] &&
5294 hostname2 && hostname2[0] &&
5295 strcmp(hostname1,hostname2) == 0)
5296 {
5297 s.m_sectionType= BaseString("SHM");
5298 DBUG_PRINT("info",("adding SHM connection %d %d",nodeId1,nodeId2));
5299 }
5300 else
5301 {
5302 s.m_sectionType= BaseString("TCP");
5303 DBUG_PRINT("info",("adding TCP connection %d %d",nodeId1,nodeId2));
5304
5305 if (wan)
5306 {
5307 s.m_sectionData->put("TCP_RCV_BUF_SIZE", 4194304);
5308 s.m_sectionData->put("TCP_SND_BUF_SIZE", 4194304);
5309 s.m_sectionData->put("TCP_MAXSEG_SIZE", 61440);
5310 }
5311 }
5312
5313 sections.push_back(s);
5314 return true;
5315 }
5316
5317 static bool
add_node_connections(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)5318 add_node_connections(Vector<ConfigInfo::ConfigRuleSection>§ions,
5319 struct InitConfigFileParser::Context &ctx,
5320 const char * rule_data)
5321 {
5322 DBUG_ENTER("add_node_connections");
5323 Uint32 i;
5324 Properties * props= ctx.m_config;
5325 Properties p_connections(true);
5326 Properties p_connections2(true);
5327
5328 for (i = 0;; i++){
5329 const Properties * tmp;
5330 Uint32 nodeId1, nodeId2;
5331
5332 if(!props->get("Connection", i, &tmp)) break;
5333
5334 if(!tmp->get("NodeId1", &nodeId1)) continue;
5335 p_connections.put("", nodeId1, nodeId1);
5336 if(!tmp->get("NodeId2", &nodeId2)) continue;
5337 p_connections.put("", nodeId2, nodeId2);
5338
5339 p_connections2.put("", nodeId1 + (nodeId2<<16), nodeId1);
5340 p_connections2.put("", nodeId2 + (nodeId1<<16), nodeId2);
5341 }
5342
5343 Uint32 nNodes;
5344 ctx.m_userProperties.get("NoOfNodes", &nNodes);
5345
5346 Properties p_db_nodes(true);
5347 Properties p_api_nodes(true);
5348 Properties p_mgm_nodes(true);
5349
5350 Uint32 i_db= 0, i_api= 0, i_mgm= 0, n;
5351 for (i= 0, n= 0; n < nNodes; i++){
5352 const Properties * tmp;
5353 if(!props->get("Node", i, &tmp)) continue;
5354 n++;
5355
5356 const char * type;
5357 if(!tmp->get("Type", &type)) continue;
5358
5359 if (strcmp(type,DB_TOKEN) == 0)
5360 p_db_nodes.put("", i_db++, i);
5361 else if (strcmp(type,API_TOKEN) == 0)
5362 p_api_nodes.put("", i_api++, i);
5363 else if (strcmp(type,MGM_TOKEN) == 0)
5364 p_mgm_nodes.put("", i_mgm++, i);
5365 }
5366
5367 Uint32 nodeId1, nodeId2, dummy;
5368
5369 // DB -> DB
5370 for (i= 0; p_db_nodes.get("", i, &nodeId1); i++){
5371 for (Uint32 j= i+1;; j++){
5372 if(!p_db_nodes.get("", j, &nodeId2)) break;
5373 if(!p_connections2.get("", nodeId1+(nodeId2<<16), &dummy))
5374 {
5375 if (!add_a_connection(sections,ctx,nodeId1,nodeId2,false))
5376 goto err;
5377 }
5378 }
5379 }
5380
5381 // API -> DB
5382 for (i= 0; p_api_nodes.get("", i, &nodeId1); i++){
5383 if(!p_connections.get("", nodeId1, &dummy)) {
5384 for (Uint32 j= 0;; j++){
5385 if(!p_db_nodes.get("", j, &nodeId2)) break;
5386 if (!add_a_connection(sections,ctx,nodeId1,nodeId2,false))
5387 goto err;
5388 }
5389 }
5390 }
5391
5392 // MGM -> DB
5393 for (i= 0; p_mgm_nodes.get("", i, &nodeId1); i++){
5394 if(!p_connections.get("", nodeId1, &dummy)) {
5395 for (Uint32 j= 0;; j++){
5396 if(!p_db_nodes.get("", j, &nodeId2)) break;
5397 if (!add_a_connection(sections,ctx,nodeId1,nodeId2,0))
5398 goto err;
5399 }
5400 }
5401 }
5402
5403 // MGM -> MGM
5404 for (i= 0; p_mgm_nodes.get("", i, &nodeId1); i++){
5405 for (Uint32 j= i+1;; j++){
5406 if(!p_mgm_nodes.get("", j, &nodeId2)) break;
5407 if(!p_connections2.get("", nodeId1+(nodeId2<<16), &dummy))
5408 {
5409 if (!add_a_connection(sections,ctx,nodeId1,nodeId2,0))
5410 goto err;
5411 }
5412 }
5413 }
5414
5415 DBUG_RETURN(true);
5416 err:
5417 DBUG_RETURN(false);
5418 }
5419
set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)5420 static bool set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection>§ions,
5421 struct InitConfigFileParser::Context &ctx,
5422 const char * rule_data)
5423 {
5424 DBUG_ENTER("set_connection_priorities");
5425 DBUG_RETURN(true);
5426 }
5427
5428 static bool
check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)5429 check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>§ions,
5430 struct InitConfigFileParser::Context &ctx,
5431 const char * rule_data)
5432 {
5433 Uint32 i, n;
5434 Uint32 n_nodes;
5435 Uint32 replicas= 0;
5436 Uint32 db_host_count= 0;
5437 bool with_arbitration_rank= false;
5438 ctx.m_userProperties.get("NoOfNodes", &n_nodes);
5439 ctx.m_userProperties.get("NoOfReplicas", &replicas);
5440
5441 /**
5442 * Register user supplied values
5443 */
5444 Uint8 ng_cnt[MAX_NDB_NODES];
5445 Bitmask<(MAX_NDB_NODES+31)/32> nodes_wo_ng;
5446 bzero(ng_cnt, sizeof(ng_cnt));
5447
5448 for (i= 0, n= 0; n < n_nodes; i++)
5449 {
5450 const Properties * tmp;
5451 if(!ctx.m_config->get("Node", i, &tmp)) continue;
5452 n++;
5453
5454 const char * type;
5455 if(!tmp->get("Type", &type)) continue;
5456
5457 if (strcmp(type,DB_TOKEN) == 0)
5458 {
5459 Uint32 id;
5460 tmp->get("NodeId", &id);
5461
5462 Uint32 ng;
5463 if (tmp->get("Nodegroup", &ng))
5464 {
5465 if (ng == NDB_NO_NODEGROUP)
5466 {
5467 break;
5468 }
5469 else if (ng >= MAX_NDB_NODES)
5470 {
5471 ctx.reportError("Invalid nodegroup %u for node %u",
5472 ng, id);
5473 return false;
5474 }
5475 ng_cnt[ng]++;
5476 }
5477 else
5478 {
5479 nodes_wo_ng.set(i);
5480 }
5481 }
5482 }
5483
5484 /**
5485 * Auto-assign nodegroups if user didnt
5486 */
5487 Uint32 next_ng = 0;
5488 for (;ng_cnt[next_ng] >= replicas; next_ng++);
5489 for (i = nodes_wo_ng.find(0); i!=BitmaskImpl::NotFound;
5490 i = nodes_wo_ng.find(i + 1))
5491 {
5492 Properties* tmp = 0;
5493 ctx.m_config->getCopy("Node", i, &tmp);
5494
5495 tmp->put("Nodegroup", next_ng, true);
5496 ctx.m_config->put("Node", i, tmp, true);
5497 ng_cnt[next_ng]++;
5498
5499 Uint32 id;
5500 tmp->get("NodeId", &id);
5501
5502 for (;ng_cnt[next_ng] >= replicas; next_ng++);
5503
5504 delete tmp;
5505 }
5506
5507 /**
5508 * Check node vs replicas
5509 */
5510 for (i = 0; i<MAX_NDB_NODES; i++)
5511 {
5512 if (ng_cnt[i] != 0 && ng_cnt[i] != (Uint8)replicas)
5513 {
5514 ctx.reportError("Nodegroup %u has %u members, NoOfReplicas=%u",
5515 i, ng_cnt[i], replicas);
5516 return false;
5517 }
5518 }
5519
5520 // check that node groups and arbitrators are ok
5521 // just issue warning if not
5522 if(replicas > 1){
5523 Properties p_db_hosts(true); // store hosts which db nodes run on
5524 Properties p_arbitrators(true); // store hosts which arbitrators run on
5525 // arbitrator should not run together with db node on same host
5526 Uint32 group= 0, i_group= 0;
5527 BaseString node_group_warning, arbitration_warning;
5528 const char *arbit_warn_fmt=
5529 "\n arbitrator with id %d and db node with id %d on same host %s";
5530 const char *arbit_warn_fmt2=
5531 "\n arbitrator with id %d has no hostname specified";
5532
5533 ctx.m_userProperties.get("NoOfNodes", &n_nodes);
5534 for (i= 0, n= 0; n < n_nodes; i++){
5535 const Properties * tmp;
5536 if(!ctx.m_config->get("Node", i, &tmp)) continue;
5537 n++;
5538
5539 const char * type;
5540 if(!tmp->get("Type", &type)) continue;
5541
5542 const char* host= 0;
5543 tmp->get("HostName", &host);
5544
5545 if (strcmp(type,DB_TOKEN) == 0)
5546 {
5547 {
5548 Uint32 ii;
5549 if (!p_db_hosts.get(host,&ii))
5550 db_host_count++;
5551 p_db_hosts.put(host,i);
5552 if (p_arbitrators.get(host,&ii))
5553 {
5554 arbitration_warning.appfmt(arbit_warn_fmt, ii, i, host);
5555 p_arbitrators.remove(host); // only one warning per db node
5556 }
5557 }
5558 {
5559 unsigned j;
5560 BaseString str, str2;
5561 str.assfmt("#group%d_",group);
5562 p_db_hosts.put(str.c_str(),i_group,host);
5563 str2.assfmt("##group%d_",group);
5564 p_db_hosts.put(str2.c_str(),i_group,i);
5565 for (j= 0; j < i_group; j++)
5566 {
5567 const char *other_host;
5568 p_db_hosts.get(str.c_str(),j,&other_host);
5569 if (strcmp(host,other_host) == 0) {
5570 unsigned int other_i, c= 0;
5571 p_db_hosts.get(str2.c_str(),j,&other_i);
5572 p_db_hosts.get(str.c_str(),&c);
5573 if (c == 0) // first warning in this node group
5574 node_group_warning.appfmt(" Node group %d", group);
5575 c|= 1 << j;
5576 p_db_hosts.put(str.c_str(),c);
5577 node_group_warning.appfmt(",\n db node with id %d and id %d "
5578 "on same host %s", other_i, i, host);
5579 }
5580 }
5581 i_group++;
5582 DBUG_ASSERT(i_group <= replicas);
5583 if (i_group == replicas)
5584 {
5585 unsigned c= 0;
5586 p_db_hosts.get(str.c_str(),&c);
5587 if (c+1 == (1u << (replicas-1))) // all nodes on same machine
5588 node_group_warning.append(".\n Host failure will "
5589 "cause complete cluster shutdown.");
5590 else if (c > 0)
5591 node_group_warning.append(".\n Host failure may "
5592 "cause complete cluster shutdown.");
5593 group++;
5594 i_group= 0;
5595 }
5596 }
5597 }
5598 else if (strcmp(type,API_TOKEN) == 0 ||
5599 strcmp(type,MGM_TOKEN) == 0)
5600 {
5601 Uint32 rank;
5602 if(tmp->get("ArbitrationRank", &rank) && rank > 0)
5603 {
5604 with_arbitration_rank = true; //check whether MGM or API node configured with rank >0
5605 if(host && host[0] != 0)
5606 {
5607 Uint32 ii;
5608 p_arbitrators.put(host,i);
5609 if (p_db_hosts.get(host,&ii))
5610 {
5611 arbitration_warning.appfmt(arbit_warn_fmt, i, ii, host);
5612 }
5613 }
5614 else
5615 {
5616 arbitration_warning.appfmt(arbit_warn_fmt2, i);
5617 }
5618 }
5619 }
5620 }
5621 if (db_host_count > 1 && node_group_warning.length() > 0)
5622 ctx.reportWarning("Cluster configuration warning:\n%s",node_group_warning.c_str());
5623 if (!with_arbitration_rank)
5624 {
5625 ctx.reportWarning("Cluster configuration warning:"
5626 "\n Neither %s nor %s nodes are configured with arbitrator,"
5627 "\n may cause complete cluster shutdown in case of host failure.",
5628 MGM_TOKEN, API_TOKEN);
5629 }
5630 if (db_host_count > 1 && arbitration_warning.length() > 0)
5631 ctx.reportWarning("Cluster configuration warning:%s%s",arbitration_warning.c_str(),
5632 "\n Running arbitrator on the same host as a database node may"
5633 "\n cause complete cluster shutdown in case of host failure.");
5634 }
5635 return true;
5636 }
5637
5638 static bool
check_mutually_exclusive(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)5639 check_mutually_exclusive(Vector<ConfigInfo::ConfigRuleSection>§ions,
5640 struct InitConfigFileParser::Context &ctx,
5641 const char * rule_data)
5642 {
5643 /* This rule checks for configuration settings that are
5644 * mutually exclusive and rejects them
5645 */
5646
5647 //ctx.m_userProperties.print(stderr);
5648
5649 Uint32 numNodes, n;
5650 ctx.m_userProperties.get("NoOfNodes", &numNodes);
5651
5652 for (n=0; n < numNodes; n++)
5653 {
5654 const Properties* nodeProperties;
5655 if (!ctx.m_config->get("Node", n, &nodeProperties)) continue;
5656
5657 //nodeProperties->print(stderr);
5658
5659 const char* nodeType;
5660 if (unlikely(!nodeProperties->get("Type", &nodeType)))
5661 {
5662 ctx.reportError("Missing nodeType for node %u", n);
5663 return false;
5664 }
5665
5666 if (strcmp(nodeType,DB_TOKEN) == 0)
5667 {
5668 {
5669 /* StopOnError related cross-checks */
5670 Uint32 stopOnError;
5671 Uint32 maxStartFailRetries;
5672 Uint32 startFailRetryDelay;
5673
5674 if (unlikely(!nodeProperties->get("StopOnError", &stopOnError)))
5675 {
5676 ctx.reportError("Missing StopOnError setting for node %u", n);
5677 return false;
5678 }
5679
5680 if (unlikely(!nodeProperties->get("MaxStartFailRetries", &maxStartFailRetries)))
5681 {
5682 ctx.reportError("Missing MaxStartFailRetries setting");
5683 return false;
5684 }
5685
5686 if (unlikely(!nodeProperties->get("StartFailRetryDelay", &startFailRetryDelay)))
5687 {
5688 ctx.reportError("Missing StartFailRetryDelay setting");
5689 return false;
5690 }
5691
5692 if (unlikely(((stopOnError != 0) &&
5693 ((maxStartFailRetries != 3) ||
5694 (startFailRetryDelay != 0)))))
5695 {
5696 ctx.reportError("Non default settings for MaxStartFailRetries "
5697 "or StartFailRetryDelay with StopOnError != 0");
5698 return false;
5699 }
5700 }
5701 } /* DB_TOKEN */
5702 } /* for nodes */
5703
5704 return true;
5705 }
5706
5707
ParamInfoIter(const ConfigInfo & info,Uint32 section,Uint32 section_type)5708 ConfigInfo::ParamInfoIter::ParamInfoIter(const ConfigInfo& info,
5709 Uint32 section,
5710 Uint32 section_type) :
5711 m_info(info),
5712 m_section_name(NULL),
5713 m_curr_param(0)
5714 {
5715 /* Find the section's name */
5716 for (int j=0; j<info.m_NoOfParams; j++) {
5717 const ConfigInfo::ParamInfo & param = info.m_ParamInfo[j];
5718 if (param._type == ConfigInfo::CI_SECTION &&
5719 param._paramId == section &&
5720 (section_type == ~(Uint32)0 ||
5721 ConfigInfo::getSectionType(param) == section_type))
5722 {
5723 m_section_name= param._section;
5724 return;
5725 }
5726 }
5727 abort();
5728 }
5729
5730
5731 const ConfigInfo::ParamInfo*
next(void)5732 ConfigInfo::ParamInfoIter::next(void) {
5733 assert(m_curr_param < m_info.m_NoOfParams);
5734 do {
5735 /* Loop through the parameter and return a pointer to the next found */
5736 const ConfigInfo::ParamInfo* param = &m_info.m_ParamInfo[m_curr_param++];
5737 if (strcmp(param->_section, m_section_name) == 0 &&
5738 param->_type != ConfigInfo::CI_SECTION)
5739 return param;
5740 }
5741 while (m_curr_param<m_info.m_NoOfParams);
5742
5743 return NULL;
5744 }
5745
5746
5747 static bool
is_name_in_list(const char * name,Vector<BaseString> & list)5748 is_name_in_list(const char* name, Vector<BaseString>& list)
5749 {
5750 for (Uint32 i = 0; i<list.size(); i++)
5751 {
5752 if (strstr(name, list[i].c_str()))
5753 return true;
5754 }
5755 return false;
5756 }
5757
5758
5759 static
5760 bool
saveSectionsInConfigValues(Vector<ConfigInfo::ConfigRuleSection> & notused,struct InitConfigFileParser::Context & ctx,const char * rule_data)5761 saveSectionsInConfigValues(Vector<ConfigInfo::ConfigRuleSection>& notused,
5762 struct InitConfigFileParser::Context &ctx,
5763 const char * rule_data)
5764 {
5765 if (rule_data == 0)
5766 return true;
5767
5768 BaseString sections(rule_data);
5769 Vector<BaseString> list;
5770 sections.split(list, ",");
5771
5772 Properties::Iterator it(ctx.m_config);
5773
5774 {
5775 // Estimate size of Properties when saved as ConfigValues
5776 // and expand ConfigValues to that size in order to avoid
5777 // the need of allocating memory and copying from new to old
5778 Uint32 keys = 0;
5779 Uint64 data_sz = 0;
5780 for (const char * name = it.first(); name != 0; name = it.next())
5781 {
5782 PropertiesType pt;
5783 if (is_name_in_list(name, list) &&
5784 ctx.m_config->getTypeOf(name, &pt) &&
5785 pt == PropertiesType_Properties)
5786 {
5787 const Properties* tmp;
5788 require(ctx.m_config->get(name, &tmp) != 0);
5789
5790 keys += 2; // openSection(key + no)
5791 keys += 1; // CFG_TYPE_OF_SECTION
5792
5793 Properties::Iterator it2(tmp);
5794 for (const char * name2 = it2.first(); name2 != 0; name2 = it2.next())
5795 {
5796 keys++;
5797 require(tmp->getTypeOf(name2, &pt) != 0);
5798 switch(pt){
5799 case PropertiesType_char:
5800 const char* value;
5801 require(tmp->get(name2, &value) != 0);
5802 data_sz += 1 + ((strlen(value) + 3) / 4);
5803 break;
5804
5805 case PropertiesType_Uint32:
5806 data_sz += 1;
5807 break;
5808
5809 case PropertiesType_Uint64:
5810 data_sz += 2;
5811 break;
5812
5813 case PropertiesType_Properties:
5814 default:
5815 require(false);
5816 break;
5817 }
5818 }
5819 }
5820 }
5821
5822 assert(data_sz >> 32 == 0);
5823 ctx.m_configValues.expand(keys, Uint32(data_sz));
5824 }
5825
5826 for (const char * name = it.first(); name != 0; name = it.next())
5827 {
5828 PropertiesType pt;
5829 if (is_name_in_list(name, list) &&
5830 ctx.m_config->getTypeOf(name, &pt) &&
5831 pt == PropertiesType_Properties)
5832 {
5833 const char * type;
5834 const Properties* tmp;
5835 require(ctx.m_config->get(name, &tmp) != 0);
5836 require(tmp->get("Type", &type) != 0);
5837 require((ctx.m_currentInfo = ctx.m_info->getInfo(type)) != 0);
5838 ctx.m_currentSection = const_cast<Properties*>(tmp);
5839 BaseString::snprintf(ctx.fname, sizeof(ctx.fname), "%s", type);
5840 saveInConfigValues(ctx, 0);
5841 }
5842 }
5843
5844 return true;
5845 }
5846
5847
5848 template class Vector<ConfigInfo::ConfigRuleSection>;
5849 #endif /* NDB_MGMAPI */
5850