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