1 /* Copyright (c) 2003-2007 MySQL AB
2 Use is subject to license terms
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #include <ndb_global.h>
18 #ifndef NDB_MGMAPI
19 #include <ndb_opt_defaults.h>
20
21 #include <NdbTCP.h>
22 #include "ConfigInfo.hpp"
23 #include <mgmapi_config_parameters.h>
24 #include <ndb_limits.h>
25 #include "InitConfigFileParser.hpp"
26 #include <m_string.h>
27
28 extern my_bool opt_ndb_shm;
29 extern my_bool opt_core;
30
31 #else
32 #include "ConfigInfo.hpp"
33 #include <mgmapi_config_parameters.h>
34 #endif /* NDB_MGMAPI */
35
36 #define MAX_LINE_LENGTH 255
37 #define KEY_INTERNAL 0
38 #define MAX_INT_RNIL 0xfffffeff
39 #define MAX_PORT_NO 65535
40
41 #define _STR_VALUE(x) #x
42 #define STR_VALUE(x) _STR_VALUE(x)
43
44 /****************************************************************************
45 * Section names
46 ****************************************************************************/
47
48 #define DB_TOKEN_PRINT "ndbd(DB)"
49 #define MGM_TOKEN_PRINT "ndb_mgmd(MGM)"
50 #define API_TOKEN_PRINT "mysqld(API)"
51
52 #define DB_TOKEN "DB"
53 #define MGM_TOKEN "MGM"
54 #define API_TOKEN "API"
55
56 #ifndef NDB_MGMAPI
57 const ConfigInfo::AliasPair
58 ConfigInfo::m_sectionNameAliases[]={
59 {API_TOKEN, "MYSQLD"},
60 {DB_TOKEN, "NDBD"},
61 {MGM_TOKEN, "NDB_MGMD"},
62 {0, 0}
63 };
64
65 const char*
66 ConfigInfo::m_sectionNames[]={
67 "SYSTEM",
68 "COMPUTER",
69
70 DB_TOKEN,
71 MGM_TOKEN,
72 API_TOKEN,
73
74 "TCP",
75 "SCI",
76 "SHM"
77 };
78 const int ConfigInfo::m_noOfSectionNames =
79 sizeof(m_sectionNames)/sizeof(char*);
80
81
82 /****************************************************************************
83 * Section Rules declarations
84 ****************************************************************************/
85 static bool transformComputer(InitConfigFileParser::Context & ctx, const char *);
86 static bool transformSystem(InitConfigFileParser::Context & ctx, const char *);
87 static bool transformNode(InitConfigFileParser::Context & ctx, const char *);
88 static bool checkConnectionSupport(InitConfigFileParser::Context & ctx, const char *);
89 static bool transformConnection(InitConfigFileParser::Context & ctx, const char *);
90 static bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *);
91 static bool checkMandatory(InitConfigFileParser::Context & ctx, const char *);
92 static bool fixPortNumber(InitConfigFileParser::Context & ctx, const char *);
93 static bool fixShmKey(InitConfigFileParser::Context & ctx, const char *);
94 static bool checkDbConstraints(InitConfigFileParser::Context & ctx, const char *);
95 static bool checkConnectionConstraints(InitConfigFileParser::Context &, const char *);
96 static bool checkTCPConstraints(InitConfigFileParser::Context &, const char *);
97 static bool fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data);
98 static bool fixHostname(InitConfigFileParser::Context & ctx, const char * data);
99 static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data);
100 static bool fixDepricated(InitConfigFileParser::Context & ctx, const char *);
101 static bool saveInConfigValues(InitConfigFileParser::Context & ctx, const char *);
102 static bool fixFileSystemPath(InitConfigFileParser::Context & ctx, const char * data);
103 static bool fixBackupDataDir(InitConfigFileParser::Context & ctx, const char * data);
104 static bool fixShmUniqueId(InitConfigFileParser::Context & ctx, const char * data);
105 static bool checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx, const char * data);
106
107 const ConfigInfo::SectionRule
108 ConfigInfo::m_SectionRules[] = {
109 { "SYSTEM", transformSystem, 0 },
110 { "COMPUTER", transformComputer, 0 },
111
112 { DB_TOKEN, transformNode, 0 },
113 { API_TOKEN, transformNode, 0 },
114 { MGM_TOKEN, transformNode, 0 },
115
116 { MGM_TOKEN, fixShmUniqueId, 0 },
117
118 { "TCP", checkConnectionSupport, 0 },
119 { "SHM", checkConnectionSupport, 0 },
120 { "SCI", checkConnectionSupport, 0 },
121
122 { "TCP", transformConnection, 0 },
123 { "SHM", transformConnection, 0 },
124 { "SCI", transformConnection, 0 },
125
126 { DB_TOKEN, fixNodeHostname, 0 },
127 { API_TOKEN, fixNodeHostname, 0 },
128 { MGM_TOKEN, fixNodeHostname, 0 },
129
130 { "TCP", fixNodeId, "NodeId1" },
131 { "TCP", fixNodeId, "NodeId2" },
132 { "SHM", fixNodeId, "NodeId1" },
133 { "SHM", fixNodeId, "NodeId2" },
134 { "SCI", fixNodeId, "NodeId1" },
135 { "SCI", fixNodeId, "NodeId2" },
136
137 { "TCP", fixHostname, "HostName1" },
138 { "TCP", fixHostname, "HostName2" },
139 { "SHM", fixHostname, "HostName1" },
140 { "SHM", fixHostname, "HostName2" },
141 { "SCI", fixHostname, "HostName1" },
142 { "SCI", fixHostname, "HostName2" },
143 { "SHM", fixHostname, "HostName1" },
144 { "SHM", fixHostname, "HostName2" },
145
146 { "TCP", fixPortNumber, 0 }, // has to come after fixHostName
147 { "SHM", fixPortNumber, 0 }, // has to come after fixHostName
148 { "SCI", fixPortNumber, 0 }, // has to come after fixHostName
149
150 { "*", applyDefaultValues, "user" },
151 { "*", fixDepricated, 0 },
152 { "*", applyDefaultValues, "system" },
153
154 { "SHM", fixShmKey, 0 }, // has to come after apply default values
155
156 { DB_TOKEN, checkLocalhostHostnameMix, 0 },
157 { API_TOKEN, checkLocalhostHostnameMix, 0 },
158 { MGM_TOKEN, checkLocalhostHostnameMix, 0 },
159
160 { DB_TOKEN, fixFileSystemPath, 0 },
161 { DB_TOKEN, fixBackupDataDir, 0 },
162
163 { DB_TOKEN, checkDbConstraints, 0 },
164
165 { "TCP", checkConnectionConstraints, 0 },
166 { "SHM", checkConnectionConstraints, 0 },
167 { "SCI", checkConnectionConstraints, 0 },
168
169 { "TCP", checkTCPConstraints, "HostName1" },
170 { "TCP", checkTCPConstraints, "HostName2" },
171 { "SCI", checkTCPConstraints, "HostName1" },
172 { "SCI", checkTCPConstraints, "HostName2" },
173 { "SHM", checkTCPConstraints, "HostName1" },
174 { "SHM", checkTCPConstraints, "HostName2" },
175
176 { "*", checkMandatory, 0 },
177
178 { DB_TOKEN, saveInConfigValues, 0 },
179 { API_TOKEN, saveInConfigValues, 0 },
180 { MGM_TOKEN, saveInConfigValues, 0 },
181
182 { "TCP", saveInConfigValues, 0 },
183 { "SHM", saveInConfigValues, 0 },
184 { "SCI", saveInConfigValues, 0 }
185 };
186 const int ConfigInfo::m_NoOfRules = sizeof(m_SectionRules)/sizeof(SectionRule);
187
188 /****************************************************************************
189 * Config Rules declarations
190 ****************************************************************************/
191 static bool sanity_checks(Vector<ConfigInfo::ConfigRuleSection>§ions,
192 struct InitConfigFileParser::Context &ctx,
193 const char * rule_data);
194 static bool add_node_connections(Vector<ConfigInfo::ConfigRuleSection>§ions,
195 struct InitConfigFileParser::Context &ctx,
196 const char * rule_data);
197 static bool set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection>§ions,
198 struct InitConfigFileParser::Context &ctx,
199 const char * rule_data);
200 static bool check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>§ions,
201 struct InitConfigFileParser::Context &ctx,
202 const char * rule_data);
203
204 const ConfigInfo::ConfigRule
205 ConfigInfo::m_ConfigRules[] = {
206 { sanity_checks, 0 },
207 { add_node_connections, 0 },
208 { set_connection_priorities, 0 },
209 { check_node_vs_replicas, 0 },
210 { 0, 0 }
211 };
212
213 struct DepricationTransform {
214 const char * m_section;
215 const char * m_oldName;
216 const char * m_newName;
217 double m_add;
218 double m_mul;
219 };
220
221 static
222 const DepricationTransform f_deprication[] = {
223 { DB_TOKEN, "Discless", "Diskless", 0, 1 },
224 { DB_TOKEN, "Id", "NodeId", 0, 1 },
225 { API_TOKEN, "Id", "NodeId", 0, 1 },
226 { MGM_TOKEN, "Id", "NodeId", 0, 1 },
227 { 0, 0, 0, 0, 0}
228 };
229 #endif /* NDB_MGMAPI */
230
231 /**
232 * The default constructors create objects with suitable values for the
233 * configuration parameters.
234 *
235 * Some are however given the value MANDATORY which means that the value
236 * must be specified in the configuration file.
237 *
238 * Min and max values are also given for some parameters.
239 * - Attr1: Name in file (initial config file)
240 * - Attr2: Name in prop (properties object)
241 * - Attr3: Name of Section (in init config file)
242 * - Attr4: Updateable
243 * - Attr5: Type of parameter (INT or BOOL)
244 * - Attr6: Default Value (number only)
245 * - Attr7: Min value
246 * - Attr8: Max value
247 *
248 * Parameter constraints are coded in file Config.cpp.
249 *
250 * *******************************************************************
251 * Parameters used under development should be marked "NOTIMPLEMENTED"
252 * *******************************************************************
253 */
254
255 const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
256
257 /****************************************************************************
258 * COMPUTER
259 ***************************************************************************/
260 {
261 KEY_INTERNAL,
262 "COMPUTER",
263 "COMPUTER",
264 "Computer section",
265 ConfigInfo::CI_INTERNAL,
266 false,
267 ConfigInfo::CI_SECTION,
268 0,
269 0, 0 },
270
271 {
272 KEY_INTERNAL,
273 "Id",
274 "COMPUTER",
275 "Name of computer",
276 ConfigInfo::CI_USED,
277 false,
278 ConfigInfo::CI_STRING,
279 MANDATORY,
280 0, 0 },
281
282 {
283 KEY_INTERNAL,
284 "HostName",
285 "COMPUTER",
286 "Hostname of computer (e.g. mysql.com)",
287 ConfigInfo::CI_USED,
288 false,
289 ConfigInfo::CI_STRING,
290 MANDATORY,
291 0, 0 },
292
293 {
294 KEY_INTERNAL,
295 "ByteOrder",
296 "COMPUTER",
297 0,
298 ConfigInfo::CI_DEPRICATED,
299 false,
300 ConfigInfo::CI_STRING,
301 UNDEFINED,
302 0,
303 0 },
304
305 /****************************************************************************
306 * SYSTEM
307 ***************************************************************************/
308 {
309 CFG_SECTION_SYSTEM,
310 "SYSTEM",
311 "SYSTEM",
312 "System section",
313 ConfigInfo::CI_USED,
314 false,
315 ConfigInfo::CI_SECTION,
316 (const char *)CFG_SECTION_SYSTEM,
317 0, 0 },
318
319 {
320 CFG_SYS_NAME,
321 "Name",
322 "SYSTEM",
323 "Name of system (NDB Cluster)",
324 ConfigInfo::CI_USED,
325 false,
326 ConfigInfo::CI_STRING,
327 MANDATORY,
328 0, 0 },
329
330 {
331 CFG_SYS_PRIMARY_MGM_NODE,
332 "PrimaryMGMNode",
333 "SYSTEM",
334 "Node id of Primary "MGM_TOKEN_PRINT" node",
335 ConfigInfo::CI_USED,
336 false,
337 ConfigInfo::CI_INT,
338 "0",
339 "0",
340 STR_VALUE(MAX_INT_RNIL) },
341
342 {
343 CFG_SYS_CONFIG_GENERATION,
344 "ConfigGenerationNumber",
345 "SYSTEM",
346 "Configuration generation number",
347 ConfigInfo::CI_USED,
348 false,
349 ConfigInfo::CI_INT,
350 "0",
351 "0",
352 STR_VALUE(MAX_INT_RNIL) },
353
354 /***************************************************************************
355 * DB
356 ***************************************************************************/
357 {
358 CFG_SECTION_NODE,
359 DB_TOKEN,
360 DB_TOKEN,
361 "Node section",
362 ConfigInfo::CI_USED,
363 false,
364 ConfigInfo::CI_SECTION,
365 (const char *)NODE_TYPE_DB,
366 0, 0
367 },
368
369 {
370 CFG_NODE_HOST,
371 "HostName",
372 DB_TOKEN,
373 "Name of computer for this node",
374 ConfigInfo::CI_INTERNAL,
375 false,
376 ConfigInfo::CI_STRING,
377 "localhost",
378 0, 0 },
379
380 {
381 CFG_NODE_SYSTEM,
382 "System",
383 DB_TOKEN,
384 "Name of system for this node",
385 ConfigInfo::CI_INTERNAL,
386 false,
387 ConfigInfo::CI_STRING,
388 UNDEFINED,
389 0, 0 },
390
391 {
392 KEY_INTERNAL,
393 "Id",
394 DB_TOKEN,
395 "",
396 ConfigInfo::CI_DEPRICATED,
397 false,
398 ConfigInfo::CI_INT,
399 MANDATORY,
400 "1",
401 STR_VALUE(MAX_DATA_NODE_ID) },
402
403 {
404 CFG_NODE_ID,
405 "NodeId",
406 DB_TOKEN,
407 "Number identifying the database node ("DB_TOKEN_PRINT")",
408 ConfigInfo::CI_USED,
409 false,
410 ConfigInfo::CI_INT,
411 MANDATORY,
412 "1",
413 STR_VALUE(MAX_DATA_NODE_ID) },
414
415 {
416 KEY_INTERNAL,
417 "ServerPort",
418 DB_TOKEN,
419 "Port used to setup transporter",
420 ConfigInfo::CI_USED,
421 false,
422 ConfigInfo::CI_INT,
423 UNDEFINED,
424 "1",
425 STR_VALUE(MAX_PORT_NO) },
426
427 {
428 CFG_DB_NO_REPLICAS,
429 "NoOfReplicas",
430 DB_TOKEN,
431 "Number of copies of all data in the database (1-4)",
432 ConfigInfo::CI_USED,
433 false,
434 ConfigInfo::CI_INT,
435 MANDATORY,
436 "1",
437 "4" },
438
439 {
440 CFG_DB_NO_ATTRIBUTES,
441 "MaxNoOfAttributes",
442 DB_TOKEN,
443 "Total number of attributes stored in database. I.e. sum over all tables",
444 ConfigInfo::CI_USED,
445 false,
446 ConfigInfo::CI_INT,
447 "1000",
448 "32",
449 STR_VALUE(MAX_INT_RNIL) },
450
451 {
452 CFG_DB_NO_TABLES,
453 "MaxNoOfTables",
454 DB_TOKEN,
455 "Total number of tables stored in the database",
456 ConfigInfo::CI_USED,
457 false,
458 ConfigInfo::CI_INT,
459 "128",
460 "8",
461 STR_VALUE(MAX_TABLES) },
462
463 {
464 CFG_DB_NO_ORDERED_INDEXES,
465 "MaxNoOfOrderedIndexes",
466 DB_TOKEN,
467 "Total number of ordered indexes that can be defined in the system",
468 ConfigInfo::CI_USED,
469 false,
470 ConfigInfo::CI_INT,
471 "128",
472 "0",
473 STR_VALUE(MAX_INT_RNIL) },
474
475 {
476 CFG_DB_NO_UNIQUE_HASH_INDEXES,
477 "MaxNoOfUniqueHashIndexes",
478 DB_TOKEN,
479 "Total number of unique hash indexes that can be defined in the system",
480 ConfigInfo::CI_USED,
481 false,
482 ConfigInfo::CI_INT,
483 "64",
484 "0",
485 STR_VALUE(MAX_INT_RNIL) },
486
487 {
488 CFG_DB_NO_INDEXES,
489 "MaxNoOfIndexes",
490 DB_TOKEN,
491 "Total number of indexes that can be defined in the system",
492 ConfigInfo::CI_DEPRICATED,
493 false,
494 ConfigInfo::CI_INT,
495 "128",
496 "0",
497 STR_VALUE(MAX_INT_RNIL) },
498
499 {
500 CFG_DB_NO_INDEX_OPS,
501 "MaxNoOfConcurrentIndexOperations",
502 DB_TOKEN,
503 "Total number of index operations that can execute simultaneously on one "DB_TOKEN_PRINT" node",
504 ConfigInfo::CI_USED,
505 false,
506 ConfigInfo::CI_INT,
507 "8K",
508 "0",
509 STR_VALUE(MAX_INT_RNIL)
510 },
511
512 {
513 CFG_DB_NO_TRIGGERS,
514 "MaxNoOfTriggers",
515 DB_TOKEN,
516 "Total number of triggers that can be defined in the system",
517 ConfigInfo::CI_USED,
518 false,
519 ConfigInfo::CI_INT,
520 "768",
521 "0",
522 STR_VALUE(MAX_INT_RNIL) },
523
524 {
525 CFG_DB_NO_TRIGGER_OPS,
526 "MaxNoOfFiredTriggers",
527 DB_TOKEN,
528 "Total number of triggers that can fire simultaneously in one "DB_TOKEN_PRINT" node",
529 ConfigInfo::CI_USED,
530 false,
531 ConfigInfo::CI_INT,
532 "4000",
533 "0",
534 STR_VALUE(MAX_INT_RNIL) },
535
536 {
537 KEY_INTERNAL,
538 "ExecuteOnComputer",
539 DB_TOKEN,
540 "String referencing an earlier defined COMPUTER",
541 ConfigInfo::CI_USED,
542 false,
543 ConfigInfo::CI_STRING,
544 UNDEFINED,
545 0, 0 },
546
547 {
548 CFG_DB_NO_SAVE_MSGS,
549 "MaxNoOfSavedMessages",
550 DB_TOKEN,
551 "Max number of error messages in error log and max number of trace files",
552 ConfigInfo::CI_USED,
553 true,
554 ConfigInfo::CI_INT,
555 "25",
556 "0",
557 STR_VALUE(MAX_INT_RNIL) },
558
559 {
560 CFG_DB_MEMLOCK,
561 "LockPagesInMainMemory",
562 DB_TOKEN,
563 "If set to yes, then NDB Cluster data will not be swapped out to disk",
564 ConfigInfo::CI_USED,
565 true,
566 ConfigInfo::CI_INT,
567 "0",
568 "0",
569 "2" },
570
571 {
572 CFG_DB_WATCHDOG_INTERVAL,
573 "TimeBetweenWatchDogCheck",
574 DB_TOKEN,
575 "Time between execution checks inside a database node",
576 ConfigInfo::CI_USED,
577 true,
578 ConfigInfo::CI_INT,
579 "6000",
580 "70",
581 STR_VALUE(MAX_INT_RNIL) },
582
583 {
584 CFG_DB_WATCHDOG_INTERVAL_INITIAL,
585 "TimeBetweenWatchDogCheckInitial",
586 DB_TOKEN,
587 "Time between execution checks inside a database node in the early start phases when memory is allocated",
588 ConfigInfo::CI_USED,
589 true,
590 ConfigInfo::CI_INT,
591 "6000",
592 "70",
593 STR_VALUE(MAX_INT_RNIL) },
594
595 {
596 CFG_DB_STOP_ON_ERROR,
597 "StopOnError",
598 DB_TOKEN,
599 "If set to N, "DB_TOKEN_PRINT" automatically restarts/recovers in case of node failure",
600 ConfigInfo::CI_USED,
601 true,
602 ConfigInfo::CI_BOOL,
603 "true",
604 "false",
605 "true" },
606
607 {
608 CFG_DB_STOP_ON_ERROR_INSERT,
609 "RestartOnErrorInsert",
610 DB_TOKEN,
611 "See src/kernel/vm/Emulator.hpp NdbRestartType for details",
612 ConfigInfo::CI_INTERNAL,
613 true,
614 ConfigInfo::CI_INT,
615 "2",
616 "0",
617 "4" },
618
619 {
620 CFG_DB_NO_OPS,
621 "MaxNoOfConcurrentOperations",
622 DB_TOKEN,
623 "Max number of operation records in transaction coordinator",
624 ConfigInfo::CI_USED,
625 false,
626 ConfigInfo::CI_INT,
627 "32k",
628 "32",
629 STR_VALUE(MAX_INT_RNIL) },
630
631 {
632 CFG_DB_NO_LOCAL_OPS,
633 "MaxNoOfLocalOperations",
634 DB_TOKEN,
635 "Max number of operation records defined in the local storage node",
636 ConfigInfo::CI_USED,
637 false,
638 ConfigInfo::CI_INT,
639 UNDEFINED,
640 "32",
641 STR_VALUE(MAX_INT_RNIL) },
642
643 {
644 CFG_DB_NO_LOCAL_SCANS,
645 "MaxNoOfLocalScans",
646 DB_TOKEN,
647 "Max number of fragment scans in parallel in the local storage node",
648 ConfigInfo::CI_USED,
649 false,
650 ConfigInfo::CI_INT,
651 UNDEFINED,
652 "32",
653 STR_VALUE(MAX_INT_RNIL) },
654
655 {
656 CFG_DB_BATCH_SIZE,
657 "BatchSizePerLocalScan",
658 DB_TOKEN,
659 "Used to calculate the number of lock records for scan with hold lock",
660 ConfigInfo::CI_USED,
661 false,
662 ConfigInfo::CI_INT,
663 STR_VALUE(DEF_BATCH_SIZE),
664 "1",
665 STR_VALUE(MAX_PARALLEL_OP_PER_SCAN) },
666
667 {
668 CFG_DB_NO_TRANSACTIONS,
669 "MaxNoOfConcurrentTransactions",
670 DB_TOKEN,
671 "Max number of transaction executing concurrently on the "DB_TOKEN_PRINT" node",
672 ConfigInfo::CI_USED,
673 false,
674 ConfigInfo::CI_INT,
675 "4096",
676 "32",
677 STR_VALUE(MAX_INT_RNIL) },
678
679 {
680 CFG_DB_NO_SCANS,
681 "MaxNoOfConcurrentScans",
682 DB_TOKEN,
683 "Max number of scans executing concurrently on the "DB_TOKEN_PRINT" node",
684 ConfigInfo::CI_USED,
685 false,
686 ConfigInfo::CI_INT,
687 "256",
688 "2",
689 "500" },
690
691 {
692 CFG_DB_TRANS_BUFFER_MEM,
693 "TransactionBufferMemory",
694 DB_TOKEN,
695 "Dynamic buffer space (in bytes) for key and attribute data allocated for each "DB_TOKEN_PRINT" node",
696 ConfigInfo::CI_USED,
697 false,
698 ConfigInfo::CI_INT,
699 "1M",
700 "1K",
701 STR_VALUE(MAX_INT_RNIL) },
702
703 {
704 CFG_DB_INDEX_MEM,
705 "IndexMemory",
706 DB_TOKEN,
707 "Number bytes on each "DB_TOKEN_PRINT" node allocated for storing indexes",
708 ConfigInfo::CI_USED,
709 false,
710 ConfigInfo::CI_INT64,
711 "18M",
712 "1M",
713 "1024G" },
714
715 {
716 CFG_DB_DATA_MEM,
717 "DataMemory",
718 DB_TOKEN,
719 "Number bytes on each "DB_TOKEN_PRINT" node allocated for storing data",
720 ConfigInfo::CI_USED,
721 false,
722 ConfigInfo::CI_INT64,
723 "80M",
724 "1M",
725 "1024G" },
726
727 {
728 CFG_DB_UNDO_INDEX_BUFFER,
729 "UndoIndexBuffer",
730 DB_TOKEN,
731 "Number bytes on each "DB_TOKEN_PRINT" node allocated for writing UNDO logs for index part",
732 ConfigInfo::CI_USED,
733 false,
734 ConfigInfo::CI_INT,
735 "2M",
736 "1M",
737 STR_VALUE(MAX_INT_RNIL)},
738
739 {
740 CFG_DB_UNDO_DATA_BUFFER,
741 "UndoDataBuffer",
742 DB_TOKEN,
743 "Number bytes on each "DB_TOKEN_PRINT" node allocated for writing UNDO logs for data part",
744 ConfigInfo::CI_USED,
745 false,
746 ConfigInfo::CI_INT,
747 "16M",
748 "1M",
749 STR_VALUE(MAX_INT_RNIL)},
750
751 {
752 CFG_DB_REDO_BUFFER,
753 "RedoBuffer",
754 DB_TOKEN,
755 "Number bytes on each "DB_TOKEN_PRINT" node allocated for writing REDO logs",
756 ConfigInfo::CI_USED,
757 false,
758 ConfigInfo::CI_INT,
759 "8M",
760 "1M",
761 STR_VALUE(MAX_INT_RNIL)},
762
763 {
764 CFG_DB_LONG_SIGNAL_BUFFER,
765 "LongMessageBuffer",
766 DB_TOKEN,
767 "Number bytes on each "DB_TOKEN_PRINT" node allocated for internal long messages",
768 ConfigInfo::CI_USED,
769 false,
770 ConfigInfo::CI_INT,
771 "1M",
772 "512k",
773 STR_VALUE(MAX_INT_RNIL)},
774
775 {
776 CFG_DB_DISK_PAGE_BUFFER_MEMORY,
777 "DiskPageBufferMemory",
778 DB_TOKEN,
779 "Number bytes on each "DB_TOKEN_PRINT" node allocated for disk page buffer cache",
780 ConfigInfo::CI_USED,
781 false,
782 ConfigInfo::CI_INT64,
783 "64M",
784 "4M",
785 "1024G" },
786
787 {
788 CFG_DB_SGA,
789 "SharedGlobalMemory",
790 DB_TOKEN,
791 "Total number bytes on each "DB_TOKEN_PRINT" node allocated for any use",
792 ConfigInfo::CI_USED,
793 false,
794 ConfigInfo::CI_INT64,
795 "20M",
796 "0",
797 "65536G" }, // 32k pages * 32-bit i value
798
799 {
800 CFG_DB_START_PARTIAL_TIMEOUT,
801 "StartPartialTimeout",
802 DB_TOKEN,
803 "Time to wait before trying to start wo/ all nodes. 0=Wait forever",
804 ConfigInfo::CI_USED,
805 true,
806 ConfigInfo::CI_INT,
807 "30000",
808 "0",
809 STR_VALUE(MAX_INT_RNIL) },
810
811 {
812 CFG_DB_START_PARTITION_TIMEOUT,
813 "StartPartitionedTimeout",
814 DB_TOKEN,
815 "Time to wait before trying to start partitioned. 0=Wait forever",
816 ConfigInfo::CI_USED,
817 true,
818 ConfigInfo::CI_INT,
819 "60000",
820 "0",
821 STR_VALUE(MAX_INT_RNIL) },
822
823 {
824 CFG_DB_START_FAILURE_TIMEOUT,
825 "StartFailureTimeout",
826 DB_TOKEN,
827 "Time to wait before terminating. 0=Wait forever",
828 ConfigInfo::CI_USED,
829 true,
830 ConfigInfo::CI_INT,
831 "0",
832 "0",
833 STR_VALUE(MAX_INT_RNIL) },
834
835 {
836 CFG_DB_HEARTBEAT_INTERVAL,
837 "HeartbeatIntervalDbDb",
838 DB_TOKEN,
839 "Time between "DB_TOKEN_PRINT"-"DB_TOKEN_PRINT" heartbeats. "DB_TOKEN_PRINT" considered dead after 3 missed HBs",
840 ConfigInfo::CI_USED,
841 true,
842 ConfigInfo::CI_INT,
843 "1500",
844 "10",
845 STR_VALUE(MAX_INT_RNIL) },
846
847 {
848 CFG_DB_API_HEARTBEAT_INTERVAL,
849 "HeartbeatIntervalDbApi",
850 DB_TOKEN,
851 "Time between "API_TOKEN_PRINT"-"DB_TOKEN_PRINT" heartbeats. "API_TOKEN_PRINT" connection closed after 3 missed HBs",
852 ConfigInfo::CI_USED,
853 true,
854 ConfigInfo::CI_INT,
855 "1500",
856 "100",
857 STR_VALUE(MAX_INT_RNIL) },
858
859 {
860 CFG_DB_LCP_INTERVAL,
861 "TimeBetweenLocalCheckpoints",
862 DB_TOKEN,
863 "Time between taking snapshots of the database (expressed in 2log of bytes)",
864 ConfigInfo::CI_USED,
865 true,
866 ConfigInfo::CI_INT,
867 "20",
868 "0",
869 "31" },
870
871 {
872 CFG_DB_GCP_INTERVAL,
873 "TimeBetweenGlobalCheckpoints",
874 DB_TOKEN,
875 "Time between doing group commit of transactions to disk",
876 ConfigInfo::CI_USED,
877 true,
878 ConfigInfo::CI_INT,
879 "2000",
880 "10",
881 "32000" },
882
883 {
884 CFG_DB_NO_REDOLOG_FILES,
885 "NoOfFragmentLogFiles",
886 DB_TOKEN,
887 "No of 16 Mbyte Redo log files in each of 4 file sets belonging to "DB_TOKEN_PRINT" node",
888 ConfigInfo::CI_USED,
889 false,
890 ConfigInfo::CI_INT,
891 "16",
892 "3",
893 STR_VALUE(MAX_INT_RNIL) },
894
895 {
896 CFG_DB_REDOLOG_FILE_SIZE,
897 "FragmentLogFileSize",
898 DB_TOKEN,
899 "Size of each Redo log file",
900 ConfigInfo::CI_USED,
901 false,
902 ConfigInfo::CI_INT,
903 "16M",
904 "4M",
905 "1G" },
906
907 {
908 CFG_DB_MAX_OPEN_FILES,
909 "MaxNoOfOpenFiles",
910 DB_TOKEN,
911 "Max number of files open per "DB_TOKEN_PRINT" node.(One thread is created per file)",
912 ConfigInfo::CI_USED,
913 false,
914 ConfigInfo::CI_INT,
915 "0",
916 "20",
917 STR_VALUE(MAX_INT_RNIL) },
918
919 {
920 CFG_DB_INITIAL_OPEN_FILES,
921 "InitialNoOfOpenFiles",
922 DB_TOKEN,
923 "Initial number of files open per "DB_TOKEN_PRINT" node.(One thread is created per file)",
924 ConfigInfo::CI_USED,
925 false,
926 ConfigInfo::CI_INT,
927 "27",
928 "20",
929 STR_VALUE(MAX_INT_RNIL) },
930
931 {
932 CFG_DB_TRANSACTION_CHECK_INTERVAL,
933 "TimeBetweenInactiveTransactionAbortCheck",
934 DB_TOKEN,
935 "Time between inactive transaction checks",
936 ConfigInfo::CI_USED,
937 true,
938 ConfigInfo::CI_INT,
939 "1000",
940 "1000",
941 STR_VALUE(MAX_INT_RNIL) },
942
943 {
944 CFG_DB_TRANSACTION_INACTIVE_TIMEOUT,
945 "TransactionInactiveTimeout",
946 DB_TOKEN,
947 "Time application can wait before executing another transaction part (ms).\n"
948 "This is the time the transaction coordinator waits for the application\n"
949 "to execute or send another part (query, statement) of the transaction.\n"
950 "If the application takes too long time, the transaction gets aborted.\n"
951 "Timeout set to 0 means that we don't timeout at all on application wait.",
952 ConfigInfo::CI_USED,
953 true,
954 ConfigInfo::CI_INT,
955 STR_VALUE(MAX_INT_RNIL),
956 "0",
957 STR_VALUE(MAX_INT_RNIL) },
958
959 {
960 CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT,
961 "TransactionDeadlockDetectionTimeout",
962 DB_TOKEN,
963 "Time transaction can be executing in a DB node (ms).\n"
964 "This is the time the transaction coordinator waits for each database node\n"
965 "of the transaction to execute a request. If the database node takes too\n"
966 "long time, the transaction gets aborted.",
967 ConfigInfo::CI_USED,
968 true,
969 ConfigInfo::CI_INT,
970 "1200",
971 "50",
972 STR_VALUE(MAX_INT_RNIL) },
973
974 {
975 CFG_DB_LCP_DISC_PAGES_TUP_SR,
976 "NoOfDiskPagesToDiskDuringRestartTUP",
977 DB_TOKEN,
978 "DiskCheckpointSpeedSr",
979 ConfigInfo::CI_DEPRICATED,
980 true,
981 ConfigInfo::CI_INT,
982 "40",
983 "1",
984 STR_VALUE(MAX_INT_RNIL) },
985
986 {
987 CFG_DB_LCP_DISC_PAGES_TUP,
988 "NoOfDiskPagesToDiskAfterRestartTUP",
989 DB_TOKEN,
990 "DiskCheckpointSpeed",
991 ConfigInfo::CI_DEPRICATED,
992 true,
993 ConfigInfo::CI_INT,
994 "40",
995 "1",
996 STR_VALUE(MAX_INT_RNIL) },
997
998 {
999 CFG_DB_LCP_DISC_PAGES_ACC_SR,
1000 "NoOfDiskPagesToDiskDuringRestartACC",
1001 DB_TOKEN,
1002 "DiskCheckpointSpeedSr",
1003 ConfigInfo::CI_DEPRICATED,
1004 true,
1005 ConfigInfo::CI_INT,
1006 "20",
1007 "1",
1008 STR_VALUE(MAX_INT_RNIL) },
1009
1010 {
1011 CFG_DB_LCP_DISC_PAGES_ACC,
1012 "NoOfDiskPagesToDiskAfterRestartACC",
1013 DB_TOKEN,
1014 "DiskCheckpointSpeed",
1015 ConfigInfo::CI_DEPRICATED,
1016 true,
1017 ConfigInfo::CI_INT,
1018 "20",
1019 "1",
1020 STR_VALUE(MAX_INT_RNIL) },
1021
1022
1023 {
1024 CFG_DB_DISCLESS,
1025 "Diskless",
1026 DB_TOKEN,
1027 "Run wo/ disk",
1028 ConfigInfo::CI_USED,
1029 true,
1030 ConfigInfo::CI_BOOL,
1031 "false",
1032 "false",
1033 "true"},
1034
1035 {
1036 KEY_INTERNAL,
1037 "Discless",
1038 DB_TOKEN,
1039 "Diskless",
1040 ConfigInfo::CI_DEPRICATED,
1041 true,
1042 ConfigInfo::CI_BOOL,
1043 "false",
1044 "false",
1045 "true"},
1046
1047
1048
1049 {
1050 CFG_DB_ARBIT_TIMEOUT,
1051 "ArbitrationTimeout",
1052 DB_TOKEN,
1053 "Max time (milliseconds) database partion waits for arbitration signal",
1054 ConfigInfo::CI_USED,
1055 false,
1056 ConfigInfo::CI_INT,
1057 "3000",
1058 "10",
1059 STR_VALUE(MAX_INT_RNIL) },
1060
1061 {
1062 CFG_NODE_DATADIR,
1063 "DataDir",
1064 DB_TOKEN,
1065 "Data directory for this node",
1066 ConfigInfo::CI_USED,
1067 false,
1068 ConfigInfo::CI_STRING,
1069 MYSQLCLUSTERDIR,
1070 0, 0 },
1071
1072 {
1073 CFG_DB_FILESYSTEM_PATH,
1074 "FileSystemPath",
1075 DB_TOKEN,
1076 "Path to directory where the "DB_TOKEN_PRINT" node stores its data (directory must exist)",
1077 ConfigInfo::CI_USED,
1078 false,
1079 ConfigInfo::CI_STRING,
1080 UNDEFINED,
1081 0, 0 },
1082
1083 {
1084 CFG_LOGLEVEL_STARTUP,
1085 "LogLevelStartup",
1086 DB_TOKEN,
1087 "Node startup info printed on stdout",
1088 ConfigInfo::CI_USED,
1089 false,
1090 ConfigInfo::CI_INT,
1091 "1",
1092 "0",
1093 "15" },
1094
1095 {
1096 CFG_LOGLEVEL_SHUTDOWN,
1097 "LogLevelShutdown",
1098 DB_TOKEN,
1099 "Node shutdown info printed on stdout",
1100 ConfigInfo::CI_USED,
1101 false,
1102 ConfigInfo::CI_INT,
1103 "0",
1104 "0",
1105 "15" },
1106
1107 {
1108 CFG_LOGLEVEL_STATISTICS,
1109 "LogLevelStatistic",
1110 DB_TOKEN,
1111 "Transaction, operation, transporter info printed on stdout",
1112 ConfigInfo::CI_USED,
1113 false,
1114 ConfigInfo::CI_INT,
1115 "0",
1116 "0",
1117 "15" },
1118
1119 {
1120 CFG_LOGLEVEL_CHECKPOINT,
1121 "LogLevelCheckpoint",
1122 DB_TOKEN,
1123 "Local and Global checkpoint info printed on stdout",
1124 ConfigInfo::CI_USED,
1125 false,
1126 ConfigInfo::CI_INT,
1127 "0",
1128 "0",
1129 "15" },
1130
1131 {
1132 CFG_LOGLEVEL_NODERESTART,
1133 "LogLevelNodeRestart",
1134 DB_TOKEN,
1135 "Node restart, node failure info printed on stdout",
1136 ConfigInfo::CI_USED,
1137 false,
1138 ConfigInfo::CI_INT,
1139 "0",
1140 "0",
1141 "15" },
1142
1143 {
1144 CFG_LOGLEVEL_CONNECTION,
1145 "LogLevelConnection",
1146 DB_TOKEN,
1147 "Node connect/disconnect info printed on stdout",
1148 ConfigInfo::CI_USED,
1149 false,
1150 ConfigInfo::CI_INT,
1151 "0",
1152 "0",
1153 "15" },
1154
1155 {
1156 CFG_LOGLEVEL_CONGESTION,
1157 "LogLevelCongestion",
1158 DB_TOKEN,
1159 "Congestion info printed on stdout",
1160 ConfigInfo::CI_USED,
1161 false,
1162 ConfigInfo::CI_INT,
1163 "0",
1164 "0",
1165 "15" },
1166
1167 {
1168 CFG_LOGLEVEL_ERROR,
1169 "LogLevelError",
1170 DB_TOKEN,
1171 "Transporter, heartbeat errors printed on stdout",
1172 ConfigInfo::CI_USED,
1173 false,
1174 ConfigInfo::CI_INT,
1175 "0",
1176 "0",
1177 "15" },
1178
1179 {
1180 CFG_LOGLEVEL_INFO,
1181 "LogLevelInfo",
1182 DB_TOKEN,
1183 "Heartbeat and log info printed on stdout",
1184 ConfigInfo::CI_USED,
1185 false,
1186 ConfigInfo::CI_INT,
1187 "0",
1188 "0",
1189 "15" },
1190
1191 /**
1192 * Backup
1193 */
1194 {
1195 CFG_DB_PARALLEL_BACKUPS,
1196 "ParallelBackups",
1197 DB_TOKEN,
1198 "Maximum number of parallel backups",
1199 ConfigInfo::CI_NOTIMPLEMENTED,
1200 false,
1201 ConfigInfo::CI_INT,
1202 "1",
1203 "1",
1204 "1" },
1205
1206 {
1207 CFG_DB_BACKUP_DATADIR,
1208 "BackupDataDir",
1209 DB_TOKEN,
1210 "Path to where to store backups",
1211 ConfigInfo::CI_USED,
1212 false,
1213 ConfigInfo::CI_STRING,
1214 UNDEFINED,
1215 0, 0 },
1216
1217 {
1218 CFG_DB_DISK_SYNCH_SIZE,
1219 "DiskSyncSize",
1220 DB_TOKEN,
1221 "Data written to a file before a synch is forced",
1222 ConfigInfo::CI_USED,
1223 false,
1224 ConfigInfo::CI_INT,
1225 "4M",
1226 "32k",
1227 STR_VALUE(MAX_INT_RNIL) },
1228
1229 {
1230 CFG_DB_CHECKPOINT_SPEED,
1231 "DiskCheckpointSpeed",
1232 DB_TOKEN,
1233 "Bytes per second allowed to be written by checkpoint",
1234 ConfigInfo::CI_USED,
1235 false,
1236 ConfigInfo::CI_INT,
1237 "10M",
1238 "1M",
1239 STR_VALUE(MAX_INT_RNIL) },
1240
1241 {
1242 CFG_DB_CHECKPOINT_SPEED_SR,
1243 "DiskCheckpointSpeedInRestart",
1244 DB_TOKEN,
1245 "Bytes per second allowed to be written by checkpoint during restart",
1246 ConfigInfo::CI_USED,
1247 false,
1248 ConfigInfo::CI_INT,
1249 "100M",
1250 "1M",
1251 STR_VALUE(MAX_INT_RNIL) },
1252
1253 {
1254 CFG_DB_BACKUP_MEM,
1255 "BackupMemory",
1256 DB_TOKEN,
1257 "Total memory allocated for backups per node (in bytes)",
1258 ConfigInfo::CI_USED,
1259 false,
1260 ConfigInfo::CI_INT,
1261 "4M", // sum of BackupDataBufferSize and BackupLogBufferSize
1262 "0",
1263 STR_VALUE(MAX_INT_RNIL) },
1264
1265 {
1266 CFG_DB_BACKUP_DATA_BUFFER_MEM,
1267 "BackupDataBufferSize",
1268 DB_TOKEN,
1269 "Default size of databuffer for a backup (in bytes)",
1270 ConfigInfo::CI_USED,
1271 false,
1272 ConfigInfo::CI_INT,
1273 "2M", // remember to change BackupMemory
1274 "0",
1275 STR_VALUE(MAX_INT_RNIL) },
1276
1277 {
1278 CFG_DB_BACKUP_LOG_BUFFER_MEM,
1279 "BackupLogBufferSize",
1280 DB_TOKEN,
1281 "Default size of logbuffer for a backup (in bytes)",
1282 ConfigInfo::CI_USED,
1283 false,
1284 ConfigInfo::CI_INT,
1285 "2M", // remember to change BackupMemory
1286 "0",
1287 STR_VALUE(MAX_INT_RNIL) },
1288
1289 {
1290 CFG_DB_BACKUP_WRITE_SIZE,
1291 "BackupWriteSize",
1292 DB_TOKEN,
1293 "Default size of filesystem writes made by backup (in bytes)",
1294 ConfigInfo::CI_USED,
1295 false,
1296 ConfigInfo::CI_INT,
1297 "32K",
1298 "2K",
1299 STR_VALUE(MAX_INT_RNIL) },
1300
1301 {
1302 CFG_DB_BACKUP_MAX_WRITE_SIZE,
1303 "BackupMaxWriteSize",
1304 DB_TOKEN,
1305 "Max size of filesystem writes made by backup (in bytes)",
1306 ConfigInfo::CI_USED,
1307 false,
1308 ConfigInfo::CI_INT,
1309 "256K",
1310 "2K",
1311 STR_VALUE(MAX_INT_RNIL) },
1312
1313 {
1314 CFG_DB_STRING_MEMORY,
1315 "StringMemory",
1316 DB_TOKEN,
1317 "Default size of string memory (0 -> 5% of max 1-100 -> %of max, >100 -> actual bytes)",
1318 ConfigInfo::CI_USED,
1319 false,
1320 ConfigInfo::CI_INT,
1321 "0",
1322 "0",
1323 STR_VALUE(MAX_INT_RNIL) },
1324
1325 {
1326 CFG_DB_MAX_ALLOCATE,
1327 "MaxAllocate",
1328 DB_TOKEN,
1329 "Maximum size of allocation to use when allocating memory for tables",
1330 ConfigInfo::CI_USED,
1331 false,
1332 ConfigInfo::CI_INT,
1333 "32M",
1334 "1M",
1335 "1G" },
1336
1337 {
1338 CFG_DB_MEMREPORT_FREQUENCY,
1339 "MemReportFrequency",
1340 DB_TOKEN,
1341 "Frequency of mem reports in seconds, 0 = only when passing %-limits",
1342 ConfigInfo::CI_USED,
1343 false,
1344 ConfigInfo::CI_INT,
1345 "0",
1346 "0",
1347 STR_VALUE(MAX_INT_RNIL) },
1348
1349 {
1350 CFG_DB_O_DIRECT,
1351 "ODirect",
1352 DB_TOKEN,
1353 "Use O_DIRECT file write/read when possible",
1354 ConfigInfo::CI_USED,
1355 true,
1356 ConfigInfo::CI_BOOL,
1357 "false",
1358 "false",
1359 "true"},
1360
1361 /***************************************************************************
1362 * API
1363 ***************************************************************************/
1364 {
1365 CFG_SECTION_NODE,
1366 API_TOKEN,
1367 API_TOKEN,
1368 "Node section",
1369 ConfigInfo::CI_USED,
1370 false,
1371 ConfigInfo::CI_SECTION,
1372 (const char *)NODE_TYPE_API,
1373 0, 0
1374 },
1375
1376 {
1377 CFG_NODE_HOST,
1378 "HostName",
1379 API_TOKEN,
1380 "Name of computer for this node",
1381 ConfigInfo::CI_INTERNAL,
1382 false,
1383 ConfigInfo::CI_STRING,
1384 "",
1385 0, 0 },
1386
1387 {
1388 CFG_NODE_SYSTEM,
1389 "System",
1390 API_TOKEN,
1391 "Name of system for this node",
1392 ConfigInfo::CI_INTERNAL,
1393 false,
1394 ConfigInfo::CI_STRING,
1395 UNDEFINED,
1396 0, 0 },
1397
1398 {
1399 KEY_INTERNAL,
1400 "Id",
1401 API_TOKEN,
1402 "",
1403 ConfigInfo::CI_DEPRICATED,
1404 false,
1405 ConfigInfo::CI_INT,
1406 MANDATORY,
1407 "1",
1408 STR_VALUE(MAX_NODES_ID) },
1409
1410 {
1411 CFG_NODE_ID,
1412 "NodeId",
1413 API_TOKEN,
1414 "Number identifying application node ("API_TOKEN_PRINT")",
1415 ConfigInfo::CI_USED,
1416 false,
1417 ConfigInfo::CI_INT,
1418 MANDATORY,
1419 "1",
1420 STR_VALUE(MAX_NODES_ID) },
1421
1422 {
1423 KEY_INTERNAL,
1424 "ExecuteOnComputer",
1425 API_TOKEN,
1426 "String referencing an earlier defined COMPUTER",
1427 ConfigInfo::CI_USED,
1428 false,
1429 ConfigInfo::CI_STRING,
1430 UNDEFINED,
1431 0, 0 },
1432
1433 {
1434 CFG_NODE_ARBIT_RANK,
1435 "ArbitrationRank",
1436 API_TOKEN,
1437 "If 0, then "API_TOKEN_PRINT" is not arbitrator. Kernel selects arbitrators in order 1, 2",
1438 ConfigInfo::CI_USED,
1439 false,
1440 ConfigInfo::CI_INT,
1441 "0",
1442 "0",
1443 "2" },
1444
1445 {
1446 CFG_NODE_ARBIT_DELAY,
1447 "ArbitrationDelay",
1448 API_TOKEN,
1449 "When asked to arbitrate, arbitrator waits this long before voting (msec)",
1450 ConfigInfo::CI_USED,
1451 false,
1452 ConfigInfo::CI_INT,
1453 "0",
1454 "0",
1455 STR_VALUE(MAX_INT_RNIL) },
1456
1457 {
1458 CFG_MAX_SCAN_BATCH_SIZE,
1459 "MaxScanBatchSize",
1460 "API",
1461 "The maximum collective batch size for one scan",
1462 ConfigInfo::CI_USED,
1463 false,
1464 ConfigInfo::CI_INT,
1465 STR_VALUE(MAX_SCAN_BATCH_SIZE),
1466 "32k",
1467 "16M" },
1468
1469 {
1470 CFG_BATCH_BYTE_SIZE,
1471 "BatchByteSize",
1472 "API",
1473 "The default batch size in bytes",
1474 ConfigInfo::CI_USED,
1475 false,
1476 ConfigInfo::CI_INT,
1477 STR_VALUE(SCAN_BATCH_SIZE),
1478 "1k",
1479 "1M" },
1480
1481 {
1482 CFG_BATCH_SIZE,
1483 "BatchSize",
1484 "API",
1485 "The default batch size in number of records",
1486 ConfigInfo::CI_USED,
1487 false,
1488 ConfigInfo::CI_INT,
1489 STR_VALUE(DEF_BATCH_SIZE),
1490 "1",
1491 STR_VALUE(MAX_PARALLEL_OP_PER_SCAN) },
1492
1493 /****************************************************************************
1494 * MGM
1495 ***************************************************************************/
1496 {
1497 CFG_SECTION_NODE,
1498 MGM_TOKEN,
1499 MGM_TOKEN,
1500 "Node section",
1501 ConfigInfo::CI_USED,
1502 false,
1503 ConfigInfo::CI_SECTION,
1504 (const char *)NODE_TYPE_MGM,
1505 0, 0
1506 },
1507
1508 {
1509 CFG_NODE_HOST,
1510 "HostName",
1511 MGM_TOKEN,
1512 "Name of computer for this node",
1513 ConfigInfo::CI_INTERNAL,
1514 false,
1515 ConfigInfo::CI_STRING,
1516 "",
1517 0, 0 },
1518
1519 {
1520 CFG_NODE_DATADIR,
1521 "DataDir",
1522 MGM_TOKEN,
1523 "Data directory for this node",
1524 ConfigInfo::CI_USED,
1525 false,
1526 ConfigInfo::CI_STRING,
1527 MYSQLCLUSTERDIR,
1528 0, 0 },
1529
1530 {
1531 CFG_NODE_SYSTEM,
1532 "System",
1533 MGM_TOKEN,
1534 "Name of system for this node",
1535 ConfigInfo::CI_INTERNAL,
1536 false,
1537 ConfigInfo::CI_STRING,
1538 UNDEFINED,
1539 0, 0 },
1540
1541 {
1542 KEY_INTERNAL,
1543 "Id",
1544 MGM_TOKEN,
1545 "",
1546 ConfigInfo::CI_DEPRICATED,
1547 false,
1548 ConfigInfo::CI_INT,
1549 MANDATORY,
1550 "1",
1551 STR_VALUE(MAX_NODES_ID) },
1552
1553 {
1554 CFG_NODE_ID,
1555 "NodeId",
1556 MGM_TOKEN,
1557 "Number identifying the management server node ("MGM_TOKEN_PRINT")",
1558 ConfigInfo::CI_USED,
1559 false,
1560 ConfigInfo::CI_INT,
1561 MANDATORY,
1562 "1",
1563 STR_VALUE(MAX_NODES_ID) },
1564
1565 {
1566 CFG_LOG_DESTINATION,
1567 "LogDestination",
1568 MGM_TOKEN,
1569 "String describing where logmessages are sent",
1570 ConfigInfo::CI_USED,
1571 false,
1572 ConfigInfo::CI_STRING,
1573 0,
1574 0, 0 },
1575
1576 {
1577 KEY_INTERNAL,
1578 "ExecuteOnComputer",
1579 MGM_TOKEN,
1580 "String referencing an earlier defined COMPUTER",
1581 ConfigInfo::CI_USED,
1582 false,
1583 ConfigInfo::CI_STRING,
1584 0,
1585 0, 0 },
1586
1587 {
1588 KEY_INTERNAL,
1589 "MaxNoOfSavedEvents",
1590 MGM_TOKEN,
1591 "",
1592 ConfigInfo::CI_USED,
1593 false,
1594 ConfigInfo::CI_INT,
1595 "100",
1596 "0",
1597 STR_VALUE(MAX_INT_RNIL) },
1598
1599 {
1600 CFG_MGM_PORT,
1601 "PortNumber",
1602 MGM_TOKEN,
1603 "Port number to give commands to/fetch configurations from management server",
1604 ConfigInfo::CI_USED,
1605 false,
1606 ConfigInfo::CI_INT,
1607 NDB_PORT,
1608 "0",
1609 STR_VALUE(MAX_PORT_NO) },
1610
1611 {
1612 KEY_INTERNAL,
1613 "PortNumberStats",
1614 MGM_TOKEN,
1615 "Port number used to get statistical information from a management server",
1616 ConfigInfo::CI_USED,
1617 false,
1618 ConfigInfo::CI_INT,
1619 UNDEFINED,
1620 "0",
1621 STR_VALUE(MAX_PORT_NO) },
1622
1623 {
1624 CFG_NODE_ARBIT_RANK,
1625 "ArbitrationRank",
1626 MGM_TOKEN,
1627 "If 0, then "MGM_TOKEN_PRINT" is not arbitrator. Kernel selects arbitrators in order 1, 2",
1628 ConfigInfo::CI_USED,
1629 false,
1630 ConfigInfo::CI_INT,
1631 "1",
1632 "0",
1633 "2" },
1634
1635 {
1636 CFG_NODE_ARBIT_DELAY,
1637 "ArbitrationDelay",
1638 MGM_TOKEN,
1639 "",
1640 ConfigInfo::CI_USED,
1641 false,
1642 ConfigInfo::CI_INT,
1643 "0",
1644 "0",
1645 STR_VALUE(MAX_INT_RNIL) },
1646
1647 /****************************************************************************
1648 * TCP
1649 ***************************************************************************/
1650 {
1651 CFG_SECTION_CONNECTION,
1652 "TCP",
1653 "TCP",
1654 "Connection section",
1655 ConfigInfo::CI_USED,
1656 false,
1657 ConfigInfo::CI_SECTION,
1658 (const char *)CONNECTION_TYPE_TCP,
1659 0, 0
1660 },
1661
1662 {
1663 CFG_CONNECTION_HOSTNAME_1,
1664 "HostName1",
1665 "TCP",
1666 "Name/IP of computer on one side of the connection",
1667 ConfigInfo::CI_INTERNAL,
1668 false,
1669 ConfigInfo::CI_STRING,
1670 UNDEFINED,
1671 0, 0 },
1672
1673 {
1674 CFG_CONNECTION_HOSTNAME_2,
1675 "HostName2",
1676 "TCP",
1677 "Name/IP of computer on one side of the connection",
1678 ConfigInfo::CI_INTERNAL,
1679 false,
1680 ConfigInfo::CI_STRING,
1681 UNDEFINED,
1682 0, 0 },
1683
1684 {
1685 CFG_CONNECTION_NODE_1,
1686 "NodeId1",
1687 "TCP",
1688 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
1689 ConfigInfo::CI_USED,
1690 false,
1691 ConfigInfo::CI_STRING,
1692 MANDATORY,
1693 0, 0 },
1694
1695 {
1696 CFG_CONNECTION_NODE_2,
1697 "NodeId2",
1698 "TCP",
1699 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
1700 ConfigInfo::CI_USED,
1701 false,
1702 ConfigInfo::CI_STRING,
1703 MANDATORY,
1704 0, 0 },
1705
1706 {
1707 CFG_CONNECTION_GROUP,
1708 "Group",
1709 "TCP",
1710 "",
1711 ConfigInfo::CI_USED,
1712 false,
1713 ConfigInfo::CI_INT,
1714 "55",
1715 "0", "200" },
1716
1717 {
1718 CFG_CONNECTION_NODE_ID_SERVER,
1719 "NodeIdServer",
1720 "TCP",
1721 "",
1722 ConfigInfo::CI_USED,
1723 false,
1724 ConfigInfo::CI_INT,
1725 MANDATORY,
1726 "1", "63" },
1727
1728 {
1729 CFG_CONNECTION_SEND_SIGNAL_ID,
1730 "SendSignalId",
1731 "TCP",
1732 "Sends id in each signal. Used in trace files.",
1733 ConfigInfo::CI_USED,
1734 false,
1735 ConfigInfo::CI_BOOL,
1736 "true",
1737 "false",
1738 "true" },
1739
1740
1741 {
1742 CFG_CONNECTION_CHECKSUM,
1743 "Checksum",
1744 "TCP",
1745 "If checksum is enabled, all signals between nodes are checked for errors",
1746 ConfigInfo::CI_USED,
1747 false,
1748 ConfigInfo::CI_BOOL,
1749 "false",
1750 "false",
1751 "true" },
1752
1753 {
1754 CFG_CONNECTION_SERVER_PORT,
1755 "PortNumber",
1756 "TCP",
1757 "Port used for this transporter",
1758 ConfigInfo::CI_USED,
1759 false,
1760 ConfigInfo::CI_INT,
1761 MANDATORY,
1762 "0",
1763 STR_VALUE(MAX_PORT_NO) },
1764
1765 {
1766 CFG_TCP_SEND_BUFFER_SIZE,
1767 "SendBufferMemory",
1768 "TCP",
1769 "Bytes of buffer for signals sent from this node",
1770 ConfigInfo::CI_USED,
1771 false,
1772 ConfigInfo::CI_INT,
1773 "256K",
1774 "64K",
1775 STR_VALUE(MAX_INT_RNIL) },
1776
1777 {
1778 CFG_TCP_RECEIVE_BUFFER_SIZE,
1779 "ReceiveBufferMemory",
1780 "TCP",
1781 "Bytes of buffer for signals received by this node",
1782 ConfigInfo::CI_USED,
1783 false,
1784 ConfigInfo::CI_INT,
1785 "64K",
1786 "16K",
1787 STR_VALUE(MAX_INT_RNIL) },
1788
1789 {
1790 CFG_TCP_PROXY,
1791 "Proxy",
1792 "TCP",
1793 "",
1794 ConfigInfo::CI_USED,
1795 false,
1796 ConfigInfo::CI_STRING,
1797 UNDEFINED,
1798 0, 0 },
1799
1800 {
1801 CFG_CONNECTION_NODE_1_SYSTEM,
1802 "NodeId1_System",
1803 "TCP",
1804 "System for node 1 in connection",
1805 ConfigInfo::CI_INTERNAL,
1806 false,
1807 ConfigInfo::CI_STRING,
1808 UNDEFINED,
1809 0, 0 },
1810
1811 {
1812 CFG_CONNECTION_NODE_2_SYSTEM,
1813 "NodeId2_System",
1814 "TCP",
1815 "System for node 2 in connection",
1816 ConfigInfo::CI_INTERNAL,
1817 false,
1818 ConfigInfo::CI_STRING,
1819 UNDEFINED,
1820 0, 0 },
1821
1822
1823 /****************************************************************************
1824 * SHM
1825 ***************************************************************************/
1826 {
1827 CFG_SECTION_CONNECTION,
1828 "SHM",
1829 "SHM",
1830 "Connection section",
1831 ConfigInfo::CI_USED,
1832 false,
1833 ConfigInfo::CI_SECTION,
1834 (const char *)CONNECTION_TYPE_SHM,
1835 0, 0 },
1836
1837 {
1838 CFG_CONNECTION_HOSTNAME_1,
1839 "HostName1",
1840 "SHM",
1841 "Name/IP of computer on one side of the connection",
1842 ConfigInfo::CI_INTERNAL,
1843 false,
1844 ConfigInfo::CI_STRING,
1845 UNDEFINED,
1846 0, 0 },
1847
1848 {
1849 CFG_CONNECTION_HOSTNAME_2,
1850 "HostName2",
1851 "SHM",
1852 "Name/IP of computer on one side of the connection",
1853 ConfigInfo::CI_INTERNAL,
1854 false,
1855 ConfigInfo::CI_STRING,
1856 UNDEFINED,
1857 0, 0 },
1858
1859 {
1860 CFG_CONNECTION_SERVER_PORT,
1861 "PortNumber",
1862 "SHM",
1863 "Port used for this transporter",
1864 ConfigInfo::CI_USED,
1865 false,
1866 ConfigInfo::CI_INT,
1867 MANDATORY,
1868 "0",
1869 STR_VALUE(MAX_PORT_NO) },
1870
1871 {
1872 CFG_SHM_SIGNUM,
1873 "Signum",
1874 "SHM",
1875 "Signum to be used for signalling",
1876 ConfigInfo::CI_USED,
1877 false,
1878 ConfigInfo::CI_INT,
1879 UNDEFINED,
1880 "0",
1881 STR_VALUE(MAX_INT_RNIL) },
1882
1883 {
1884 CFG_CONNECTION_NODE_1,
1885 "NodeId1",
1886 "SHM",
1887 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
1888 ConfigInfo::CI_USED,
1889 false,
1890 ConfigInfo::CI_STRING,
1891 MANDATORY,
1892 0, 0 },
1893
1894 {
1895 CFG_CONNECTION_NODE_2,
1896 "NodeId2",
1897 "SHM",
1898 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
1899 ConfigInfo::CI_USED,
1900 false,
1901 ConfigInfo::CI_STRING,
1902 MANDATORY,
1903 0, 0 },
1904
1905 {
1906 CFG_CONNECTION_GROUP,
1907 "Group",
1908 "SHM",
1909 "",
1910 ConfigInfo::CI_USED,
1911 false,
1912 ConfigInfo::CI_INT,
1913 "35",
1914 "0", "200" },
1915
1916 {
1917 CFG_CONNECTION_NODE_ID_SERVER,
1918 "NodeIdServer",
1919 "SHM",
1920 "",
1921 ConfigInfo::CI_USED,
1922 false,
1923 ConfigInfo::CI_INT,
1924 MANDATORY,
1925 "1", "63" },
1926
1927 {
1928 CFG_CONNECTION_SEND_SIGNAL_ID,
1929 "SendSignalId",
1930 "SHM",
1931 "Sends id in each signal. Used in trace files.",
1932 ConfigInfo::CI_USED,
1933 false,
1934 ConfigInfo::CI_BOOL,
1935 "false",
1936 "false",
1937 "true" },
1938
1939
1940 {
1941 CFG_CONNECTION_CHECKSUM,
1942 "Checksum",
1943 "SHM",
1944 "If checksum is enabled, all signals between nodes are checked for errors",
1945 ConfigInfo::CI_USED,
1946 false,
1947 ConfigInfo::CI_BOOL,
1948 "true",
1949 "false",
1950 "true" },
1951
1952 {
1953 CFG_SHM_KEY,
1954 "ShmKey",
1955 "SHM",
1956 "A shared memory key",
1957 ConfigInfo::CI_USED,
1958 false,
1959 ConfigInfo::CI_INT,
1960 UNDEFINED,
1961 "0",
1962 STR_VALUE(MAX_INT_RNIL) },
1963
1964 {
1965 CFG_SHM_BUFFER_MEM,
1966 "ShmSize",
1967 "SHM",
1968 "Size of shared memory segment",
1969 ConfigInfo::CI_USED,
1970 false,
1971 ConfigInfo::CI_INT,
1972 "1M",
1973 "64K",
1974 STR_VALUE(MAX_INT_RNIL) },
1975
1976 {
1977 CFG_CONNECTION_NODE_1_SYSTEM,
1978 "NodeId1_System",
1979 "SHM",
1980 "System for node 1 in connection",
1981 ConfigInfo::CI_INTERNAL,
1982 false,
1983 ConfigInfo::CI_STRING,
1984 UNDEFINED,
1985 0, 0 },
1986
1987 {
1988 CFG_CONNECTION_NODE_2_SYSTEM,
1989 "NodeId2_System",
1990 "SHM",
1991 "System for node 2 in connection",
1992 ConfigInfo::CI_INTERNAL,
1993 false,
1994 ConfigInfo::CI_STRING,
1995 UNDEFINED,
1996 0, 0 },
1997
1998 /****************************************************************************
1999 * SCI
2000 ***************************************************************************/
2001 {
2002 CFG_SECTION_CONNECTION,
2003 "SCI",
2004 "SCI",
2005 "Connection section",
2006 ConfigInfo::CI_USED,
2007 false,
2008 ConfigInfo::CI_SECTION,
2009 (const char *)CONNECTION_TYPE_SCI,
2010 0, 0
2011 },
2012
2013 {
2014 CFG_CONNECTION_NODE_1,
2015 "NodeId1",
2016 "SCI",
2017 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2018 ConfigInfo::CI_USED,
2019 false,
2020 ConfigInfo::CI_STRING,
2021 MANDATORY,
2022 "0",
2023 STR_VALUE(MAX_INT_RNIL) },
2024
2025 {
2026 CFG_CONNECTION_NODE_2,
2027 "NodeId2",
2028 "SCI",
2029 "Id of node ("DB_TOKEN_PRINT", "API_TOKEN_PRINT" or "MGM_TOKEN_PRINT") on one side of the connection",
2030 ConfigInfo::CI_USED,
2031 false,
2032 ConfigInfo::CI_STRING,
2033 MANDATORY,
2034 "0",
2035 STR_VALUE(MAX_INT_RNIL) },
2036
2037 {
2038 CFG_CONNECTION_GROUP,
2039 "Group",
2040 "SCI",
2041 "",
2042 ConfigInfo::CI_USED,
2043 false,
2044 ConfigInfo::CI_INT,
2045 "15",
2046 "0", "200" },
2047
2048 {
2049 CFG_CONNECTION_NODE_ID_SERVER,
2050 "NodeIdServer",
2051 "SCI",
2052 "",
2053 ConfigInfo::CI_USED,
2054 false,
2055 ConfigInfo::CI_INT,
2056 MANDATORY,
2057 "1", "63" },
2058
2059 {
2060 CFG_CONNECTION_HOSTNAME_1,
2061 "HostName1",
2062 "SCI",
2063 "Name/IP of computer on one side of the connection",
2064 ConfigInfo::CI_INTERNAL,
2065 false,
2066 ConfigInfo::CI_STRING,
2067 UNDEFINED,
2068 0, 0 },
2069
2070 {
2071 CFG_CONNECTION_HOSTNAME_2,
2072 "HostName2",
2073 "SCI",
2074 "Name/IP of computer on one side of the connection",
2075 ConfigInfo::CI_INTERNAL,
2076 false,
2077 ConfigInfo::CI_STRING,
2078 UNDEFINED,
2079 0, 0 },
2080
2081 {
2082 CFG_CONNECTION_SERVER_PORT,
2083 "PortNumber",
2084 "SCI",
2085 "Port used for this transporter",
2086 ConfigInfo::CI_USED,
2087 false,
2088 ConfigInfo::CI_INT,
2089 MANDATORY,
2090 "0",
2091 STR_VALUE(MAX_PORT_NO) },
2092
2093 {
2094 CFG_SCI_HOST1_ID_0,
2095 "Host1SciId0",
2096 "SCI",
2097 "SCI-node id for adapter 0 on Host1 (a computer can have two adapters)",
2098 ConfigInfo::CI_USED,
2099 false,
2100 ConfigInfo::CI_INT,
2101 MANDATORY,
2102 "0",
2103 STR_VALUE(MAX_INT_RNIL) },
2104
2105 {
2106 CFG_SCI_HOST1_ID_1,
2107 "Host1SciId1",
2108 "SCI",
2109 "SCI-node id for adapter 1 on Host1 (a computer can have two adapters)",
2110 ConfigInfo::CI_USED,
2111 false,
2112 ConfigInfo::CI_INT,
2113 "0",
2114 "0",
2115 STR_VALUE(MAX_INT_RNIL) },
2116
2117 {
2118 CFG_SCI_HOST2_ID_0,
2119 "Host2SciId0",
2120 "SCI",
2121 "SCI-node id for adapter 0 on Host2 (a computer can have two adapters)",
2122 ConfigInfo::CI_USED,
2123 false,
2124 ConfigInfo::CI_INT,
2125 MANDATORY,
2126 "0",
2127 STR_VALUE(MAX_INT_RNIL) },
2128
2129 {
2130 CFG_SCI_HOST2_ID_1,
2131 "Host2SciId1",
2132 "SCI",
2133 "SCI-node id for adapter 1 on Host2 (a computer can have two adapters)",
2134 ConfigInfo::CI_USED,
2135 false,
2136 ConfigInfo::CI_INT,
2137 "0",
2138 "0",
2139 STR_VALUE(MAX_INT_RNIL) },
2140
2141 {
2142 CFG_CONNECTION_SEND_SIGNAL_ID,
2143 "SendSignalId",
2144 "SCI",
2145 "Sends id in each signal. Used in trace files.",
2146 ConfigInfo::CI_USED,
2147 false,
2148 ConfigInfo::CI_BOOL,
2149 "true",
2150 "false",
2151 "true" },
2152
2153 {
2154 CFG_CONNECTION_CHECKSUM,
2155 "Checksum",
2156 "SCI",
2157 "If checksum is enabled, all signals between nodes are checked for errors",
2158 ConfigInfo::CI_USED,
2159 false,
2160 ConfigInfo::CI_BOOL,
2161 "false",
2162 "false",
2163 "true" },
2164
2165 {
2166 CFG_SCI_SEND_LIMIT,
2167 "SendLimit",
2168 "SCI",
2169 "Transporter send buffer contents are sent when this no of bytes is buffered",
2170 ConfigInfo::CI_USED,
2171 false,
2172 ConfigInfo::CI_INT,
2173 "8K",
2174 "128",
2175 "32K" },
2176
2177 {
2178 CFG_SCI_BUFFER_MEM,
2179 "SharedBufferSize",
2180 "SCI",
2181 "Size of shared memory segment",
2182 ConfigInfo::CI_USED,
2183 false,
2184 ConfigInfo::CI_INT,
2185 "1M",
2186 "64K",
2187 STR_VALUE(MAX_INT_RNIL) },
2188
2189 {
2190 CFG_CONNECTION_NODE_1_SYSTEM,
2191 "NodeId1_System",
2192 "SCI",
2193 "System for node 1 in connection",
2194 ConfigInfo::CI_INTERNAL,
2195 false,
2196 ConfigInfo::CI_STRING,
2197 UNDEFINED,
2198 0, 0 },
2199
2200 {
2201 CFG_CONNECTION_NODE_2_SYSTEM,
2202 "NodeId2_System",
2203 "SCI",
2204 "System for node 2 in connection",
2205 ConfigInfo::CI_INTERNAL,
2206 false,
2207 ConfigInfo::CI_STRING,
2208 UNDEFINED,
2209 0, 0 }
2210 };
2211
2212 const int ConfigInfo::m_NoOfParams = sizeof(m_ParamInfo) / sizeof(ParamInfo);
2213
2214 #ifndef NDB_MGMAPI
2215 /****************************************************************************
2216 * Ctor
2217 ****************************************************************************/
require(bool v)2218 static void require(bool v)
2219 {
2220 if(!v)
2221 {
2222 if (opt_core)
2223 abort();
2224 else
2225 exit(-1);
2226 }
2227 }
2228
ConfigInfo()2229 ConfigInfo::ConfigInfo()
2230 : m_info(true), m_systemDefaults(true)
2231 {
2232 int i;
2233 Properties *section;
2234 const Properties *oldpinfo;
2235
2236 for (i=0; i<m_NoOfParams; i++) {
2237 const ParamInfo & param = m_ParamInfo[i];
2238 Uint64 default_uint64;
2239 bool default_bool;
2240
2241 // Create new section if it did not exist
2242 if (!m_info.getCopy(param._section, §ion)) {
2243 Properties newsection(true);
2244 m_info.put(param._section, &newsection);
2245
2246 // Get copy of section
2247 m_info.getCopy(param._section, §ion);
2248 }
2249
2250 // Create pinfo (parameter info) entry
2251 Properties pinfo(true);
2252 pinfo.put("Id", param._paramId);
2253 pinfo.put("Fname", param._fname);
2254 pinfo.put("Description", param._description);
2255 pinfo.put("Updateable", param._updateable);
2256 pinfo.put("Type", param._type);
2257 pinfo.put("Status", param._status);
2258
2259 if(param._default == MANDATORY){
2260 pinfo.put("Mandatory", (Uint32)1);
2261 }
2262
2263 switch (param._type) {
2264 case CI_BOOL:
2265 {
2266 bool tmp_bool;
2267 require(InitConfigFileParser::convertStringToBool(param._min, tmp_bool));
2268 pinfo.put64("Min", tmp_bool);
2269 require(InitConfigFileParser::convertStringToBool(param._max, tmp_bool));
2270 pinfo.put64("Max", tmp_bool);
2271 break;
2272 }
2273 case CI_INT:
2274 case CI_INT64:
2275 {
2276 Uint64 tmp_uint64;
2277 require(InitConfigFileParser::convertStringToUint64(param._min, tmp_uint64));
2278 pinfo.put64("Min", tmp_uint64);
2279 require(InitConfigFileParser::convertStringToUint64(param._max, tmp_uint64));
2280 pinfo.put64("Max", tmp_uint64);
2281 break;
2282 }
2283 case CI_SECTION:
2284 pinfo.put("SectionType", (Uint32)UintPtr(param._default));
2285 break;
2286 case CI_STRING:
2287 break;
2288 }
2289
2290 // Check that pinfo is really new
2291 if (section->get(param._fname, &oldpinfo)) {
2292 ndbout << "Error: Parameter " << param._fname
2293 << " defined twice in section " << param._section
2294 << "." << endl;
2295 require(false);
2296 }
2297
2298 // Add new pinfo to section
2299 section->put(param._fname, &pinfo);
2300
2301 // Replace section with modified section
2302 m_info.put(param._section, section, true);
2303 delete section;
2304
2305 if(param._type != ConfigInfo::CI_SECTION){
2306 Properties * p;
2307 if(!m_systemDefaults.getCopy(param._section, &p)){
2308 p = new Properties(true);
2309 }
2310 if(param._default != UNDEFINED &&
2311 param._default != MANDATORY){
2312 switch (param._type)
2313 {
2314 case CI_SECTION:
2315 break;
2316 case CI_STRING:
2317 require(p->put(param._fname, param._default));
2318 break;
2319 case CI_BOOL:
2320 {
2321 require(InitConfigFileParser::convertStringToBool(param._default, default_bool));
2322 require(p->put(param._fname, default_bool));
2323 break;
2324 }
2325 case CI_INT:
2326 case CI_INT64:
2327 {
2328 require(InitConfigFileParser::convertStringToUint64(param._default, default_uint64));
2329 require(p->put(param._fname, default_uint64));
2330 break;
2331 }
2332 }
2333 }
2334 require(m_systemDefaults.put(param._section, p, true));
2335 delete p;
2336 }
2337 }
2338
2339 for (i=0; i<m_NoOfParams; i++) {
2340 if(m_ParamInfo[i]._section == NULL){
2341 ndbout << "Check that each entry has a section failed." << endl;
2342 ndbout << "Parameter \"" << m_ParamInfo[i]._fname << endl;
2343 ndbout << "Edit file " << __FILE__ << "." << endl;
2344 require(false);
2345 }
2346
2347 if(m_ParamInfo[i]._type == ConfigInfo::CI_SECTION)
2348 continue;
2349
2350 const Properties * p = getInfo(m_ParamInfo[i]._section);
2351 if (!p || !p->contains(m_ParamInfo[i]._fname)) {
2352 ndbout << "Check that each pname has an fname failed." << endl;
2353 ndbout << "Parameter \"" << m_ParamInfo[i]._fname
2354 << "\" does not exist in section \""
2355 << m_ParamInfo[i]._section << "\"." << endl;
2356 ndbout << "Edit file " << __FILE__ << "." << endl;
2357 require(false);
2358 }
2359 }
2360 }
2361
2362 /****************************************************************************
2363 * Getters
2364 ****************************************************************************/
warning(const char * src,const char * arg)2365 inline void warning(const char * src, const char * arg){
2366 ndbout << "Illegal call to ConfigInfo::" << src << "() - " << arg << endl;
2367 require(false);
2368 }
2369
2370 const Properties *
getInfo(const char * section) const2371 ConfigInfo::getInfo(const char * section) const {
2372 const Properties * p;
2373 if(!m_info.get(section, &p)){
2374 return 0;
2375 // warning("getInfo", section);
2376 }
2377 return p;
2378 }
2379
2380 const Properties *
getDefaults(const char * section) const2381 ConfigInfo::getDefaults(const char * section) const {
2382 const Properties * p;
2383 if(!m_systemDefaults.get(section, &p)){
2384 return 0;
2385 //warning("getDefaults", section);
2386 }
2387 return p;
2388 }
2389
2390 static
2391 Uint64
getInfoInt(const Properties * section,const char * fname,const char * type)2392 getInfoInt(const Properties * section,
2393 const char* fname, const char * type){
2394 Uint32 val32;
2395 const Properties * p;
2396 if (section->get(fname, &p) && p->get(type, &val32)) {
2397 return val32;
2398 }
2399
2400 Uint64 val64;
2401 if(p && p->get(type, &val64)){
2402 return val64;
2403 }
2404
2405 section->print();
2406 if(section->get(fname, &p)){
2407 p->print();
2408 }
2409
2410 warning(type, fname);
2411 return 0;
2412 }
2413
2414 static
2415 const char *
getInfoString(const Properties * section,const char * fname,const char * type)2416 getInfoString(const Properties * section,
2417 const char* fname, const char * type){
2418 const char* val;
2419 const Properties * p;
2420 if (section->get(fname, &p) && p->get(type, &val)) {
2421 return val;
2422 }
2423 warning(type, fname);
2424 return val;
2425 }
2426
2427 Uint64
getMax(const Properties * section,const char * fname) const2428 ConfigInfo::getMax(const Properties * section, const char* fname) const {
2429 return getInfoInt(section, fname, "Max");
2430 }
2431
2432 Uint64
getMin(const Properties * section,const char * fname) const2433 ConfigInfo::getMin(const Properties * section, const char* fname) const {
2434 return getInfoInt(section, fname, "Min");
2435 }
2436
2437 Uint64
getDefault(const Properties * section,const char * fname) const2438 ConfigInfo::getDefault(const Properties * section, const char* fname) const {
2439 return getInfoInt(section, fname, "Default");
2440 }
2441
2442 const char*
getDescription(const Properties * section,const char * fname) const2443 ConfigInfo::getDescription(const Properties * section,
2444 const char* fname) const {
2445 return getInfoString(section, fname, "Description");
2446 }
2447
2448 bool
isSection(const char * section) const2449 ConfigInfo::isSection(const char * section) const {
2450 for (int i = 0; i<m_noOfSectionNames; i++) {
2451 if(!strcasecmp(section, m_sectionNames[i])) return true;
2452 }
2453 return false;
2454 }
2455
2456 const char*
nameToAlias(const char * name)2457 ConfigInfo::nameToAlias(const char * name) {
2458 for (int i = 0; m_sectionNameAliases[i].name != 0; i++)
2459 if(!strcasecmp(name, m_sectionNameAliases[i].name))
2460 return m_sectionNameAliases[i].alias;
2461 return 0;
2462 }
2463
2464 const char*
getAlias(const char * section)2465 ConfigInfo::getAlias(const char * section) {
2466 for (int i = 0; m_sectionNameAliases[i].name != 0; i++)
2467 if(!strcasecmp(section, m_sectionNameAliases[i].alias))
2468 return m_sectionNameAliases[i].name;
2469 return 0;
2470 }
2471
2472 bool
verify(const Properties * section,const char * fname,Uint64 value) const2473 ConfigInfo::verify(const Properties * section, const char* fname,
2474 Uint64 value) const {
2475 Uint64 min, max;
2476
2477 min = getInfoInt(section, fname, "Min");
2478 max = getInfoInt(section, fname, "Max");
2479 if(min > max){
2480 warning("verify", fname);
2481 }
2482 if (value >= min && value <= max)
2483 return true;
2484 else
2485 return false;
2486 }
2487
2488 ConfigInfo::Type
getType(const Properties * section,const char * fname) const2489 ConfigInfo::getType(const Properties * section, const char* fname) const {
2490 return (ConfigInfo::Type) getInfoInt(section, fname, "Type");
2491 }
2492
2493 ConfigInfo::Status
getStatus(const Properties * section,const char * fname) const2494 ConfigInfo::getStatus(const Properties * section, const char* fname) const {
2495 return (ConfigInfo::Status) getInfoInt(section, fname, "Status");
2496 }
2497
2498 /****************************************************************************
2499 * Printers
2500 ****************************************************************************/
2501
print() const2502 void ConfigInfo::print() const {
2503 Properties::Iterator it(&m_info);
2504 for (const char* n = it.first(); n != NULL; n = it.next()) {
2505 print(n);
2506 }
2507 }
2508
print(const char * section) const2509 void ConfigInfo::print(const char* section) const {
2510 ndbout << "****** " << section << " ******" << endl << endl;
2511 const Properties * sec = getInfo(section);
2512 Properties::Iterator it(sec);
2513 for (const char* n = it.first(); n != NULL; n = it.next()) {
2514 // Skip entries with different F- and P-names
2515 if (getStatus(sec, n) == ConfigInfo::CI_INTERNAL) continue;
2516 if (getStatus(sec, n) == ConfigInfo::CI_DEPRICATED) continue;
2517 if (getStatus(sec, n) == ConfigInfo::CI_NOTIMPLEMENTED) continue;
2518 print(sec, n);
2519 }
2520 }
2521
print(const Properties * section,const char * parameter) const2522 void ConfigInfo::print(const Properties * section,
2523 const char* parameter) const {
2524 ndbout << parameter;
2525 // ndbout << getDescription(section, parameter) << endl;
2526 switch (getType(section, parameter)) {
2527 case ConfigInfo::CI_BOOL:
2528 ndbout << " (Boolean value)" << endl;
2529 ndbout << getDescription(section, parameter) << endl;
2530 if (getDefault(section, parameter) == false) {
2531 ndbout << "Default: N (Legal values: Y, N)" << endl;
2532 } else if (getDefault(section, parameter) == true) {
2533 ndbout << "Default: Y (Legal values: Y, N)" << endl;
2534 } else if (getDefault(section, parameter) == (UintPtr)MANDATORY) {
2535 ndbout << "MANDATORY (Legal values: Y, N)" << endl;
2536 } else {
2537 ndbout << "UNKNOWN" << endl;
2538 }
2539 ndbout << endl;
2540 break;
2541
2542 case ConfigInfo::CI_INT:
2543 case ConfigInfo::CI_INT64:
2544 ndbout << " (Non-negative Integer)" << endl;
2545 ndbout << getDescription(section, parameter) << endl;
2546 if (getDefault(section, parameter) == (UintPtr)MANDATORY) {
2547 ndbout << "MANDATORY (";
2548 } else if (getDefault(section, parameter) == (UintPtr)UNDEFINED) {
2549 ndbout << "UNDEFINED (";
2550 } else {
2551 ndbout << "Default: " << getDefault(section, parameter) << " (";
2552 }
2553 ndbout << "Min: " << getMin(section, parameter) << ", ";
2554 ndbout << "Max: " << getMax(section, parameter) << ")" << endl;
2555 ndbout << endl;
2556 break;
2557
2558 case ConfigInfo::CI_STRING:
2559 ndbout << " (String)" << endl;
2560 ndbout << getDescription(section, parameter) << endl;
2561 if (getDefault(section, parameter) == (UintPtr)MANDATORY) {
2562 ndbout << "MANDATORY" << endl;
2563 } else {
2564 ndbout << "No default value" << endl;
2565 }
2566 ndbout << endl;
2567 break;
2568 case ConfigInfo::CI_SECTION:
2569 break;
2570 }
2571 }
2572
2573 /****************************************************************************
2574 * Section Rules
2575 ****************************************************************************/
2576
2577 /**
2578 * Node rule: Add "Type" and update "NoOfNodes"
2579 */
2580 bool
transformNode(InitConfigFileParser::Context & ctx,const char * data)2581 transformNode(InitConfigFileParser::Context & ctx, const char * data){
2582
2583 Uint32 id, line;
2584 if(!ctx.m_currentSection->get("NodeId", &id) && !ctx.m_currentSection->get("Id", &id)){
2585 Uint32 nextNodeId= 1;
2586 ctx.m_userProperties.get("NextNodeId", &nextNodeId);
2587 id= nextNodeId;
2588 while (ctx.m_userProperties.get("AllocatedNodeId_", id, &line))
2589 id++;
2590 if (id != nextNodeId)
2591 {
2592 fprintf(stderr,"Cluster configuration warning line %d: "
2593 "Could not use next node id %d for section [%s], "
2594 "using next unused node id %d.\n",
2595 ctx.m_sectionLineno, nextNodeId, ctx.fname, id);
2596 }
2597 ctx.m_currentSection->put("NodeId", id);
2598 } else if(ctx.m_userProperties.get("AllocatedNodeId_", id, &line)) {
2599 ctx.reportError("Duplicate nodeid in section "
2600 "[%s] starting at line: %d. Previously used on line %d.",
2601 ctx.fname, ctx.m_sectionLineno, line);
2602 return false;
2603 }
2604
2605 if(id >= MAX_NODES)
2606 {
2607 ctx.reportError("too many nodes configured, only up to %d nodes supported.",
2608 MAX_NODES);
2609 return false;
2610 }
2611
2612 // next node id _always_ next numbers after last used id
2613 ctx.m_userProperties.put("NextNodeId", id+1, true);
2614
2615 ctx.m_userProperties.put("AllocatedNodeId_", id, ctx.m_sectionLineno);
2616 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id);
2617
2618 ctx.m_currentSection->put("Type", ctx.fname);
2619
2620 Uint32 nodes = 0;
2621 ctx.m_userProperties.get("NoOfNodes", &nodes);
2622 ctx.m_userProperties.put("NoOfNodes", ++nodes, true);
2623
2624 /**
2625 * Update count (per type)
2626 */
2627 nodes = 0;
2628 ctx.m_userProperties.get(ctx.fname, &nodes);
2629 ctx.m_userProperties.put(ctx.fname, ++nodes, true);
2630
2631 return true;
2632 }
2633
checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx,const char * data)2634 static bool checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx, const char * data)
2635 {
2636 DBUG_ENTER("checkLocalhostHostnameMix");
2637 const char * hostname= 0;
2638 ctx.m_currentSection->get("HostName", &hostname);
2639 if (hostname == 0 || hostname[0] == 0)
2640 DBUG_RETURN(true);
2641
2642 Uint32 localhost_used= 0;
2643 if(!strcmp(hostname, "localhost") || !strcmp(hostname, "127.0.0.1")){
2644 localhost_used= 1;
2645 ctx.m_userProperties.put("$computer-localhost-used", localhost_used);
2646 if(!ctx.m_userProperties.get("$computer-localhost", &hostname))
2647 DBUG_RETURN(true);
2648 } else {
2649 ctx.m_userProperties.get("$computer-localhost-used", &localhost_used);
2650 ctx.m_userProperties.put("$computer-localhost", hostname);
2651 }
2652
2653 if (localhost_used) {
2654 ctx.reportError("Mixing of localhost (default for [NDBD]HostName) with other hostname(%s) is illegal",
2655 hostname);
2656 DBUG_RETURN(false);
2657 }
2658
2659 DBUG_RETURN(true);
2660 }
2661
2662 bool
fixNodeHostname(InitConfigFileParser::Context & ctx,const char * data)2663 fixNodeHostname(InitConfigFileParser::Context & ctx, const char * data)
2664 {
2665 const char * hostname;
2666 DBUG_ENTER("fixNodeHostname");
2667
2668 if (ctx.m_currentSection->get("HostName", &hostname))
2669 DBUG_RETURN(checkLocalhostHostnameMix(ctx,0));
2670
2671 const char * compId;
2672 if(!ctx.m_currentSection->get("ExecuteOnComputer", &compId))
2673 DBUG_RETURN(true);
2674
2675 const Properties * computer;
2676 char tmp[255];
2677 BaseString::snprintf(tmp, sizeof(tmp), "Computer_%s", compId);
2678 if(!ctx.m_config->get(tmp, &computer)){
2679 ctx.reportError("Computer \"%s\" not declared"
2680 "- [%s] starting at line: %d",
2681 compId, ctx.fname, ctx.m_sectionLineno);
2682 DBUG_RETURN(false);
2683 }
2684
2685 if(!computer->get("HostName", &hostname)){
2686 ctx.reportError("HostName missing in [COMPUTER] (Id: %d) "
2687 " - [%s] starting at line: %d",
2688 compId, ctx.fname, ctx.m_sectionLineno);
2689 DBUG_RETURN(false);
2690 }
2691
2692 require(ctx.m_currentSection->put("HostName", hostname));
2693 DBUG_RETURN(checkLocalhostHostnameMix(ctx,0));
2694 }
2695
2696 bool
fixFileSystemPath(InitConfigFileParser::Context & ctx,const char * data)2697 fixFileSystemPath(InitConfigFileParser::Context & ctx, const char * data){
2698 DBUG_ENTER("fixFileSystemPath");
2699
2700 const char * path;
2701 if (ctx.m_currentSection->get("FileSystemPath", &path))
2702 DBUG_RETURN(true);
2703
2704 if (ctx.m_currentSection->get("DataDir", &path)) {
2705 require(ctx.m_currentSection->put("FileSystemPath", path));
2706 DBUG_RETURN(true);
2707 }
2708
2709 require(false);
2710 DBUG_RETURN(false);
2711 }
2712
2713 bool
fixBackupDataDir(InitConfigFileParser::Context & ctx,const char * data)2714 fixBackupDataDir(InitConfigFileParser::Context & ctx, const char * data){
2715
2716 const char * path;
2717 if (ctx.m_currentSection->get("BackupDataDir", &path))
2718 return true;
2719
2720 if (ctx.m_currentSection->get("FileSystemPath", &path)) {
2721 require(ctx.m_currentSection->put("BackupDataDir", path));
2722 return true;
2723 }
2724
2725 require(false);
2726 return false;
2727 }
2728
2729 /**
2730 * Connection rule: Check support of connection
2731 */
2732 bool
checkConnectionSupport(InitConfigFileParser::Context & ctx,const char * data)2733 checkConnectionSupport(InitConfigFileParser::Context & ctx, const char * data)
2734 {
2735 int error= 0;
2736 if (strcasecmp("TCP",ctx.fname) == 0)
2737 {
2738 // always enabled
2739 }
2740 else if (strcasecmp("SHM",ctx.fname) == 0)
2741 {
2742 #ifndef NDB_SHM_TRANSPORTER
2743 error= 1;
2744 #endif
2745 }
2746 else if (strcasecmp("SCI",ctx.fname) == 0)
2747 {
2748 #ifndef NDB_SCI_TRANSPORTER
2749 error= 1;
2750 #endif
2751 }
2752
2753 if (error)
2754 {
2755 ctx.reportError("Binary not compiled with this connection support, "
2756 "[%s] starting at line: %d",
2757 ctx.fname, ctx.m_sectionLineno);
2758 return false;
2759 }
2760 return true;
2761 }
2762
2763 /**
2764 * Connection rule: Update "NoOfConnections"
2765 */
2766 bool
transformConnection(InitConfigFileParser::Context & ctx,const char * data)2767 transformConnection(InitConfigFileParser::Context & ctx, const char * data)
2768 {
2769 Uint32 connections = 0;
2770 ctx.m_userProperties.get("NoOfConnections", &connections);
2771 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Connection_%d", connections);
2772 ctx.m_userProperties.put("NoOfConnections", ++connections, true);
2773
2774 ctx.m_currentSection->put("Type", ctx.fname);
2775 return true;
2776 }
2777
2778 /**
2779 * System rule: Just add it
2780 */
2781 bool
transformSystem(InitConfigFileParser::Context & ctx,const char * data)2782 transformSystem(InitConfigFileParser::Context & ctx, const char * data){
2783
2784 const char * name;
2785 if(!ctx.m_currentSection->get("Name", &name)){
2786 ctx.reportError("Mandatory parameter Name missing from section "
2787 "[%s] starting at line: %d",
2788 ctx.fname, ctx.m_sectionLineno);
2789 return false;
2790 }
2791
2792 ndbout << "transformSystem " << name << endl;
2793
2794 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name);
2795
2796 return true;
2797 }
2798
2799 /**
2800 * Computer rule: Update "NoOfComputers", add "Type"
2801 */
2802 bool
transformComputer(InitConfigFileParser::Context & ctx,const char * data)2803 transformComputer(InitConfigFileParser::Context & ctx, const char * data){
2804 const char * id;
2805 if(!ctx.m_currentSection->get("Id", &id)){
2806 ctx.reportError("Mandatory parameter Id missing from section "
2807 "[%s] starting at line: %d",
2808 ctx.fname, ctx.m_sectionLineno);
2809 return false;
2810 }
2811 BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Computer_%s", id);
2812
2813 Uint32 computers = 0;
2814 ctx.m_userProperties.get("NoOfComputers", &computers);
2815 ctx.m_userProperties.put("NoOfComputers", ++computers, true);
2816
2817 const char * hostname = 0;
2818 ctx.m_currentSection->get("HostName", &hostname);
2819 if(!hostname){
2820 return true;
2821 }
2822
2823 return checkLocalhostHostnameMix(ctx,0);
2824 }
2825
2826 /**
2827 * Apply default values
2828 */
2829 void
applyDefaultValues(InitConfigFileParser::Context & ctx,const Properties * defaults)2830 applyDefaultValues(InitConfigFileParser::Context & ctx,
2831 const Properties * defaults)
2832 {
2833 DBUG_ENTER("applyDefaultValues");
2834 if(defaults != NULL){
2835 Properties::Iterator it(defaults);
2836
2837 for(const char * name = it.first(); name != NULL; name = it.next()){
2838 (void) ctx.m_info->getStatus(ctx.m_currentInfo, name);
2839 if(!ctx.m_currentSection->contains(name)){
2840 switch (ctx.m_info->getType(ctx.m_currentInfo, name)){
2841 case ConfigInfo::CI_INT:
2842 case ConfigInfo::CI_BOOL:{
2843 Uint32 val = 0;
2844 ::require(defaults->get(name, &val));
2845 ctx.m_currentSection->put(name, val);
2846 DBUG_PRINT("info",("%s=%d #default",name,val));
2847 break;
2848 }
2849 case ConfigInfo::CI_INT64:{
2850 Uint64 val = 0;
2851 ::require(defaults->get(name, &val));
2852 ctx.m_currentSection->put64(name, val);
2853 DBUG_PRINT("info",("%s=%lld #default",name,val));
2854 break;
2855 }
2856 case ConfigInfo::CI_STRING:{
2857 const char * val;
2858 ::require(defaults->get(name, &val));
2859 ctx.m_currentSection->put(name, val);
2860 DBUG_PRINT("info",("%s=%s #default",name,val));
2861 break;
2862 }
2863 case ConfigInfo::CI_SECTION:
2864 break;
2865 }
2866 }
2867 #ifndef DBUG_OFF
2868 else
2869 {
2870 switch (ctx.m_info->getType(ctx.m_currentInfo, name)){
2871 case ConfigInfo::CI_INT:
2872 case ConfigInfo::CI_BOOL:{
2873 Uint32 val = 0;
2874 ::require(ctx.m_currentSection->get(name, &val));
2875 DBUG_PRINT("info",("%s=%d",name,val));
2876 break;
2877 }
2878 case ConfigInfo::CI_INT64:{
2879 Uint64 val = 0;
2880 ::require(ctx.m_currentSection->get(name, &val));
2881 DBUG_PRINT("info",("%s=%lld",name,val));
2882 break;
2883 }
2884 case ConfigInfo::CI_STRING:{
2885 const char * val;
2886 ::require(ctx.m_currentSection->get(name, &val));
2887 DBUG_PRINT("info",("%s=%s",name,val));
2888 break;
2889 }
2890 case ConfigInfo::CI_SECTION:
2891 break;
2892 }
2893 }
2894 #endif
2895 }
2896 }
2897 DBUG_VOID_RETURN;
2898 }
2899
2900 bool
applyDefaultValues(InitConfigFileParser::Context & ctx,const char * data)2901 applyDefaultValues(InitConfigFileParser::Context & ctx, const char * data){
2902
2903 if(strcmp(data, "user") == 0)
2904 applyDefaultValues(ctx, ctx.m_userDefaults);
2905 else if (strcmp(data, "system") == 0)
2906 applyDefaultValues(ctx, ctx.m_systemDefaults);
2907 else
2908 return false;
2909
2910 return true;
2911 }
2912
2913 /**
2914 * Check that a section contains all MANDATORY parameters
2915 */
2916 bool
checkMandatory(InitConfigFileParser::Context & ctx,const char * data)2917 checkMandatory(InitConfigFileParser::Context & ctx, const char * data){
2918
2919 Properties::Iterator it(ctx.m_currentInfo);
2920 for(const char * name = it.first(); name != NULL; name = it.next()){
2921 const Properties * info = NULL;
2922 ::require(ctx.m_currentInfo->get(name, &info));
2923 Uint32 val;
2924 if(info->get("Mandatory", &val)){
2925 const char * fname;
2926 ::require(info->get("Fname", &fname));
2927 if(!ctx.m_currentSection->contains(fname)){
2928 ctx.reportError("Mandatory parameter %s missing from section "
2929 "[%s] starting at line: %d",
2930 fname, ctx.fname, ctx.m_sectionLineno);
2931 return false;
2932 }
2933 }
2934 }
2935 return true;
2936 }
2937
2938 /**
2939 * Connection rule: Fix node id
2940 *
2941 * Transform a string "NodeidX" (e.g. "uppsala.32")
2942 * into a Uint32 "NodeIdX" (e.g. 32) and a string "SystemX" (e.g. "uppsala").
2943 */
fixNodeId(InitConfigFileParser::Context & ctx,const char * data)2944 static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
2945 {
2946 char buf[] = "NodeIdX"; buf[6] = data[sizeof("NodeI")];
2947 char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("NodeI")];
2948 const char* nodeId;
2949 if(!ctx.m_currentSection->get(buf, &nodeId))
2950 {
2951 ctx.reportError("Mandatory parameter %s missing from section"
2952 "[%s] starting at line: %d",
2953 buf, ctx.fname, ctx.m_sectionLineno);
2954 return false;
2955 }
2956
2957 char tmpLine[MAX_LINE_LENGTH];
2958 strncpy(tmpLine, nodeId, MAX_LINE_LENGTH);
2959 char* token1 = strtok(tmpLine, ".");
2960 char* token2 = strtok(NULL, ".");
2961 Uint32 id;
2962
2963 if(!token1)
2964 {
2965 ctx.reportError("Value for mandatory parameter %s missing from section "
2966 "[%s] starting at line: %d",
2967 buf, ctx.fname, ctx.m_sectionLineno);
2968 return false;
2969 }
2970 if (token2 == NULL) { // Only a number given
2971 errno = 0;
2972 char* p;
2973 id = strtol(token1, &p, 10);
2974 if (errno != 0 || id <= 0x0 || id > MAX_NODES)
2975 {
2976 ctx.reportError("Illegal value for mandatory parameter %s from section "
2977 "[%s] starting at line: %d",
2978 buf, ctx.fname, ctx.m_sectionLineno);
2979 return false;
2980 }
2981 require(ctx.m_currentSection->put(buf, id, true));
2982 } else { // A pair given (e.g. "uppsala.32")
2983 errno = 0;
2984 char* p;
2985 id = strtol(token2, &p, 10);
2986 if (errno != 0 || id <= 0x0 || id > MAX_NODES)
2987 {
2988 ctx.reportError("Illegal value for mandatory parameter %s from section "
2989 "[%s] starting at line: %d",
2990 buf, ctx.fname, ctx.m_sectionLineno);
2991 return false;
2992 }
2993 require(ctx.m_currentSection->put(buf, id, true));
2994 require(ctx.m_currentSection->put(sysbuf, token1));
2995 }
2996 return true;
2997 }
2998
2999 /**
3000 * Connection rule: Fix hostname
3001 *
3002 * Unless Hostname is not already specified, do steps:
3003 * -# Via Connection's NodeId lookup Node
3004 * -# Via Node's ExecuteOnComputer lookup Hostname
3005 * -# Add HostName to Connection
3006 */
3007 static bool
fixHostname(InitConfigFileParser::Context & ctx,const char * data)3008 fixHostname(InitConfigFileParser::Context & ctx, const char * data){
3009
3010 char buf[] = "NodeIdX"; buf[6] = data[sizeof("HostNam")];
3011 char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("HostNam")];
3012
3013 if(!ctx.m_currentSection->contains(data)){
3014 Uint32 id = 0;
3015 require(ctx.m_currentSection->get(buf, &id));
3016
3017 const Properties * node;
3018 if(!ctx.m_config->get("Node", id, &node))
3019 {
3020 ctx.reportError("Unknown node: \"%d\" specified in connection "
3021 "[%s] starting at line: %d",
3022 id, ctx.fname, ctx.m_sectionLineno);
3023 return false;
3024 }
3025
3026 const char * hostname;
3027 require(node->get("HostName", &hostname));
3028 require(ctx.m_currentSection->put(data, hostname));
3029 }
3030 return true;
3031 }
3032
3033 /**
3034 * Connection rule: Fix port number (using a port number adder)
3035 */
3036 static bool
fixPortNumber(InitConfigFileParser::Context & ctx,const char * data)3037 fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
3038
3039 DBUG_ENTER("fixPortNumber");
3040
3041 Uint32 id1, id2;
3042 const char *hostName1;
3043 const char *hostName2;
3044 require(ctx.m_currentSection->get("NodeId1", &id1));
3045 require(ctx.m_currentSection->get("NodeId2", &id2));
3046 require(ctx.m_currentSection->get("HostName1", &hostName1));
3047 require(ctx.m_currentSection->get("HostName2", &hostName2));
3048 DBUG_PRINT("info",("NodeId1=%d HostName1=\"%s\"",id1,hostName1));
3049 DBUG_PRINT("info",("NodeId2=%d HostName2=\"%s\"",id2,hostName2));
3050
3051 const Properties *node1, *node2;
3052 require(ctx.m_config->get("Node", id1, &node1));
3053 require(ctx.m_config->get("Node", id2, &node2));
3054
3055 const char *type1, *type2;
3056 require(node1->get("Type", &type1));
3057 require(node2->get("Type", &type2));
3058
3059 /* add NodeIdServer info */
3060 {
3061 Uint32 nodeIdServer = id1 < id2 ? id1 : id2;
3062 if(strcmp(type1, API_TOKEN) == 0 || strcmp(type2, MGM_TOKEN) == 0)
3063 nodeIdServer = id2;
3064 else if(strcmp(type2, API_TOKEN) == 0 || strcmp(type1, MGM_TOKEN) == 0)
3065 nodeIdServer = id1;
3066 ctx.m_currentSection->put("NodeIdServer", nodeIdServer);
3067
3068 if (id2 == nodeIdServer) {
3069 {
3070 const char *tmp= hostName1;
3071 hostName1= hostName2;
3072 hostName2= tmp;
3073 }
3074 {
3075 Uint32 tmp= id1;
3076 id1= id2;
3077 id2= tmp;
3078 }
3079 {
3080 const Properties *tmp= node1;
3081 node1= node2;
3082 node2= tmp;
3083 }
3084 {
3085 const char *tmp= type1;
3086 type1= type2;
3087 type2= tmp;
3088 }
3089 }
3090 }
3091
3092 BaseString hostname(hostName1);
3093
3094 if (hostname.c_str()[0] == 0) {
3095 ctx.reportError("Hostname required on nodeid %d since it will "
3096 "act as server.", id1);
3097 DBUG_RETURN(false);
3098 }
3099
3100 Uint32 port= 0;
3101 if(strcmp(type1, MGM_TOKEN)==0)
3102 node1->get("PortNumber",&port);
3103 else if(strcmp(type2, MGM_TOKEN)==0)
3104 node2->get("PortNumber",&port);
3105
3106 if (!port &&
3107 !node1->get("ServerPort", &port) &&
3108 !ctx.m_userProperties.get("ServerPort_", id1, &port))
3109 {
3110 Uint32 base= 0;
3111 /*
3112 * If the connection doesn't involve an mgm server,
3113 * and a default port number has been set, behave the old
3114 * way of allocating port numbers for transporters.
3115 */
3116 if(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base))
3117 {
3118 Uint32 adder= 0;
3119 {
3120 BaseString server_port_adder(hostname);
3121 server_port_adder.append("_ServerPortAdder");
3122 ctx.m_userProperties.get(server_port_adder.c_str(), &adder);
3123 ctx.m_userProperties.put(server_port_adder.c_str(), adder+1, true);
3124 }
3125
3126 if (!ctx.m_userProperties.get("ServerPortBase", &base)){
3127 if(!(ctx.m_userDefaults &&
3128 ctx.m_userDefaults->get("PortNumber", &base)) &&
3129 !ctx.m_systemDefaults->get("PortNumber", &base)) {
3130 base= strtoll(NDB_TCP_BASE_PORT,0,0);
3131 }
3132 ctx.m_userProperties.put("ServerPortBase", base);
3133 }
3134
3135 port= base + adder;
3136 ctx.m_userProperties.put("ServerPort_", id1, port);
3137 }
3138 }
3139
3140 if(ctx.m_currentSection->contains("PortNumber")) {
3141 ndbout << "PortNumber should no longer be specificied "
3142 << "per connection, please remove from config. "
3143 << "Will be changed to " << port << endl;
3144 ctx.m_currentSection->put("PortNumber", port, true);
3145 }
3146 else
3147 {
3148 ctx.m_currentSection->put("PortNumber", port);
3149 }
3150
3151 DBUG_PRINT("info", ("connection %d-%d port %d host %s",
3152 id1, id2, port, hostname.c_str()));
3153
3154 DBUG_RETURN(true);
3155 }
3156
3157 static bool
fixShmUniqueId(InitConfigFileParser::Context & ctx,const char * data)3158 fixShmUniqueId(InitConfigFileParser::Context & ctx, const char * data)
3159 {
3160 DBUG_ENTER("fixShmUniqueId");
3161 Uint32 nodes= 0;
3162 ctx.m_userProperties.get(ctx.fname, &nodes);
3163 if (nodes == 1) // first management server
3164 {
3165 Uint32 portno= atoi(NDB_PORT);
3166 ctx.m_currentSection->get("PortNumber", &portno);
3167 ctx.m_userProperties.put("ShmUniqueId", portno);
3168 }
3169 DBUG_RETURN(true);
3170 }
3171
3172 static
3173 bool
fixShmKey(InitConfigFileParser::Context & ctx,const char *)3174 fixShmKey(InitConfigFileParser::Context & ctx, const char *)
3175 {
3176 DBUG_ENTER("fixShmKey");
3177 {
3178 static int last_signum= -1;
3179 Uint32 signum;
3180 if(!ctx.m_currentSection->get("Signum", &signum))
3181 {
3182 signum= OPT_NDB_SHM_SIGNUM_DEFAULT;
3183 if (signum <= 0)
3184 {
3185 ctx.reportError("Unable to set default parameter for [SHM]Signum"
3186 " please specify [SHM DEFAULT]Signum");
3187 return false;
3188 }
3189 ctx.m_currentSection->put("Signum", signum);
3190 DBUG_PRINT("info",("Added Signum=%u", signum));
3191 }
3192 if ( last_signum != (int)signum && last_signum >= 0 )
3193 {
3194 ctx.reportError("All shared memory transporters must have same [SHM]Signum defined."
3195 " Use [SHM DEFAULT]Signum");
3196 return false;
3197 }
3198 last_signum= (int)signum;
3199 }
3200 {
3201 Uint32 id1= 0, id2= 0, key= 0;
3202 require(ctx.m_currentSection->get("NodeId1", &id1));
3203 require(ctx.m_currentSection->get("NodeId2", &id2));
3204 if(!ctx.m_currentSection->get("ShmKey", &key))
3205 {
3206 require(ctx.m_userProperties.get("ShmUniqueId", &key));
3207 key= key << 16 | (id1 > id2 ? id1 << 8 | id2 : id2 << 8 | id1);
3208 ctx.m_currentSection->put("ShmKey", key);
3209 DBUG_PRINT("info",("Added ShmKey=0x%x", key));
3210 }
3211 }
3212 DBUG_RETURN(true);
3213 }
3214
3215 /**
3216 * DB Node rule: Check various constraints
3217 */
3218 static bool
checkDbConstraints(InitConfigFileParser::Context & ctx,const char *)3219 checkDbConstraints(InitConfigFileParser::Context & ctx, const char *){
3220
3221 Uint32 t1 = 0, t2 = 0;
3222 ctx.m_currentSection->get("MaxNoOfConcurrentOperations", &t1);
3223 ctx.m_currentSection->get("MaxNoOfConcurrentTransactions", &t2);
3224
3225 if (t1 < t2) {
3226 ctx.reportError("MaxNoOfConcurrentOperations must be greater than "
3227 "MaxNoOfConcurrentTransactions - [%s] starting at line: %d",
3228 ctx.fname, ctx.m_sectionLineno);
3229 return false;
3230 }
3231
3232 Uint32 replicas = 0, otherReplicas;
3233 ctx.m_currentSection->get("NoOfReplicas", &replicas);
3234 if(ctx.m_userProperties.get("NoOfReplicas", &otherReplicas)){
3235 if(replicas != otherReplicas){
3236 ctx.reportError("NoOfReplicas defined differently on different nodes"
3237 " - [%s] starting at line: %d",
3238 ctx.fname, ctx.m_sectionLineno);
3239 return false;
3240 }
3241 } else {
3242 ctx.m_userProperties.put("NoOfReplicas", replicas);
3243 }
3244
3245 /**
3246 * In kernel, will calculate the MaxNoOfMeataTables use the following sum:
3247 * Uint32 noOfMetaTables = noOfTables + noOfOrderedIndexes +
3248 * noOfUniqueHashIndexes + 2
3249 * 2 is the number of the SysTables.
3250 * So must check that the sum does't exceed the max value of Uint32.
3251 */
3252 Uint32 noOfTables = 0,
3253 noOfOrderedIndexes = 0,
3254 noOfUniqueHashIndexes = 0;
3255 ctx.m_currentSection->get("MaxNoOfTables", &noOfTables);
3256 ctx.m_currentSection->get("MaxNoOfOrderedIndexes", &noOfOrderedIndexes);
3257 ctx.m_currentSection->get("MaxNoOfUniqueHashIndexes", &noOfUniqueHashIndexes);
3258
3259 Uint64 sum= (Uint64)noOfTables + noOfOrderedIndexes + noOfUniqueHashIndexes;
3260
3261 if (sum > ((Uint32)~0 - 2)) {
3262 ctx.reportError("The sum of MaxNoOfTables, MaxNoOfOrderedIndexes and"
3263 " MaxNoOfUniqueHashIndexes must not exceed %u - [%s]"
3264 " starting at line: %d",
3265 ((Uint32)~0 - 2), ctx.fname, ctx.m_sectionLineno);
3266 return false;
3267 }
3268
3269 return true;
3270 }
3271
3272 /**
3273 * Connection rule: Check varius constraints
3274 */
3275 static bool
checkConnectionConstraints(InitConfigFileParser::Context & ctx,const char *)3276 checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
3277
3278 Uint32 id1 = 0, id2 = 0;
3279 ctx.m_currentSection->get("NodeId1", &id1);
3280 ctx.m_currentSection->get("NodeId2", &id2);
3281
3282 if(id1 == id2){
3283 ctx.reportError("Illegal connection from node to itself"
3284 " - [%s] starting at line: %d",
3285 ctx.fname, ctx.m_sectionLineno);
3286 return false;
3287 }
3288
3289 const Properties * node1;
3290 if(!ctx.m_config->get("Node", id1, &node1)){
3291 ctx.reportError("Connection refering to undefined node: %d"
3292 " - [%s] starting at line: %d",
3293 id1, ctx.fname, ctx.m_sectionLineno);
3294 return false;
3295 }
3296
3297 const Properties * node2;
3298 if(!ctx.m_config->get("Node", id2, &node2)){
3299 ctx.reportError("Connection refering to undefined node: %d"
3300 " - [%s] starting at line: %d",
3301 id2, ctx.fname, ctx.m_sectionLineno);
3302 return false;
3303 }
3304
3305 const char * type1;
3306 const char * type2;
3307 require(node1->get("Type", &type1));
3308 require(node2->get("Type", &type2));
3309
3310 /**
3311 * Report error if the following are true
3312 * -# None of the nodes is of type DB
3313 * -# Not both of them are MGMs
3314 */
3315 if((strcmp(type1, DB_TOKEN) != 0 && strcmp(type2, DB_TOKEN) != 0) &&
3316 !(strcmp(type1, MGM_TOKEN) == 0 && strcmp(type2, MGM_TOKEN) == 0))
3317 {
3318 ctx.reportError("Invalid connection between node %d (%s) and node %d (%s)"
3319 " - [%s] starting at line: %d",
3320 id1, type1, id2, type2,
3321 ctx.fname, ctx.m_sectionLineno);
3322 return false;
3323 }
3324
3325 return true;
3326 }
3327
3328 static bool
checkTCPConstraints(InitConfigFileParser::Context & ctx,const char * data)3329 checkTCPConstraints(InitConfigFileParser::Context & ctx, const char * data){
3330
3331 const char * host;
3332 struct in_addr addr;
3333 if(ctx.m_currentSection->get(data, &host) && strlen(host) &&
3334 Ndb_getInAddr(&addr, host)){
3335 ctx.reportError("Unable to lookup/illegal hostname %s"
3336 " - [%s] starting at line: %d",
3337 host, ctx.fname, ctx.m_sectionLineno);
3338 return false;
3339 }
3340 return true;
3341 }
3342
3343 static
3344 bool
transform(InitConfigFileParser::Context & ctx,Properties & dst,const char * oldName,const char * newName,double add,double mul)3345 transform(InitConfigFileParser::Context & ctx,
3346 Properties & dst,
3347 const char * oldName,
3348 const char * newName,
3349 double add, double mul){
3350
3351 if(ctx.m_currentSection->contains(newName)){
3352 ctx.reportError("Both %s and %s specified"
3353 " - [%s] starting at line: %d",
3354 oldName, newName,
3355 ctx.fname, ctx.m_sectionLineno);
3356 return false;
3357 }
3358
3359 PropertiesType oldType;
3360 require(ctx.m_currentSection->getTypeOf(oldName, &oldType));
3361 ConfigInfo::Type newType = ctx.m_info->getType(ctx.m_currentInfo, newName);
3362
3363 if(!((oldType == PropertiesType_Uint32 || oldType == PropertiesType_Uint64)
3364 && (newType == ConfigInfo::CI_INT || newType == ConfigInfo::CI_INT64 || newType == ConfigInfo::CI_BOOL))){
3365 ndbout << "oldType: " << (int)oldType << ", newType: " << (int)newType << endl;
3366 ctx.reportError("Unable to handle type conversion w.r.t deprication %s %s"
3367 "- [%s] starting at line: %d",
3368 oldName, newName,
3369 ctx.fname, ctx.m_sectionLineno);
3370 return false;
3371 }
3372 Uint64 oldVal;
3373 require(ctx.m_currentSection->get(oldName, &oldVal));
3374
3375 Uint64 newVal = (Uint64)((Int64)oldVal * mul + add);
3376 if(!ctx.m_info->verify(ctx.m_currentInfo, newName, newVal)){
3377 ctx.reportError("Unable to handle deprication, new value not within bounds"
3378 "%s %s - [%s] starting at line: %d",
3379 oldName, newName,
3380 ctx.fname, ctx.m_sectionLineno);
3381 return false;
3382 }
3383
3384 if(newType == ConfigInfo::CI_INT || newType == ConfigInfo::CI_BOOL){
3385 require(dst.put(newName, (Uint32)newVal));
3386 } else if(newType == ConfigInfo::CI_INT64) {
3387 require(dst.put64(newName, newVal));
3388 }
3389 return true;
3390 }
3391
3392 static bool
fixDepricated(InitConfigFileParser::Context & ctx,const char * data)3393 fixDepricated(InitConfigFileParser::Context & ctx, const char * data){
3394 const char * name;
3395 /**
3396 * Transform old values to new values
3397 * Transform new values to old values (backward compatible)
3398 */
3399 Properties tmp(true);
3400 Properties::Iterator it(ctx.m_currentSection);
3401 for (name = it.first(); name != NULL; name = it.next()) {
3402 const DepricationTransform * p = &f_deprication[0];
3403 while(p->m_section != 0){
3404 if(strcmp(p->m_section, ctx.fname) == 0){
3405 double mul = p->m_mul;
3406 double add = p->m_add;
3407 if(strcasecmp(name, p->m_oldName) == 0){
3408 if(!transform(ctx, tmp, name, p->m_newName, add, mul)){
3409 return false;
3410 }
3411 } else if(strcasecmp(name, p->m_newName) == 0) {
3412 if(!transform(ctx, tmp, name, p->m_oldName, -add/mul,1.0/mul)){
3413 return false;
3414 }
3415 }
3416 }
3417 p++;
3418 }
3419 }
3420
3421 Properties::Iterator it2(&tmp);
3422 for (name = it2.first(); name != NULL; name = it2.next()) {
3423 PropertiesType type;
3424 require(tmp.getTypeOf(name, &type));
3425 switch(type){
3426 case PropertiesType_Uint32:{
3427 Uint32 val;
3428 require(tmp.get(name, &val));
3429 ::require(ctx.m_currentSection->put(name, val));
3430 break;
3431 }
3432 case PropertiesType_char:{
3433 const char * val;
3434 require(tmp.get(name, &val));
3435 ::require(ctx.m_currentSection->put(name, val));
3436 break;
3437 }
3438 case PropertiesType_Uint64:{
3439 Uint64 val;
3440 require(tmp.get(name, &val));
3441 ::require(ctx.m_currentSection->put64(name, val));
3442 break;
3443 }
3444 case PropertiesType_Properties:
3445 default:
3446 ::require(false);
3447 }
3448 }
3449 return true;
3450 }
3451
3452 extern int g_print_full_config;
3453
3454 static bool
saveInConfigValues(InitConfigFileParser::Context & ctx,const char * data)3455 saveInConfigValues(InitConfigFileParser::Context & ctx, const char * data){
3456 const Properties * sec;
3457 if(!ctx.m_currentInfo->get(ctx.fname, &sec)){
3458 require(false);
3459 return false;
3460 }
3461
3462 do {
3463 const char *secName;
3464 Uint32 id, status, typeVal;
3465 require(sec->get("Fname", &secName));
3466 require(sec->get("Id", &id));
3467 require(sec->get("Status", &status));
3468 require(sec->get("SectionType", &typeVal));
3469
3470 if(id == KEY_INTERNAL || status == ConfigInfo::CI_INTERNAL){
3471 ndbout_c("skipping section %s", ctx.fname);
3472 break;
3473 }
3474
3475 if (g_print_full_config)
3476 {
3477 const char *alias= ConfigInfo::nameToAlias(ctx.fname);
3478 printf("[%s]\n", alias ? alias : ctx.fname);
3479 }
3480
3481 Uint32 no = 0;
3482 ctx.m_userProperties.get("$Section", id, &no);
3483 ctx.m_userProperties.put("$Section", id, no+1, true);
3484
3485 ctx.m_configValues.openSection(id, no);
3486 ctx.m_configValues.put(CFG_TYPE_OF_SECTION, typeVal);
3487
3488 Properties::Iterator it(ctx.m_currentSection);
3489 for (const char* n = it.first(); n != NULL; n = it.next()) {
3490 const Properties * info;
3491 if(!ctx.m_currentInfo->get(n, &info))
3492 continue;
3493
3494 id = 0;
3495 info->get("Id", &id);
3496
3497 if(id == KEY_INTERNAL)
3498 continue;
3499
3500 bool ok = true;
3501 PropertiesType type;
3502 require(ctx.m_currentSection->getTypeOf(n, &type));
3503 switch(type){
3504 case PropertiesType_Uint32:{
3505 Uint32 val;
3506 require(ctx.m_currentSection->get(n, &val));
3507 ok = ctx.m_configValues.put(id, val);
3508 if (g_print_full_config)
3509 printf("%s=%u\n", n, val);
3510 break;
3511 }
3512 case PropertiesType_Uint64:{
3513 Uint64 val;
3514 require(ctx.m_currentSection->get(n, &val));
3515 ok = ctx.m_configValues.put64(id, val);
3516 if (g_print_full_config)
3517 printf("%s=%llu\n", n, val);
3518 break;
3519 }
3520 case PropertiesType_char:{
3521 const char * val;
3522 require(ctx.m_currentSection->get(n, &val));
3523 ok = ctx.m_configValues.put(id, val);
3524 if (g_print_full_config)
3525 printf("%s=%s\n", n, val);
3526 break;
3527 }
3528 default:
3529 require(false);
3530 }
3531 require(ok);
3532 }
3533 ctx.m_configValues.closeSection();
3534 } while(0);
3535 return true;
3536 }
3537
3538 static bool
sanity_checks(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)3539 sanity_checks(Vector<ConfigInfo::ConfigRuleSection>§ions,
3540 struct InitConfigFileParser::Context &ctx,
3541 const char * rule_data)
3542 {
3543 Uint32 db_nodes = 0;
3544 Uint32 mgm_nodes = 0;
3545 Uint32 api_nodes = 0;
3546 if (!ctx.m_userProperties.get("DB", &db_nodes)) {
3547 ctx.reportError("At least one database node (ndbd) should be defined in config file");
3548 return false;
3549 }
3550 if (!ctx.m_userProperties.get("MGM", &mgm_nodes)) {
3551 ctx.reportError("At least one management server node (ndb_mgmd) should be defined in config file");
3552 return false;
3553 }
3554 if (!ctx.m_userProperties.get("API", &api_nodes)) {
3555 ctx.reportError("At least one application node (for the mysqld) should be defined in config file");
3556 return false;
3557 }
3558 return true;
3559 }
3560
3561 static void
add_a_connection(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,Uint32 nodeId1,Uint32 nodeId2,bool use_shm)3562 add_a_connection(Vector<ConfigInfo::ConfigRuleSection>§ions,
3563 struct InitConfigFileParser::Context &ctx,
3564 Uint32 nodeId1, Uint32 nodeId2, bool use_shm)
3565 {
3566 ConfigInfo::ConfigRuleSection s;
3567 const char *hostname1= 0, *hostname2= 0;
3568 const Properties *tmp;
3569
3570 require(ctx.m_config->get("Node", nodeId1, &tmp));
3571 tmp->get("HostName", &hostname1);
3572
3573 require(ctx.m_config->get("Node", nodeId2, &tmp));
3574 tmp->get("HostName", &hostname2);
3575
3576 char buf[16];
3577 s.m_sectionData= new Properties(true);
3578 BaseString::snprintf(buf, sizeof(buf), "%u", nodeId1);
3579 s.m_sectionData->put("NodeId1", buf);
3580 BaseString::snprintf(buf, sizeof(buf), "%u", nodeId2);
3581 s.m_sectionData->put("NodeId2", buf);
3582
3583 if (use_shm &&
3584 hostname1 && hostname1[0] &&
3585 hostname2 && hostname2[0] &&
3586 strcmp(hostname1,hostname2) == 0)
3587 {
3588 s.m_sectionType= BaseString("SHM");
3589 DBUG_PRINT("info",("adding SHM connection %d %d",nodeId1,nodeId2));
3590 }
3591 else
3592 {
3593 s.m_sectionType= BaseString("TCP");
3594 DBUG_PRINT("info",("adding TCP connection %d %d",nodeId1,nodeId2));
3595 }
3596
3597 sections.push_back(s);
3598 }
3599
3600 static bool
add_node_connections(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)3601 add_node_connections(Vector<ConfigInfo::ConfigRuleSection>§ions,
3602 struct InitConfigFileParser::Context &ctx,
3603 const char * rule_data)
3604 {
3605 DBUG_ENTER("add_node_connections");
3606 Uint32 i;
3607 Properties * props= ctx.m_config;
3608 Properties p_connections(true);
3609 Properties p_connections2(true);
3610
3611 for (i = 0;; i++){
3612 const Properties * tmp;
3613 Uint32 nodeId1, nodeId2;
3614
3615 if(!props->get("Connection", i, &tmp)) break;
3616
3617 if(!tmp->get("NodeId1", &nodeId1)) continue;
3618 p_connections.put("", nodeId1, nodeId1);
3619 if(!tmp->get("NodeId2", &nodeId2)) continue;
3620 p_connections.put("", nodeId2, nodeId2);
3621
3622 p_connections2.put("", nodeId1 + nodeId2<<16, nodeId1);
3623 p_connections2.put("", nodeId2 + nodeId1<<16, nodeId2);
3624 }
3625
3626 Uint32 nNodes;
3627 ctx.m_userProperties.get("NoOfNodes", &nNodes);
3628
3629 Properties p_db_nodes(true);
3630 Properties p_api_nodes(true);
3631 Properties p_mgm_nodes(true);
3632
3633 Uint32 i_db= 0, i_api= 0, i_mgm= 0, n;
3634 for (i= 0, n= 0; n < nNodes; i++){
3635 const Properties * tmp;
3636 if(!props->get("Node", i, &tmp)) continue;
3637 n++;
3638
3639 const char * type;
3640 if(!tmp->get("Type", &type)) continue;
3641
3642 if (strcmp(type,DB_TOKEN) == 0)
3643 p_db_nodes.put("", i_db++, i);
3644 else if (strcmp(type,API_TOKEN) == 0)
3645 p_api_nodes.put("", i_api++, i);
3646 else if (strcmp(type,MGM_TOKEN) == 0)
3647 p_mgm_nodes.put("", i_mgm++, i);
3648 }
3649
3650 Uint32 nodeId1, nodeId2, dummy;
3651
3652 for (i= 0; p_db_nodes.get("", i, &nodeId1); i++){
3653 for (Uint32 j= i+1;; j++){
3654 if(!p_db_nodes.get("", j, &nodeId2)) break;
3655 if(!p_connections2.get("", nodeId1+nodeId2<<16, &dummy)) {
3656 add_a_connection(sections,ctx,nodeId1,nodeId2,opt_ndb_shm);
3657 }
3658 }
3659 }
3660
3661 for (i= 0; p_api_nodes.get("", i, &nodeId1); i++){
3662 if(!p_connections.get("", nodeId1, &dummy)) {
3663 for (Uint32 j= 0;; j++){
3664 if(!p_db_nodes.get("", j, &nodeId2)) break;
3665 add_a_connection(sections,ctx,nodeId1,nodeId2,opt_ndb_shm);
3666 }
3667 }
3668 }
3669
3670 for (i= 0; p_mgm_nodes.get("", i, &nodeId1); i++){
3671 if(!p_connections.get("", nodeId1, &dummy)) {
3672 for (Uint32 j= 0;; j++){
3673 if(!p_db_nodes.get("", j, &nodeId2)) break;
3674 add_a_connection(sections,ctx,nodeId1,nodeId2,0);
3675 }
3676 }
3677 }
3678
3679 DBUG_RETURN(true);
3680 }
3681
set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)3682 static bool set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection>§ions,
3683 struct InitConfigFileParser::Context &ctx,
3684 const char * rule_data)
3685 {
3686 DBUG_ENTER("set_connection_priorities");
3687 DBUG_RETURN(true);
3688 }
3689
3690 static bool
check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection> & sections,struct InitConfigFileParser::Context & ctx,const char * rule_data)3691 check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>§ions,
3692 struct InitConfigFileParser::Context &ctx,
3693 const char * rule_data)
3694 {
3695 Uint32 db_nodes= 0;
3696 Uint32 replicas= 0;
3697 Uint32 db_host_count= 0;
3698 bool with_arbitration_rank= false;
3699 ctx.m_userProperties.get(DB_TOKEN, &db_nodes);
3700 ctx.m_userProperties.get("NoOfReplicas", &replicas);
3701 if((db_nodes % replicas) != 0){
3702 ctx.reportError("Invalid no of db nodes wrt no of replicas.\n"
3703 "No of nodes must be dividable with no or replicas");
3704 return false;
3705 }
3706 // check that node groups and arbitrators are ok
3707 // just issue warning if not
3708 if(replicas > 1){
3709 Properties * props= ctx.m_config;
3710 Properties p_db_hosts(true); // store hosts which db nodes run on
3711 Properties p_arbitrators(true); // store hosts which arbitrators run on
3712 // arbitrator should not run together with db node on same host
3713 Uint32 i, n, group= 0, i_group= 0;
3714 Uint32 n_nodes;
3715 BaseString node_group_warning, arbitration_warning;
3716 const char *arbit_warn_fmt=
3717 "\n arbitrator with id %d and db node with id %d on same host %s";
3718 const char *arbit_warn_fmt2=
3719 "\n arbitrator with id %d has no hostname specified";
3720
3721 ctx.m_userProperties.get("NoOfNodes", &n_nodes);
3722 for (i= 0, n= 0; n < n_nodes; i++){
3723 const Properties * tmp;
3724 if(!props->get("Node", i, &tmp)) continue;
3725 n++;
3726
3727 const char * type;
3728 if(!tmp->get("Type", &type)) continue;
3729
3730 const char* host= 0;
3731 tmp->get("HostName", &host);
3732
3733 if (strcmp(type,DB_TOKEN) == 0)
3734 {
3735 {
3736 Uint32 ii;
3737 if (!p_db_hosts.get(host,&ii))
3738 db_host_count++;
3739 p_db_hosts.put(host,i);
3740 if (p_arbitrators.get(host,&ii))
3741 {
3742 arbitration_warning.appfmt(arbit_warn_fmt, ii, i, host);
3743 p_arbitrators.remove(host); // only one warning per db node
3744 }
3745 }
3746 {
3747 unsigned j;
3748 BaseString str, str2;
3749 str.assfmt("#group%d_",group);
3750 p_db_hosts.put(str.c_str(),i_group,host);
3751 str2.assfmt("##group%d_",group);
3752 p_db_hosts.put(str2.c_str(),i_group,i);
3753 for (j= 0; j < i_group; j++)
3754 {
3755 const char *other_host;
3756 p_db_hosts.get(str.c_str(),j,&other_host);
3757 if (strcmp(host,other_host) == 0) {
3758 unsigned int other_i, c= 0;
3759 p_db_hosts.get(str2.c_str(),j,&other_i);
3760 p_db_hosts.get(str.c_str(),&c);
3761 if (c == 0) // first warning in this node group
3762 node_group_warning.appfmt(" Node group %d", group);
3763 c|= 1 << j;
3764 p_db_hosts.put(str.c_str(),c);
3765 node_group_warning.appfmt(",\n db node with id %d and id %d "
3766 "on same host %s", other_i, i, host);
3767 }
3768 }
3769 i_group++;
3770 DBUG_ASSERT(i_group <= replicas);
3771 if (i_group == replicas)
3772 {
3773 unsigned c= 0;
3774 p_db_hosts.get(str.c_str(),&c);
3775 if (c+1 == (1u << (replicas-1))) // all nodes on same machine
3776 node_group_warning.append(".\n Host failure will "
3777 "cause complete cluster shutdown.");
3778 else if (c > 0)
3779 node_group_warning.append(".\n Host failure may "
3780 "cause complete cluster shutdown.");
3781 group++;
3782 i_group= 0;
3783 }
3784 }
3785 }
3786 else if (strcmp(type,API_TOKEN) == 0 ||
3787 strcmp(type,MGM_TOKEN) == 0)
3788 {
3789 Uint32 rank;
3790 if(tmp->get("ArbitrationRank", &rank) && rank > 0)
3791 {
3792 with_arbitration_rank = true; //check whether MGM or API node configured with rank >0
3793 if(host && host[0] != 0)
3794 {
3795 Uint32 ii;
3796 p_arbitrators.put(host,i);
3797 if (p_db_hosts.get(host,&ii))
3798 {
3799 arbitration_warning.appfmt(arbit_warn_fmt, i, ii, host);
3800 }
3801 }
3802 else
3803 {
3804 arbitration_warning.appfmt(arbit_warn_fmt2, i);
3805 }
3806 }
3807 }
3808 }
3809 if (db_host_count > 1 && node_group_warning.length() > 0)
3810 ctx.reportWarning("Cluster configuration warning:\n%s",node_group_warning.c_str());
3811 if (!with_arbitration_rank)
3812 {
3813 ctx.reportWarning("Cluster configuration warning:"
3814 "\n Neither %s nor %s nodes are configured with arbitrator,"
3815 "\n may cause complete cluster shutdown in case of host failure.",
3816 MGM_TOKEN, API_TOKEN);
3817 }
3818 if (db_host_count > 1 && arbitration_warning.length() > 0)
3819 ctx.reportWarning("Cluster configuration warning:%s%s",arbitration_warning.c_str(),
3820 "\n Running arbitrator on the same host as a database node may"
3821 "\n cause complete cluster shutdown in case of host failure.");
3822 }
3823 return true;
3824 }
3825
3826 template class Vector<ConfigInfo::ConfigRuleSection>;
3827 #endif /* NDB_MGMAPI */
3828