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>&sections,
192 			  struct InitConfigFileParser::Context &ctx,
193 			  const char * rule_data);
194 static bool add_node_connections(Vector<ConfigInfo::ConfigRuleSection>&sections,
195 				 struct InitConfigFileParser::Context &ctx,
196 				 const char * rule_data);
197 static bool set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection>&sections,
198 				 struct InitConfigFileParser::Context &ctx,
199 				 const char * rule_data);
200 static bool check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>&sections,
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, &section)) {
2243       Properties newsection(true);
2244       m_info.put(param._section, &newsection);
2245 
2246       // Get copy of section
2247       m_info.getCopy(param._section, &section);
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>&sections,
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>&sections,
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>&sections,
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>&sections,
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>&sections,
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