1 /* Copyright (c) 2003-2007 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include <ndb_global.h>
18 #include <ndb_opt_defaults.h>
21 #include "ConfigInfo.hpp"
22 #include <mgmapi_config_parameters.h>
23 #include <ndb_limits.h>
24 #include "InitConfigFileParser.hpp"
27 extern my_bool opt_ndb_shm
;
28 extern my_bool opt_core
;
31 #include "ConfigInfo.hpp"
32 #include <mgmapi_config_parameters.h>
33 #endif /* NDB_MGMAPI */
35 #define MAX_LINE_LENGTH 255
36 #define KEY_INTERNAL 0
37 #define MAX_INT_RNIL 0xfffffeff
38 #define MAX_PORT_NO 65535
40 #define _STR_VALUE(x) #x
41 #define STR_VALUE(x) _STR_VALUE(x)
43 /****************************************************************************
45 ****************************************************************************/
47 #define DB_TOKEN_PRINT "ndbd(DB)"
48 #define MGM_TOKEN_PRINT "ndb_mgmd(MGM)"
49 #define API_TOKEN_PRINT "mysqld(API)"
52 #define MGM_TOKEN "MGM"
53 #define API_TOKEN "API"
56 const ConfigInfo::AliasPair
57 ConfigInfo::m_sectionNameAliases
[]={
58 {API_TOKEN
, "MYSQLD"},
60 {MGM_TOKEN
, "NDB_MGMD"},
65 ConfigInfo::m_sectionNames
[]={
77 const int ConfigInfo::m_noOfSectionNames
=
78 sizeof(m_sectionNames
)/sizeof(char*);
81 /****************************************************************************
82 * Section Rules declarations
83 ****************************************************************************/
84 static bool transformComputer(InitConfigFileParser::Context
& ctx
, const char *);
85 static bool transformSystem(InitConfigFileParser::Context
& ctx
, const char *);
86 static bool transformNode(InitConfigFileParser::Context
& ctx
, const char *);
87 static bool checkConnectionSupport(InitConfigFileParser::Context
& ctx
, const char *);
88 static bool transformConnection(InitConfigFileParser::Context
& ctx
, const char *);
89 static bool applyDefaultValues(InitConfigFileParser::Context
& ctx
, const char *);
90 static bool checkMandatory(InitConfigFileParser::Context
& ctx
, const char *);
91 static bool fixPortNumber(InitConfigFileParser::Context
& ctx
, const char *);
92 static bool fixShmKey(InitConfigFileParser::Context
& ctx
, const char *);
93 static bool checkDbConstraints(InitConfigFileParser::Context
& ctx
, const char *);
94 static bool checkConnectionConstraints(InitConfigFileParser::Context
&, const char *);
95 static bool checkTCPConstraints(InitConfigFileParser::Context
&, const char *);
96 static bool fixNodeHostname(InitConfigFileParser::Context
& ctx
, const char * data
);
97 static bool fixHostname(InitConfigFileParser::Context
& ctx
, const char * data
);
98 static bool fixNodeId(InitConfigFileParser::Context
& ctx
, const char * data
);
99 static bool fixDepricated(InitConfigFileParser::Context
& ctx
, const char *);
100 static bool saveInConfigValues(InitConfigFileParser::Context
& ctx
, const char *);
101 static bool fixFileSystemPath(InitConfigFileParser::Context
& ctx
, const char * data
);
102 static bool fixBackupDataDir(InitConfigFileParser::Context
& ctx
, const char * data
);
103 static bool fixShmUniqueId(InitConfigFileParser::Context
& ctx
, const char * data
);
104 static bool checkLocalhostHostnameMix(InitConfigFileParser::Context
& ctx
, const char * data
);
106 const ConfigInfo::SectionRule
107 ConfigInfo::m_SectionRules
[] = {
108 { "SYSTEM", transformSystem
, 0 },
109 { "COMPUTER", transformComputer
, 0 },
111 { DB_TOKEN
, transformNode
, 0 },
112 { API_TOKEN
, transformNode
, 0 },
113 { MGM_TOKEN
, transformNode
, 0 },
115 { MGM_TOKEN
, fixShmUniqueId
, 0 },
117 { "TCP", checkConnectionSupport
, 0 },
118 { "SHM", checkConnectionSupport
, 0 },
119 { "SCI", checkConnectionSupport
, 0 },
121 { "TCP", transformConnection
, 0 },
122 { "SHM", transformConnection
, 0 },
123 { "SCI", transformConnection
, 0 },
125 { DB_TOKEN
, fixNodeHostname
, 0 },
126 { API_TOKEN
, fixNodeHostname
, 0 },
127 { MGM_TOKEN
, fixNodeHostname
, 0 },
129 { "TCP", fixNodeId
, "NodeId1" },
130 { "TCP", fixNodeId
, "NodeId2" },
131 { "SHM", fixNodeId
, "NodeId1" },
132 { "SHM", fixNodeId
, "NodeId2" },
133 { "SCI", fixNodeId
, "NodeId1" },
134 { "SCI", fixNodeId
, "NodeId2" },
136 { "TCP", fixHostname
, "HostName1" },
137 { "TCP", fixHostname
, "HostName2" },
138 { "SHM", fixHostname
, "HostName1" },
139 { "SHM", fixHostname
, "HostName2" },
140 { "SCI", fixHostname
, "HostName1" },
141 { "SCI", fixHostname
, "HostName2" },
142 { "SHM", fixHostname
, "HostName1" },
143 { "SHM", fixHostname
, "HostName2" },
145 { "TCP", fixPortNumber
, 0 }, // has to come after fixHostName
146 { "SHM", fixPortNumber
, 0 }, // has to come after fixHostName
147 { "SCI", fixPortNumber
, 0 }, // has to come after fixHostName
149 { "*", applyDefaultValues
, "user" },
150 { "*", fixDepricated
, 0 },
151 { "*", applyDefaultValues
, "system" },
153 { "SHM", fixShmKey
, 0 }, // has to come after apply default values
155 { DB_TOKEN
, checkLocalhostHostnameMix
, 0 },
156 { API_TOKEN
, checkLocalhostHostnameMix
, 0 },
157 { MGM_TOKEN
, checkLocalhostHostnameMix
, 0 },
159 { DB_TOKEN
, fixFileSystemPath
, 0 },
160 { DB_TOKEN
, fixBackupDataDir
, 0 },
162 { DB_TOKEN
, checkDbConstraints
, 0 },
164 { "TCP", checkConnectionConstraints
, 0 },
165 { "SHM", checkConnectionConstraints
, 0 },
166 { "SCI", checkConnectionConstraints
, 0 },
168 { "TCP", checkTCPConstraints
, "HostName1" },
169 { "TCP", checkTCPConstraints
, "HostName2" },
170 { "SCI", checkTCPConstraints
, "HostName1" },
171 { "SCI", checkTCPConstraints
, "HostName2" },
172 { "SHM", checkTCPConstraints
, "HostName1" },
173 { "SHM", checkTCPConstraints
, "HostName2" },
175 { "*", checkMandatory
, 0 },
177 { DB_TOKEN
, saveInConfigValues
, 0 },
178 { API_TOKEN
, saveInConfigValues
, 0 },
179 { MGM_TOKEN
, saveInConfigValues
, 0 },
181 { "TCP", saveInConfigValues
, 0 },
182 { "SHM", saveInConfigValues
, 0 },
183 { "SCI", saveInConfigValues
, 0 }
185 const int ConfigInfo::m_NoOfRules
= sizeof(m_SectionRules
)/sizeof(SectionRule
);
187 /****************************************************************************
188 * Config Rules declarations
189 ****************************************************************************/
190 static bool sanity_checks(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
191 struct InitConfigFileParser::Context
&ctx
,
192 const char * rule_data
);
193 static bool add_node_connections(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
194 struct InitConfigFileParser::Context
&ctx
,
195 const char * rule_data
);
196 static bool set_connection_priorities(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
197 struct InitConfigFileParser::Context
&ctx
,
198 const char * rule_data
);
199 static bool check_node_vs_replicas(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
200 struct InitConfigFileParser::Context
&ctx
,
201 const char * rule_data
);
203 const ConfigInfo::ConfigRule
204 ConfigInfo::m_ConfigRules
[] = {
205 { sanity_checks
, 0 },
206 { add_node_connections
, 0 },
207 { set_connection_priorities
, 0 },
208 { check_node_vs_replicas
, 0 },
212 struct DepricationTransform
{
213 const char * m_section
;
214 const char * m_oldName
;
215 const char * m_newName
;
221 const DepricationTransform f_deprication
[] = {
222 { DB_TOKEN
, "Discless", "Diskless", 0, 1 },
223 { DB_TOKEN
, "Id", "NodeId", 0, 1 },
224 { API_TOKEN
, "Id", "NodeId", 0, 1 },
225 { MGM_TOKEN
, "Id", "NodeId", 0, 1 },
228 #endif /* NDB_MGMAPI */
231 * The default constructors create objects with suitable values for the
232 * configuration parameters.
234 * Some are however given the value MANDATORY which means that the value
235 * must be specified in the configuration file.
237 * Min and max values are also given for some parameters.
238 * - Attr1: Name in file (initial config file)
239 * - Attr2: Name in prop (properties object)
240 * - Attr3: Name of Section (in init config file)
241 * - Attr4: Updateable
242 * - Attr5: Type of parameter (INT or BOOL)
243 * - Attr6: Default Value (number only)
247 * Parameter constraints are coded in file Config.cpp.
249 * *******************************************************************
250 * Parameters used under development should be marked "NOTIMPLEMENTED"
251 * *******************************************************************
254 const ConfigInfo::ParamInfo
ConfigInfo::m_ParamInfo
[] = {
256 /****************************************************************************
258 ***************************************************************************/
264 ConfigInfo::CI_INTERNAL
,
266 ConfigInfo::CI_SECTION
,
277 ConfigInfo::CI_STRING
,
285 "Hostname of computer (e.g. mysql.com)",
288 ConfigInfo::CI_STRING
,
297 ConfigInfo::CI_DEPRICATED
,
299 ConfigInfo::CI_STRING
,
304 /****************************************************************************
306 ***************************************************************************/
314 ConfigInfo::CI_SECTION
,
315 (const char *)CFG_SECTION_SYSTEM
,
322 "Name of system (NDB Cluster)",
325 ConfigInfo::CI_STRING
,
330 CFG_SYS_PRIMARY_MGM_NODE
,
333 "Node id of Primary "MGM_TOKEN_PRINT
" node",
339 STR_VALUE(MAX_INT_RNIL
) },
342 CFG_SYS_CONFIG_GENERATION
,
343 "ConfigGenerationNumber",
345 "Configuration generation number",
351 STR_VALUE(MAX_INT_RNIL
) },
353 /***************************************************************************
355 ***************************************************************************/
363 ConfigInfo::CI_SECTION
,
364 (const char *)NODE_TYPE_DB
,
372 "Name of computer for this node",
373 ConfigInfo::CI_INTERNAL
,
375 ConfigInfo::CI_STRING
,
383 "Name of system for this node",
384 ConfigInfo::CI_INTERNAL
,
386 ConfigInfo::CI_STRING
,
395 ConfigInfo::CI_DEPRICATED
,
400 STR_VALUE(MAX_DATA_NODE_ID
) },
406 "Number identifying the database node ("DB_TOKEN_PRINT
")",
412 STR_VALUE(MAX_DATA_NODE_ID
) },
418 "Port used to setup transporter",
424 STR_VALUE(MAX_PORT_NO
) },
430 "Number of copies of all data in the database (1-4)",
439 CFG_DB_NO_ATTRIBUTES
,
442 "Total number of attributes stored in database. I.e. sum over all tables",
448 STR_VALUE(MAX_INT_RNIL
) },
454 "Total number of tables stored in the database",
460 STR_VALUE(MAX_TABLES
) },
463 CFG_DB_NO_ORDERED_INDEXES
,
464 "MaxNoOfOrderedIndexes",
466 "Total number of ordered indexes that can be defined in the system",
472 STR_VALUE(MAX_INT_RNIL
) },
475 CFG_DB_NO_UNIQUE_HASH_INDEXES
,
476 "MaxNoOfUniqueHashIndexes",
478 "Total number of unique hash indexes that can be defined in the system",
484 STR_VALUE(MAX_INT_RNIL
) },
490 "Total number of indexes that can be defined in the system",
491 ConfigInfo::CI_DEPRICATED
,
496 STR_VALUE(MAX_INT_RNIL
) },
500 "MaxNoOfConcurrentIndexOperations",
502 "Total number of index operations that can execute simultaneously on one "DB_TOKEN_PRINT
" node",
508 STR_VALUE(MAX_INT_RNIL
)
515 "Total number of triggers that can be defined in the system",
521 STR_VALUE(MAX_INT_RNIL
) },
524 CFG_DB_NO_TRIGGER_OPS
,
525 "MaxNoOfFiredTriggers",
527 "Total number of triggers that can fire simultaneously in one "DB_TOKEN_PRINT
" node",
533 STR_VALUE(MAX_INT_RNIL
) },
539 "String referencing an earlier defined COMPUTER",
542 ConfigInfo::CI_STRING
,
548 "MaxNoOfSavedMessages",
550 "Max number of error messages in error log and max number of trace files",
556 STR_VALUE(MAX_INT_RNIL
) },
560 "LockPagesInMainMemory",
562 "If set to yes, then NDB Cluster data will not be swapped out to disk",
571 CFG_DB_WATCHDOG_INTERVAL
,
572 "TimeBetweenWatchDogCheck",
574 "Time between execution checks inside a database node",
580 STR_VALUE(MAX_INT_RNIL
) },
583 CFG_DB_WATCHDOG_INTERVAL_INITIAL
,
584 "TimeBetweenWatchDogCheckInitial",
586 "Time between execution checks inside a database node in the early start phases when memory is allocated",
592 STR_VALUE(MAX_INT_RNIL
) },
595 CFG_DB_STOP_ON_ERROR
,
598 "If set to N, "DB_TOKEN_PRINT
" automatically restarts/recovers in case of node failure",
607 CFG_DB_STOP_ON_ERROR_INSERT
,
608 "RestartOnErrorInsert",
610 "See src/kernel/vm/Emulator.hpp NdbRestartType for details",
611 ConfigInfo::CI_INTERNAL
,
620 "MaxNoOfConcurrentOperations",
622 "Max number of operation records in transaction coordinator",
628 STR_VALUE(MAX_INT_RNIL
) },
632 "MaxNoOfLocalOperations",
634 "Max number of operation records defined in the local storage node",
640 STR_VALUE(MAX_INT_RNIL
) },
643 CFG_DB_NO_LOCAL_SCANS
,
646 "Max number of fragment scans in parallel in the local storage node",
652 STR_VALUE(MAX_INT_RNIL
) },
656 "BatchSizePerLocalScan",
658 "Used to calculate the number of lock records for scan with hold lock",
662 STR_VALUE(DEF_BATCH_SIZE
),
664 STR_VALUE(MAX_PARALLEL_OP_PER_SCAN
) },
667 CFG_DB_NO_TRANSACTIONS
,
668 "MaxNoOfConcurrentTransactions",
670 "Max number of transaction executing concurrently on the "DB_TOKEN_PRINT
" node",
676 STR_VALUE(MAX_INT_RNIL
) },
680 "MaxNoOfConcurrentScans",
682 "Max number of scans executing concurrently on the "DB_TOKEN_PRINT
" node",
691 CFG_DB_TRANS_BUFFER_MEM
,
692 "TransactionBufferMemory",
694 "Dynamic buffer space (in bytes) for key and attribute data allocated for each "DB_TOKEN_PRINT
" node",
700 STR_VALUE(MAX_INT_RNIL
) },
706 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for storing indexes",
709 ConfigInfo::CI_INT64
,
718 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for storing data",
721 ConfigInfo::CI_INT64
,
727 CFG_DB_UNDO_INDEX_BUFFER
,
730 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for writing UNDO logs for index part",
736 STR_VALUE(MAX_INT_RNIL
)},
739 CFG_DB_UNDO_DATA_BUFFER
,
742 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for writing UNDO logs for data part",
748 STR_VALUE(MAX_INT_RNIL
)},
754 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for writing REDO logs",
760 STR_VALUE(MAX_INT_RNIL
)},
763 CFG_DB_LONG_SIGNAL_BUFFER
,
766 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for internal long messages",
772 STR_VALUE(MAX_INT_RNIL
)},
775 CFG_DB_DISK_PAGE_BUFFER_MEMORY
,
776 "DiskPageBufferMemory",
778 "Number bytes on each "DB_TOKEN_PRINT
" node allocated for disk page buffer cache",
781 ConfigInfo::CI_INT64
,
788 "SharedGlobalMemory",
790 "Total number bytes on each "DB_TOKEN_PRINT
" node allocated for any use",
793 ConfigInfo::CI_INT64
,
796 "65536G" }, // 32k pages * 32-bit i value
799 CFG_DB_START_PARTIAL_TIMEOUT
,
800 "StartPartialTimeout",
802 "Time to wait before trying to start wo/ all nodes. 0=Wait forever",
808 STR_VALUE(MAX_INT_RNIL
) },
811 CFG_DB_START_PARTITION_TIMEOUT
,
812 "StartPartitionedTimeout",
814 "Time to wait before trying to start partitioned. 0=Wait forever",
820 STR_VALUE(MAX_INT_RNIL
) },
823 CFG_DB_START_FAILURE_TIMEOUT
,
824 "StartFailureTimeout",
826 "Time to wait before terminating. 0=Wait forever",
832 STR_VALUE(MAX_INT_RNIL
) },
835 CFG_DB_HEARTBEAT_INTERVAL
,
836 "HeartbeatIntervalDbDb",
838 "Time between "DB_TOKEN_PRINT
"-"DB_TOKEN_PRINT
" heartbeats. "DB_TOKEN_PRINT
" considered dead after 3 missed HBs",
844 STR_VALUE(MAX_INT_RNIL
) },
847 CFG_DB_API_HEARTBEAT_INTERVAL
,
848 "HeartbeatIntervalDbApi",
850 "Time between "API_TOKEN_PRINT
"-"DB_TOKEN_PRINT
" heartbeats. "API_TOKEN_PRINT
" connection closed after 3 missed HBs",
856 STR_VALUE(MAX_INT_RNIL
) },
860 "TimeBetweenLocalCheckpoints",
862 "Time between taking snapshots of the database (expressed in 2log of bytes)",
872 "TimeBetweenGlobalCheckpoints",
874 "Time between doing group commit of transactions to disk",
883 CFG_DB_NO_REDOLOG_FILES
,
884 "NoOfFragmentLogFiles",
886 "No of 16 Mbyte Redo log files in each of 4 file sets belonging to "DB_TOKEN_PRINT
" node",
892 STR_VALUE(MAX_INT_RNIL
) },
895 CFG_DB_REDOLOG_FILE_SIZE
,
896 "FragmentLogFileSize",
898 "Size of each Redo log file",
907 CFG_DB_MAX_OPEN_FILES
,
910 "Max number of files open per "DB_TOKEN_PRINT
" node.(One thread is created per file)",
916 STR_VALUE(MAX_INT_RNIL
) },
919 CFG_DB_INITIAL_OPEN_FILES
,
920 "InitialNoOfOpenFiles",
922 "Initial number of files open per "DB_TOKEN_PRINT
" node.(One thread is created per file)",
928 STR_VALUE(MAX_INT_RNIL
) },
931 CFG_DB_TRANSACTION_CHECK_INTERVAL
,
932 "TimeBetweenInactiveTransactionAbortCheck",
934 "Time between inactive transaction checks",
940 STR_VALUE(MAX_INT_RNIL
) },
943 CFG_DB_TRANSACTION_INACTIVE_TIMEOUT
,
944 "TransactionInactiveTimeout",
946 "Time application can wait before executing another transaction part (ms).\n"
947 "This is the time the transaction coordinator waits for the application\n"
948 "to execute or send another part (query, statement) of the transaction.\n"
949 "If the application takes too long time, the transaction gets aborted.\n"
950 "Timeout set to 0 means that we don't timeout at all on application wait.",
954 STR_VALUE(MAX_INT_RNIL
),
956 STR_VALUE(MAX_INT_RNIL
) },
959 CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT
,
960 "TransactionDeadlockDetectionTimeout",
962 "Time transaction can be executing in a DB node (ms).\n"
963 "This is the time the transaction coordinator waits for each database node\n"
964 "of the transaction to execute a request. If the database node takes too\n"
965 "long time, the transaction gets aborted.",
971 STR_VALUE(MAX_INT_RNIL
) },
974 CFG_DB_LCP_DISC_PAGES_TUP_SR
,
975 "NoOfDiskPagesToDiskDuringRestartTUP",
977 "DiskCheckpointSpeedSr",
978 ConfigInfo::CI_DEPRICATED
,
983 STR_VALUE(MAX_INT_RNIL
) },
986 CFG_DB_LCP_DISC_PAGES_TUP
,
987 "NoOfDiskPagesToDiskAfterRestartTUP",
989 "DiskCheckpointSpeed",
990 ConfigInfo::CI_DEPRICATED
,
995 STR_VALUE(MAX_INT_RNIL
) },
998 CFG_DB_LCP_DISC_PAGES_ACC_SR
,
999 "NoOfDiskPagesToDiskDuringRestartACC",
1001 "DiskCheckpointSpeedSr",
1002 ConfigInfo::CI_DEPRICATED
,
1007 STR_VALUE(MAX_INT_RNIL
) },
1010 CFG_DB_LCP_DISC_PAGES_ACC
,
1011 "NoOfDiskPagesToDiskAfterRestartACC",
1013 "DiskCheckpointSpeed",
1014 ConfigInfo::CI_DEPRICATED
,
1019 STR_VALUE(MAX_INT_RNIL
) },
1027 ConfigInfo::CI_USED
,
1029 ConfigInfo::CI_BOOL
,
1039 ConfigInfo::CI_DEPRICATED
,
1041 ConfigInfo::CI_BOOL
,
1049 CFG_DB_ARBIT_TIMEOUT
,
1050 "ArbitrationTimeout",
1052 "Max time (milliseconds) database partion waits for arbitration signal",
1053 ConfigInfo::CI_USED
,
1058 STR_VALUE(MAX_INT_RNIL
) },
1064 "Data directory for this node",
1065 ConfigInfo::CI_USED
,
1067 ConfigInfo::CI_STRING
,
1072 CFG_DB_FILESYSTEM_PATH
,
1075 "Path to directory where the "DB_TOKEN_PRINT
" node stores its data (directory must exist)",
1076 ConfigInfo::CI_USED
,
1078 ConfigInfo::CI_STRING
,
1083 CFG_LOGLEVEL_STARTUP
,
1086 "Node startup info printed on stdout",
1087 ConfigInfo::CI_USED
,
1095 CFG_LOGLEVEL_SHUTDOWN
,
1098 "Node shutdown info printed on stdout",
1099 ConfigInfo::CI_USED
,
1107 CFG_LOGLEVEL_STATISTICS
,
1108 "LogLevelStatistic",
1110 "Transaction, operation, transporter info printed on stdout",
1111 ConfigInfo::CI_USED
,
1119 CFG_LOGLEVEL_CHECKPOINT
,
1120 "LogLevelCheckpoint",
1122 "Local and Global checkpoint info printed on stdout",
1123 ConfigInfo::CI_USED
,
1131 CFG_LOGLEVEL_NODERESTART
,
1132 "LogLevelNodeRestart",
1134 "Node restart, node failure info printed on stdout",
1135 ConfigInfo::CI_USED
,
1143 CFG_LOGLEVEL_CONNECTION
,
1144 "LogLevelConnection",
1146 "Node connect/disconnect info printed on stdout",
1147 ConfigInfo::CI_USED
,
1155 CFG_LOGLEVEL_CONGESTION
,
1156 "LogLevelCongestion",
1158 "Congestion info printed on stdout",
1159 ConfigInfo::CI_USED
,
1170 "Transporter, heartbeat errors printed on stdout",
1171 ConfigInfo::CI_USED
,
1182 "Heartbeat and log info printed on stdout",
1183 ConfigInfo::CI_USED
,
1194 CFG_DB_PARALLEL_BACKUPS
,
1197 "Maximum number of parallel backups",
1198 ConfigInfo::CI_NOTIMPLEMENTED
,
1206 CFG_DB_BACKUP_DATADIR
,
1209 "Path to where to store backups",
1210 ConfigInfo::CI_USED
,
1212 ConfigInfo::CI_STRING
,
1217 CFG_DB_DISK_SYNCH_SIZE
,
1220 "Data written to a file before a synch is forced",
1221 ConfigInfo::CI_USED
,
1226 STR_VALUE(MAX_INT_RNIL
) },
1229 CFG_DB_CHECKPOINT_SPEED
,
1230 "DiskCheckpointSpeed",
1232 "Bytes per second allowed to be written by checkpoint",
1233 ConfigInfo::CI_USED
,
1238 STR_VALUE(MAX_INT_RNIL
) },
1241 CFG_DB_CHECKPOINT_SPEED_SR
,
1242 "DiskCheckpointSpeedInRestart",
1244 "Bytes per second allowed to be written by checkpoint during restart",
1245 ConfigInfo::CI_USED
,
1250 STR_VALUE(MAX_INT_RNIL
) },
1256 "Total memory allocated for backups per node (in bytes)",
1257 ConfigInfo::CI_USED
,
1260 "4M", // sum of BackupDataBufferSize and BackupLogBufferSize
1262 STR_VALUE(MAX_INT_RNIL
) },
1265 CFG_DB_BACKUP_DATA_BUFFER_MEM
,
1266 "BackupDataBufferSize",
1268 "Default size of databuffer for a backup (in bytes)",
1269 ConfigInfo::CI_USED
,
1272 "2M", // remember to change BackupMemory
1274 STR_VALUE(MAX_INT_RNIL
) },
1277 CFG_DB_BACKUP_LOG_BUFFER_MEM
,
1278 "BackupLogBufferSize",
1280 "Default size of logbuffer for a backup (in bytes)",
1281 ConfigInfo::CI_USED
,
1284 "2M", // remember to change BackupMemory
1286 STR_VALUE(MAX_INT_RNIL
) },
1289 CFG_DB_BACKUP_WRITE_SIZE
,
1292 "Default size of filesystem writes made by backup (in bytes)",
1293 ConfigInfo::CI_USED
,
1298 STR_VALUE(MAX_INT_RNIL
) },
1301 CFG_DB_BACKUP_MAX_WRITE_SIZE
,
1302 "BackupMaxWriteSize",
1304 "Max size of filesystem writes made by backup (in bytes)",
1305 ConfigInfo::CI_USED
,
1310 STR_VALUE(MAX_INT_RNIL
) },
1313 CFG_DB_STRING_MEMORY
,
1316 "Default size of string memory (0 -> 5% of max 1-100 -> %of max, >100 -> actual bytes)",
1317 ConfigInfo::CI_USED
,
1322 STR_VALUE(MAX_INT_RNIL
) },
1325 CFG_DB_MAX_ALLOCATE
,
1328 "Maximum size of allocation to use when allocating memory for tables",
1329 ConfigInfo::CI_USED
,
1337 CFG_DB_MEMREPORT_FREQUENCY
,
1338 "MemReportFrequency",
1340 "Frequency of mem reports in seconds, 0 = only when passing %-limits",
1341 ConfigInfo::CI_USED
,
1346 STR_VALUE(MAX_INT_RNIL
) },
1352 "Use O_DIRECT file write/read when possible",
1353 ConfigInfo::CI_USED
,
1355 ConfigInfo::CI_BOOL
,
1360 /***************************************************************************
1362 ***************************************************************************/
1368 ConfigInfo::CI_USED
,
1370 ConfigInfo::CI_SECTION
,
1371 (const char *)NODE_TYPE_API
,
1379 "Name of computer for this node",
1380 ConfigInfo::CI_INTERNAL
,
1382 ConfigInfo::CI_STRING
,
1390 "Name of system for this node",
1391 ConfigInfo::CI_INTERNAL
,
1393 ConfigInfo::CI_STRING
,
1402 ConfigInfo::CI_DEPRICATED
,
1407 STR_VALUE(MAX_NODES_ID
) },
1413 "Number identifying application node ("API_TOKEN_PRINT
")",
1414 ConfigInfo::CI_USED
,
1419 STR_VALUE(MAX_NODES_ID
) },
1423 "ExecuteOnComputer",
1425 "String referencing an earlier defined COMPUTER",
1426 ConfigInfo::CI_USED
,
1428 ConfigInfo::CI_STRING
,
1433 CFG_NODE_ARBIT_RANK
,
1436 "If 0, then "API_TOKEN_PRINT
" is not arbitrator. Kernel selects arbitrators in order 1, 2",
1437 ConfigInfo::CI_USED
,
1445 CFG_NODE_ARBIT_DELAY
,
1448 "When asked to arbitrate, arbitrator waits this long before voting (msec)",
1449 ConfigInfo::CI_USED
,
1454 STR_VALUE(MAX_INT_RNIL
) },
1457 CFG_MAX_SCAN_BATCH_SIZE
,
1460 "The maximum collective batch size for one scan",
1461 ConfigInfo::CI_USED
,
1464 STR_VALUE(MAX_SCAN_BATCH_SIZE
),
1469 CFG_BATCH_BYTE_SIZE
,
1472 "The default batch size in bytes",
1473 ConfigInfo::CI_USED
,
1476 STR_VALUE(SCAN_BATCH_SIZE
),
1484 "The default batch size in number of records",
1485 ConfigInfo::CI_USED
,
1488 STR_VALUE(DEF_BATCH_SIZE
),
1490 STR_VALUE(MAX_PARALLEL_OP_PER_SCAN
) },
1492 /****************************************************************************
1494 ***************************************************************************/
1500 ConfigInfo::CI_USED
,
1502 ConfigInfo::CI_SECTION
,
1503 (const char *)NODE_TYPE_MGM
,
1511 "Name of computer for this node",
1512 ConfigInfo::CI_INTERNAL
,
1514 ConfigInfo::CI_STRING
,
1522 "Data directory for this node",
1523 ConfigInfo::CI_USED
,
1525 ConfigInfo::CI_STRING
,
1533 "Name of system for this node",
1534 ConfigInfo::CI_INTERNAL
,
1536 ConfigInfo::CI_STRING
,
1545 ConfigInfo::CI_DEPRICATED
,
1550 STR_VALUE(MAX_NODES_ID
) },
1556 "Number identifying the management server node ("MGM_TOKEN_PRINT
")",
1557 ConfigInfo::CI_USED
,
1562 STR_VALUE(MAX_NODES_ID
) },
1565 CFG_LOG_DESTINATION
,
1568 "String describing where logmessages are sent",
1569 ConfigInfo::CI_USED
,
1571 ConfigInfo::CI_STRING
,
1577 "ExecuteOnComputer",
1579 "String referencing an earlier defined COMPUTER",
1580 ConfigInfo::CI_USED
,
1582 ConfigInfo::CI_STRING
,
1588 "MaxNoOfSavedEvents",
1591 ConfigInfo::CI_USED
,
1596 STR_VALUE(MAX_INT_RNIL
) },
1602 "Port number to give commands to/fetch configurations from management server",
1603 ConfigInfo::CI_USED
,
1608 STR_VALUE(MAX_PORT_NO
) },
1614 "Port number used to get statistical information from a management server",
1615 ConfigInfo::CI_USED
,
1620 STR_VALUE(MAX_PORT_NO
) },
1623 CFG_NODE_ARBIT_RANK
,
1626 "If 0, then "MGM_TOKEN_PRINT
" is not arbitrator. Kernel selects arbitrators in order 1, 2",
1627 ConfigInfo::CI_USED
,
1635 CFG_NODE_ARBIT_DELAY
,
1639 ConfigInfo::CI_USED
,
1644 STR_VALUE(MAX_INT_RNIL
) },
1646 /****************************************************************************
1648 ***************************************************************************/
1650 CFG_SECTION_CONNECTION
,
1653 "Connection section",
1654 ConfigInfo::CI_USED
,
1656 ConfigInfo::CI_SECTION
,
1657 (const char *)CONNECTION_TYPE_TCP
,
1662 CFG_CONNECTION_HOSTNAME_1
,
1665 "Name/IP of computer on one side of the connection",
1666 ConfigInfo::CI_INTERNAL
,
1668 ConfigInfo::CI_STRING
,
1673 CFG_CONNECTION_HOSTNAME_2
,
1676 "Name/IP of computer on one side of the connection",
1677 ConfigInfo::CI_INTERNAL
,
1679 ConfigInfo::CI_STRING
,
1684 CFG_CONNECTION_NODE_1
,
1687 "Id of node ("DB_TOKEN_PRINT
", "API_TOKEN_PRINT
" or "MGM_TOKEN_PRINT
") on one side of the connection",
1688 ConfigInfo::CI_USED
,
1690 ConfigInfo::CI_STRING
,
1695 CFG_CONNECTION_NODE_2
,
1698 "Id of node ("DB_TOKEN_PRINT
", "API_TOKEN_PRINT
" or "MGM_TOKEN_PRINT
") on one side of the connection",
1699 ConfigInfo::CI_USED
,
1701 ConfigInfo::CI_STRING
,
1706 CFG_CONNECTION_GROUP
,
1710 ConfigInfo::CI_USED
,
1717 CFG_CONNECTION_NODE_ID_SERVER
,
1721 ConfigInfo::CI_USED
,
1728 CFG_CONNECTION_SEND_SIGNAL_ID
,
1731 "Sends id in each signal. Used in trace files.",
1732 ConfigInfo::CI_USED
,
1734 ConfigInfo::CI_BOOL
,
1741 CFG_CONNECTION_CHECKSUM
,
1744 "If checksum is enabled, all signals between nodes are checked for errors",
1745 ConfigInfo::CI_USED
,
1747 ConfigInfo::CI_BOOL
,
1753 CFG_CONNECTION_SERVER_PORT
,
1756 "Port used for this transporter",
1757 ConfigInfo::CI_USED
,
1762 STR_VALUE(MAX_PORT_NO
) },
1765 CFG_TCP_SEND_BUFFER_SIZE
,
1768 "Bytes of buffer for signals sent from this node",
1769 ConfigInfo::CI_USED
,
1774 STR_VALUE(MAX_INT_RNIL
) },
1777 CFG_TCP_RECEIVE_BUFFER_SIZE
,
1778 "ReceiveBufferMemory",
1780 "Bytes of buffer for signals received by this node",
1781 ConfigInfo::CI_USED
,
1786 STR_VALUE(MAX_INT_RNIL
) },
1793 ConfigInfo::CI_USED
,
1795 ConfigInfo::CI_STRING
,
1800 CFG_CONNECTION_NODE_1_SYSTEM
,
1803 "System for node 1 in connection",
1804 ConfigInfo::CI_INTERNAL
,
1806 ConfigInfo::CI_STRING
,
1811 CFG_CONNECTION_NODE_2_SYSTEM
,
1814 "System for node 2 in connection",
1815 ConfigInfo::CI_INTERNAL
,
1817 ConfigInfo::CI_STRING
,
1822 /****************************************************************************
1824 ***************************************************************************/
1826 CFG_SECTION_CONNECTION
,
1829 "Connection section",
1830 ConfigInfo::CI_USED
,
1832 ConfigInfo::CI_SECTION
,
1833 (const char *)CONNECTION_TYPE_SHM
,
1837 CFG_CONNECTION_HOSTNAME_1
,
1840 "Name/IP of computer on one side of the connection",
1841 ConfigInfo::CI_INTERNAL
,
1843 ConfigInfo::CI_STRING
,
1848 CFG_CONNECTION_HOSTNAME_2
,
1851 "Name/IP of computer on one side of the connection",
1852 ConfigInfo::CI_INTERNAL
,
1854 ConfigInfo::CI_STRING
,
1859 CFG_CONNECTION_SERVER_PORT
,
1862 "Port used for this transporter",
1863 ConfigInfo::CI_USED
,
1868 STR_VALUE(MAX_PORT_NO
) },
1874 "Signum to be used for signalling",
1875 ConfigInfo::CI_USED
,
1880 STR_VALUE(MAX_INT_RNIL
) },
1883 CFG_CONNECTION_NODE_1
,
1886 "Id of node ("DB_TOKEN_PRINT
", "API_TOKEN_PRINT
" or "MGM_TOKEN_PRINT
") on one side of the connection",
1887 ConfigInfo::CI_USED
,
1889 ConfigInfo::CI_STRING
,
1894 CFG_CONNECTION_NODE_2
,
1897 "Id of node ("DB_TOKEN_PRINT
", "API_TOKEN_PRINT
" or "MGM_TOKEN_PRINT
") on one side of the connection",
1898 ConfigInfo::CI_USED
,
1900 ConfigInfo::CI_STRING
,
1905 CFG_CONNECTION_GROUP
,
1909 ConfigInfo::CI_USED
,
1916 CFG_CONNECTION_NODE_ID_SERVER
,
1920 ConfigInfo::CI_USED
,
1927 CFG_CONNECTION_SEND_SIGNAL_ID
,
1930 "Sends id in each signal. Used in trace files.",
1931 ConfigInfo::CI_USED
,
1933 ConfigInfo::CI_BOOL
,
1940 CFG_CONNECTION_CHECKSUM
,
1943 "If checksum is enabled, all signals between nodes are checked for errors",
1944 ConfigInfo::CI_USED
,
1946 ConfigInfo::CI_BOOL
,
1955 "A shared memory key",
1956 ConfigInfo::CI_USED
,
1961 STR_VALUE(MAX_INT_RNIL
) },
1967 "Size of shared memory segment",
1968 ConfigInfo::CI_USED
,
1973 STR_VALUE(MAX_INT_RNIL
) },
1976 CFG_CONNECTION_NODE_1_SYSTEM
,
1979 "System for node 1 in connection",
1980 ConfigInfo::CI_INTERNAL
,
1982 ConfigInfo::CI_STRING
,
1987 CFG_CONNECTION_NODE_2_SYSTEM
,
1990 "System for node 2 in connection",
1991 ConfigInfo::CI_INTERNAL
,
1993 ConfigInfo::CI_STRING
,
1997 /****************************************************************************
1999 ***************************************************************************/
2001 CFG_SECTION_CONNECTION
,
2004 "Connection section",
2005 ConfigInfo::CI_USED
,
2007 ConfigInfo::CI_SECTION
,
2008 (const char *)CONNECTION_TYPE_SCI
,
2013 CFG_CONNECTION_NODE_1
,
2016 "Id of node ("DB_TOKEN_PRINT
", "API_TOKEN_PRINT
" or "MGM_TOKEN_PRINT
") on one side of the connection",
2017 ConfigInfo::CI_USED
,
2019 ConfigInfo::CI_STRING
,
2022 STR_VALUE(MAX_INT_RNIL
) },
2025 CFG_CONNECTION_NODE_2
,
2028 "Id of node ("DB_TOKEN_PRINT
", "API_TOKEN_PRINT
" or "MGM_TOKEN_PRINT
") on one side of the connection",
2029 ConfigInfo::CI_USED
,
2031 ConfigInfo::CI_STRING
,
2034 STR_VALUE(MAX_INT_RNIL
) },
2037 CFG_CONNECTION_GROUP
,
2041 ConfigInfo::CI_USED
,
2048 CFG_CONNECTION_NODE_ID_SERVER
,
2052 ConfigInfo::CI_USED
,
2059 CFG_CONNECTION_HOSTNAME_1
,
2062 "Name/IP of computer on one side of the connection",
2063 ConfigInfo::CI_INTERNAL
,
2065 ConfigInfo::CI_STRING
,
2070 CFG_CONNECTION_HOSTNAME_2
,
2073 "Name/IP of computer on one side of the connection",
2074 ConfigInfo::CI_INTERNAL
,
2076 ConfigInfo::CI_STRING
,
2081 CFG_CONNECTION_SERVER_PORT
,
2084 "Port used for this transporter",
2085 ConfigInfo::CI_USED
,
2090 STR_VALUE(MAX_PORT_NO
) },
2096 "SCI-node id for adapter 0 on Host1 (a computer can have two adapters)",
2097 ConfigInfo::CI_USED
,
2102 STR_VALUE(MAX_INT_RNIL
) },
2108 "SCI-node id for adapter 1 on Host1 (a computer can have two adapters)",
2109 ConfigInfo::CI_USED
,
2114 STR_VALUE(MAX_INT_RNIL
) },
2120 "SCI-node id for adapter 0 on Host2 (a computer can have two adapters)",
2121 ConfigInfo::CI_USED
,
2126 STR_VALUE(MAX_INT_RNIL
) },
2132 "SCI-node id for adapter 1 on Host2 (a computer can have two adapters)",
2133 ConfigInfo::CI_USED
,
2138 STR_VALUE(MAX_INT_RNIL
) },
2141 CFG_CONNECTION_SEND_SIGNAL_ID
,
2144 "Sends id in each signal. Used in trace files.",
2145 ConfigInfo::CI_USED
,
2147 ConfigInfo::CI_BOOL
,
2153 CFG_CONNECTION_CHECKSUM
,
2156 "If checksum is enabled, all signals between nodes are checked for errors",
2157 ConfigInfo::CI_USED
,
2159 ConfigInfo::CI_BOOL
,
2168 "Transporter send buffer contents are sent when this no of bytes is buffered",
2169 ConfigInfo::CI_USED
,
2180 "Size of shared memory segment",
2181 ConfigInfo::CI_USED
,
2186 STR_VALUE(MAX_INT_RNIL
) },
2189 CFG_CONNECTION_NODE_1_SYSTEM
,
2192 "System for node 1 in connection",
2193 ConfigInfo::CI_INTERNAL
,
2195 ConfigInfo::CI_STRING
,
2200 CFG_CONNECTION_NODE_2_SYSTEM
,
2203 "System for node 2 in connection",
2204 ConfigInfo::CI_INTERNAL
,
2206 ConfigInfo::CI_STRING
,
2211 const int ConfigInfo::m_NoOfParams
= sizeof(m_ParamInfo
) / sizeof(ParamInfo
);
2214 /****************************************************************************
2216 ****************************************************************************/
2217 static void require(bool v
)
2228 ConfigInfo::ConfigInfo()
2229 : m_info(true), m_systemDefaults(true)
2232 Properties
*section
;
2233 const Properties
*oldpinfo
;
2235 for (i
=0; i
<m_NoOfParams
; i
++) {
2236 const ParamInfo
& param
= m_ParamInfo
[i
];
2237 Uint64 default_uint64
;
2240 // Create new section if it did not exist
2241 if (!m_info
.getCopy(param
._section
, §ion
)) {
2242 Properties
newsection(true);
2243 m_info
.put(param
._section
, &newsection
);
2245 // Get copy of section
2246 m_info
.getCopy(param
._section
, §ion
);
2249 // Create pinfo (parameter info) entry
2250 Properties
pinfo(true);
2251 pinfo
.put("Id", param
._paramId
);
2252 pinfo
.put("Fname", param
._fname
);
2253 pinfo
.put("Description", param
._description
);
2254 pinfo
.put("Updateable", param
._updateable
);
2255 pinfo
.put("Type", param
._type
);
2256 pinfo
.put("Status", param
._status
);
2258 if(param
._default
== MANDATORY
){
2259 pinfo
.put("Mandatory", (Uint32
)1);
2262 switch (param
._type
) {
2266 require(InitConfigFileParser::convertStringToBool(param
._min
, tmp_bool
));
2267 pinfo
.put64("Min", tmp_bool
);
2268 require(InitConfigFileParser::convertStringToBool(param
._max
, tmp_bool
));
2269 pinfo
.put64("Max", tmp_bool
);
2276 require(InitConfigFileParser::convertStringToUint64(param
._min
, tmp_uint64
));
2277 pinfo
.put64("Min", tmp_uint64
);
2278 require(InitConfigFileParser::convertStringToUint64(param
._max
, tmp_uint64
));
2279 pinfo
.put64("Max", tmp_uint64
);
2283 pinfo
.put("SectionType", (Uint32
)UintPtr(param
._default
));
2289 // Check that pinfo is really new
2290 if (section
->get(param
._fname
, &oldpinfo
)) {
2291 ndbout
<< "Error: Parameter " << param
._fname
2292 << " defined twice in section " << param
._section
2297 // Add new pinfo to section
2298 section
->put(param
._fname
, &pinfo
);
2300 // Replace section with modified section
2301 m_info
.put(param
._section
, section
, true);
2304 if(param
._type
!= ConfigInfo::CI_SECTION
){
2306 if(!m_systemDefaults
.getCopy(param
._section
, &p
)){
2307 p
= new Properties(true);
2309 if(param
._default
!= UNDEFINED
&&
2310 param
._default
!= MANDATORY
){
2311 switch (param
._type
)
2316 require(p
->put(param
._fname
, param
._default
));
2320 require(InitConfigFileParser::convertStringToBool(param
._default
, default_bool
));
2321 require(p
->put(param
._fname
, default_bool
));
2327 require(InitConfigFileParser::convertStringToUint64(param
._default
, default_uint64
));
2328 require(p
->put(param
._fname
, default_uint64
));
2333 require(m_systemDefaults
.put(param
._section
, p
, true));
2338 for (i
=0; i
<m_NoOfParams
; i
++) {
2339 if(m_ParamInfo
[i
]._section
== NULL
){
2340 ndbout
<< "Check that each entry has a section failed." << endl
;
2341 ndbout
<< "Parameter \"" << m_ParamInfo
[i
]._fname
<< endl
;
2342 ndbout
<< "Edit file " << __FILE__
<< "." << endl
;
2346 if(m_ParamInfo
[i
]._type
== ConfigInfo::CI_SECTION
)
2349 const Properties
* p
= getInfo(m_ParamInfo
[i
]._section
);
2350 if (!p
|| !p
->contains(m_ParamInfo
[i
]._fname
)) {
2351 ndbout
<< "Check that each pname has an fname failed." << endl
;
2352 ndbout
<< "Parameter \"" << m_ParamInfo
[i
]._fname
2353 << "\" does not exist in section \""
2354 << m_ParamInfo
[i
]._section
<< "\"." << endl
;
2355 ndbout
<< "Edit file " << __FILE__
<< "." << endl
;
2361 /****************************************************************************
2363 ****************************************************************************/
2364 inline void warning(const char * src
, const char * arg
){
2365 ndbout
<< "Illegal call to ConfigInfo::" << src
<< "() - " << arg
<< endl
;
2370 ConfigInfo::getInfo(const char * section
) const {
2371 const Properties
* p
;
2372 if(!m_info
.get(section
, &p
)){
2374 // warning("getInfo", section);
2380 ConfigInfo::getDefaults(const char * section
) const {
2381 const Properties
* p
;
2382 if(!m_systemDefaults
.get(section
, &p
)){
2384 //warning("getDefaults", section);
2391 getInfoInt(const Properties
* section
,
2392 const char* fname
, const char * type
){
2394 const Properties
* p
;
2395 if (section
->get(fname
, &p
) && p
->get(type
, &val32
)) {
2400 if(p
&& p
->get(type
, &val64
)){
2405 if(section
->get(fname
, &p
)){
2409 warning(type
, fname
);
2415 getInfoString(const Properties
* section
,
2416 const char* fname
, const char * type
){
2418 const Properties
* p
;
2419 if (section
->get(fname
, &p
) && p
->get(type
, &val
)) {
2422 warning(type
, fname
);
2427 ConfigInfo::getMax(const Properties
* section
, const char* fname
) const {
2428 return getInfoInt(section
, fname
, "Max");
2432 ConfigInfo::getMin(const Properties
* section
, const char* fname
) const {
2433 return getInfoInt(section
, fname
, "Min");
2437 ConfigInfo::getDefault(const Properties
* section
, const char* fname
) const {
2438 return getInfoInt(section
, fname
, "Default");
2442 ConfigInfo::getDescription(const Properties
* section
,
2443 const char* fname
) const {
2444 return getInfoString(section
, fname
, "Description");
2448 ConfigInfo::isSection(const char * section
) const {
2449 for (int i
= 0; i
<m_noOfSectionNames
; i
++) {
2450 if(!strcasecmp(section
, m_sectionNames
[i
])) return true;
2456 ConfigInfo::nameToAlias(const char * name
) {
2457 for (int i
= 0; m_sectionNameAliases
[i
].name
!= 0; i
++)
2458 if(!strcasecmp(name
, m_sectionNameAliases
[i
].name
))
2459 return m_sectionNameAliases
[i
].alias
;
2464 ConfigInfo::getAlias(const char * section
) {
2465 for (int i
= 0; m_sectionNameAliases
[i
].name
!= 0; i
++)
2466 if(!strcasecmp(section
, m_sectionNameAliases
[i
].alias
))
2467 return m_sectionNameAliases
[i
].name
;
2472 ConfigInfo::verify(const Properties
* section
, const char* fname
,
2473 Uint64 value
) const {
2476 min
= getInfoInt(section
, fname
, "Min");
2477 max
= getInfoInt(section
, fname
, "Max");
2479 warning("verify", fname
);
2481 if (value
>= min
&& value
<= max
)
2488 ConfigInfo::getType(const Properties
* section
, const char* fname
) const {
2489 return (ConfigInfo::Type
) getInfoInt(section
, fname
, "Type");
2493 ConfigInfo::getStatus(const Properties
* section
, const char* fname
) const {
2494 return (ConfigInfo::Status
) getInfoInt(section
, fname
, "Status");
2497 /****************************************************************************
2499 ****************************************************************************/
2501 void ConfigInfo::print() const {
2502 Properties::Iterator
it(&m_info
);
2503 for (const char* n
= it
.first(); n
!= NULL
; n
= it
.next()) {
2508 void ConfigInfo::print(const char* section
) const {
2509 ndbout
<< "****** " << section
<< " ******" << endl
<< endl
;
2510 const Properties
* sec
= getInfo(section
);
2511 Properties::Iterator
it(sec
);
2512 for (const char* n
= it
.first(); n
!= NULL
; n
= it
.next()) {
2513 // Skip entries with different F- and P-names
2514 if (getStatus(sec
, n
) == ConfigInfo::CI_INTERNAL
) continue;
2515 if (getStatus(sec
, n
) == ConfigInfo::CI_DEPRICATED
) continue;
2516 if (getStatus(sec
, n
) == ConfigInfo::CI_NOTIMPLEMENTED
) continue;
2521 void ConfigInfo::print(const Properties
* section
,
2522 const char* parameter
) const {
2523 ndbout
<< parameter
;
2524 // ndbout << getDescription(section, parameter) << endl;
2525 switch (getType(section
, parameter
)) {
2526 case ConfigInfo::CI_BOOL
:
2527 ndbout
<< " (Boolean value)" << endl
;
2528 ndbout
<< getDescription(section
, parameter
) << endl
;
2529 if (getDefault(section
, parameter
) == false) {
2530 ndbout
<< "Default: N (Legal values: Y, N)" << endl
;
2531 } else if (getDefault(section
, parameter
) == true) {
2532 ndbout
<< "Default: Y (Legal values: Y, N)" << endl
;
2533 } else if (getDefault(section
, parameter
) == (UintPtr
)MANDATORY
) {
2534 ndbout
<< "MANDATORY (Legal values: Y, N)" << endl
;
2536 ndbout
<< "UNKNOWN" << endl
;
2541 case ConfigInfo::CI_INT
:
2542 case ConfigInfo::CI_INT64
:
2543 ndbout
<< " (Non-negative Integer)" << endl
;
2544 ndbout
<< getDescription(section
, parameter
) << endl
;
2545 if (getDefault(section
, parameter
) == (UintPtr
)MANDATORY
) {
2546 ndbout
<< "MANDATORY (";
2547 } else if (getDefault(section
, parameter
) == (UintPtr
)UNDEFINED
) {
2548 ndbout
<< "UNDEFINED (";
2550 ndbout
<< "Default: " << getDefault(section
, parameter
) << " (";
2552 ndbout
<< "Min: " << getMin(section
, parameter
) << ", ";
2553 ndbout
<< "Max: " << getMax(section
, parameter
) << ")" << endl
;
2557 case ConfigInfo::CI_STRING
:
2558 ndbout
<< " (String)" << endl
;
2559 ndbout
<< getDescription(section
, parameter
) << endl
;
2560 if (getDefault(section
, parameter
) == (UintPtr
)MANDATORY
) {
2561 ndbout
<< "MANDATORY" << endl
;
2563 ndbout
<< "No default value" << endl
;
2567 case ConfigInfo::CI_SECTION
:
2572 /****************************************************************************
2574 ****************************************************************************/
2577 * Node rule: Add "Type" and update "NoOfNodes"
2580 transformNode(InitConfigFileParser::Context
& ctx
, const char * data
){
2583 if(!ctx
.m_currentSection
->get("NodeId", &id
) && !ctx
.m_currentSection
->get("Id", &id
)){
2584 Uint32 nextNodeId
= 1;
2585 ctx
.m_userProperties
.get("NextNodeId", &nextNodeId
);
2587 while (ctx
.m_userProperties
.get("AllocatedNodeId_", id
, &line
))
2589 if (id
!= nextNodeId
)
2591 fprintf(stderr
,"Cluster configuration warning line %d: "
2592 "Could not use next node id %d for section [%s], "
2593 "using next unused node id %d.\n",
2594 ctx
.m_sectionLineno
, nextNodeId
, ctx
.fname
, id
);
2596 ctx
.m_currentSection
->put("NodeId", id
);
2597 } else if(ctx
.m_userProperties
.get("AllocatedNodeId_", id
, &line
)) {
2598 ctx
.reportError("Duplicate nodeid in section "
2599 "[%s] starting at line: %d. Previously used on line %d.",
2600 ctx
.fname
, ctx
.m_sectionLineno
, line
);
2606 ctx
.reportError("too many nodes configured, only up to %d nodes supported.",
2611 // next node id _always_ next numbers after last used id
2612 ctx
.m_userProperties
.put("NextNodeId", id
+1, true);
2614 ctx
.m_userProperties
.put("AllocatedNodeId_", id
, ctx
.m_sectionLineno
);
2615 BaseString::snprintf(ctx
.pname
, sizeof(ctx
.pname
), "Node_%d", id
);
2617 ctx
.m_currentSection
->put("Type", ctx
.fname
);
2620 ctx
.m_userProperties
.get("NoOfNodes", &nodes
);
2621 ctx
.m_userProperties
.put("NoOfNodes", ++nodes
, true);
2624 * Update count (per type)
2627 ctx
.m_userProperties
.get(ctx
.fname
, &nodes
);
2628 ctx
.m_userProperties
.put(ctx
.fname
, ++nodes
, true);
2633 static bool checkLocalhostHostnameMix(InitConfigFileParser::Context
& ctx
, const char * data
)
2635 DBUG_ENTER("checkLocalhostHostnameMix");
2636 const char * hostname
= 0;
2637 ctx
.m_currentSection
->get("HostName", &hostname
);
2638 if (hostname
== 0 || hostname
[0] == 0)
2641 Uint32 localhost_used
= 0;
2642 if(!strcmp(hostname
, "localhost") || !strcmp(hostname
, "127.0.0.1")){
2644 ctx
.m_userProperties
.put("$computer-localhost-used", localhost_used
);
2645 if(!ctx
.m_userProperties
.get("$computer-localhost", &hostname
))
2648 ctx
.m_userProperties
.get("$computer-localhost-used", &localhost_used
);
2649 ctx
.m_userProperties
.put("$computer-localhost", hostname
);
2652 if (localhost_used
) {
2653 ctx
.reportError("Mixing of localhost (default for [NDBD]HostName) with other hostname(%s) is illegal",
2662 fixNodeHostname(InitConfigFileParser::Context
& ctx
, const char * data
)
2664 const char * hostname
;
2665 DBUG_ENTER("fixNodeHostname");
2667 if (ctx
.m_currentSection
->get("HostName", &hostname
))
2668 DBUG_RETURN(checkLocalhostHostnameMix(ctx
,0));
2670 const char * compId
;
2671 if(!ctx
.m_currentSection
->get("ExecuteOnComputer", &compId
))
2674 const Properties
* computer
;
2676 BaseString::snprintf(tmp
, sizeof(tmp
), "Computer_%s", compId
);
2677 if(!ctx
.m_config
->get(tmp
, &computer
)){
2678 ctx
.reportError("Computer \"%s\" not declared"
2679 "- [%s] starting at line: %d",
2680 compId
, ctx
.fname
, ctx
.m_sectionLineno
);
2684 if(!computer
->get("HostName", &hostname
)){
2685 ctx
.reportError("HostName missing in [COMPUTER] (Id: %d) "
2686 " - [%s] starting at line: %d",
2687 compId
, ctx
.fname
, ctx
.m_sectionLineno
);
2691 require(ctx
.m_currentSection
->put("HostName", hostname
));
2692 DBUG_RETURN(checkLocalhostHostnameMix(ctx
,0));
2696 fixFileSystemPath(InitConfigFileParser::Context
& ctx
, const char * data
){
2697 DBUG_ENTER("fixFileSystemPath");
2700 if (ctx
.m_currentSection
->get("FileSystemPath", &path
))
2703 if (ctx
.m_currentSection
->get("DataDir", &path
)) {
2704 require(ctx
.m_currentSection
->put("FileSystemPath", path
));
2713 fixBackupDataDir(InitConfigFileParser::Context
& ctx
, const char * data
){
2716 if (ctx
.m_currentSection
->get("BackupDataDir", &path
))
2719 if (ctx
.m_currentSection
->get("FileSystemPath", &path
)) {
2720 require(ctx
.m_currentSection
->put("BackupDataDir", path
));
2729 * Connection rule: Check support of connection
2732 checkConnectionSupport(InitConfigFileParser::Context
& ctx
, const char * data
)
2735 if (strcasecmp("TCP",ctx
.fname
) == 0)
2739 else if (strcasecmp("SHM",ctx
.fname
) == 0)
2741 #ifndef NDB_SHM_TRANSPORTER
2745 else if (strcasecmp("SCI",ctx
.fname
) == 0)
2747 #ifndef NDB_SCI_TRANSPORTER
2754 ctx
.reportError("Binary not compiled with this connection support, "
2755 "[%s] starting at line: %d",
2756 ctx
.fname
, ctx
.m_sectionLineno
);
2763 * Connection rule: Update "NoOfConnections"
2766 transformConnection(InitConfigFileParser::Context
& ctx
, const char * data
)
2768 Uint32 connections
= 0;
2769 ctx
.m_userProperties
.get("NoOfConnections", &connections
);
2770 BaseString::snprintf(ctx
.pname
, sizeof(ctx
.pname
), "Connection_%d", connections
);
2771 ctx
.m_userProperties
.put("NoOfConnections", ++connections
, true);
2773 ctx
.m_currentSection
->put("Type", ctx
.fname
);
2778 * System rule: Just add it
2781 transformSystem(InitConfigFileParser::Context
& ctx
, const char * data
){
2784 if(!ctx
.m_currentSection
->get("Name", &name
)){
2785 ctx
.reportError("Mandatory parameter Name missing from section "
2786 "[%s] starting at line: %d",
2787 ctx
.fname
, ctx
.m_sectionLineno
);
2791 ndbout
<< "transformSystem " << name
<< endl
;
2793 BaseString::snprintf(ctx
.pname
, sizeof(ctx
.pname
), "SYSTEM_%s", name
);
2799 * Computer rule: Update "NoOfComputers", add "Type"
2802 transformComputer(InitConfigFileParser::Context
& ctx
, const char * data
){
2804 if(!ctx
.m_currentSection
->get("Id", &id
)){
2805 ctx
.reportError("Mandatory parameter Id missing from section "
2806 "[%s] starting at line: %d",
2807 ctx
.fname
, ctx
.m_sectionLineno
);
2810 BaseString::snprintf(ctx
.pname
, sizeof(ctx
.pname
), "Computer_%s", id
);
2812 Uint32 computers
= 0;
2813 ctx
.m_userProperties
.get("NoOfComputers", &computers
);
2814 ctx
.m_userProperties
.put("NoOfComputers", ++computers
, true);
2816 const char * hostname
= 0;
2817 ctx
.m_currentSection
->get("HostName", &hostname
);
2822 return checkLocalhostHostnameMix(ctx
,0);
2826 * Apply default values
2829 applyDefaultValues(InitConfigFileParser::Context
& ctx
,
2830 const Properties
* defaults
)
2832 DBUG_ENTER("applyDefaultValues");
2833 if(defaults
!= NULL
){
2834 Properties::Iterator
it(defaults
);
2836 for(const char * name
= it
.first(); name
!= NULL
; name
= it
.next()){
2837 (void) ctx
.m_info
->getStatus(ctx
.m_currentInfo
, name
);
2838 if(!ctx
.m_currentSection
->contains(name
)){
2839 switch (ctx
.m_info
->getType(ctx
.m_currentInfo
, name
)){
2840 case ConfigInfo::CI_INT
:
2841 case ConfigInfo::CI_BOOL
:{
2843 ::require(defaults
->get(name
, &val
));
2844 ctx
.m_currentSection
->put(name
, val
);
2845 DBUG_PRINT("info",("%s=%d #default",name
,val
));
2848 case ConfigInfo::CI_INT64
:{
2850 ::require(defaults
->get(name
, &val
));
2851 ctx
.m_currentSection
->put64(name
, val
);
2852 DBUG_PRINT("info",("%s=%lld #default",name
,val
));
2855 case ConfigInfo::CI_STRING
:{
2857 ::require(defaults
->get(name
, &val
));
2858 ctx
.m_currentSection
->put(name
, val
);
2859 DBUG_PRINT("info",("%s=%s #default",name
,val
));
2862 case ConfigInfo::CI_SECTION
:
2869 switch (ctx
.m_info
->getType(ctx
.m_currentInfo
, name
)){
2870 case ConfigInfo::CI_INT
:
2871 case ConfigInfo::CI_BOOL
:{
2873 ::require(ctx
.m_currentSection
->get(name
, &val
));
2874 DBUG_PRINT("info",("%s=%d",name
,val
));
2877 case ConfigInfo::CI_INT64
:{
2879 ::require(ctx
.m_currentSection
->get(name
, &val
));
2880 DBUG_PRINT("info",("%s=%lld",name
,val
));
2883 case ConfigInfo::CI_STRING
:{
2885 ::require(ctx
.m_currentSection
->get(name
, &val
));
2886 DBUG_PRINT("info",("%s=%s",name
,val
));
2889 case ConfigInfo::CI_SECTION
:
2900 applyDefaultValues(InitConfigFileParser::Context
& ctx
, const char * data
){
2902 if(strcmp(data
, "user") == 0)
2903 applyDefaultValues(ctx
, ctx
.m_userDefaults
);
2904 else if (strcmp(data
, "system") == 0)
2905 applyDefaultValues(ctx
, ctx
.m_systemDefaults
);
2913 * Check that a section contains all MANDATORY parameters
2916 checkMandatory(InitConfigFileParser::Context
& ctx
, const char * data
){
2918 Properties::Iterator
it(ctx
.m_currentInfo
);
2919 for(const char * name
= it
.first(); name
!= NULL
; name
= it
.next()){
2920 const Properties
* info
= NULL
;
2921 ::require(ctx
.m_currentInfo
->get(name
, &info
));
2923 if(info
->get("Mandatory", &val
)){
2925 ::require(info
->get("Fname", &fname
));
2926 if(!ctx
.m_currentSection
->contains(fname
)){
2927 ctx
.reportError("Mandatory parameter %s missing from section "
2928 "[%s] starting at line: %d",
2929 fname
, ctx
.fname
, ctx
.m_sectionLineno
);
2938 * Connection rule: Fix node id
2940 * Transform a string "NodeidX" (e.g. "uppsala.32")
2941 * into a Uint32 "NodeIdX" (e.g. 32) and a string "SystemX" (e.g. "uppsala").
2943 static bool fixNodeId(InitConfigFileParser::Context
& ctx
, const char * data
)
2945 char buf
[] = "NodeIdX"; buf
[6] = data
[sizeof("NodeI")];
2946 char sysbuf
[] = "SystemX"; sysbuf
[6] = data
[sizeof("NodeI")];
2948 if(!ctx
.m_currentSection
->get(buf
, &nodeId
))
2950 ctx
.reportError("Mandatory parameter %s missing from section"
2951 "[%s] starting at line: %d",
2952 buf
, ctx
.fname
, ctx
.m_sectionLineno
);
2956 char tmpLine
[MAX_LINE_LENGTH
];
2957 strncpy(tmpLine
, nodeId
, MAX_LINE_LENGTH
);
2958 char* token1
= strtok(tmpLine
, ".");
2959 char* token2
= strtok(NULL
, ".");
2964 ctx
.reportError("Value for mandatory parameter %s missing from section "
2965 "[%s] starting at line: %d",
2966 buf
, ctx
.fname
, ctx
.m_sectionLineno
);
2969 if (token2
== NULL
) { // Only a number given
2972 id
= strtol(token1
, &p
, 10);
2973 if (errno
!= 0 || id
<= 0x0 || id
> MAX_NODES
)
2975 ctx
.reportError("Illegal value for mandatory parameter %s from section "
2976 "[%s] starting at line: %d",
2977 buf
, ctx
.fname
, ctx
.m_sectionLineno
);
2980 require(ctx
.m_currentSection
->put(buf
, id
, true));
2981 } else { // A pair given (e.g. "uppsala.32")
2984 id
= strtol(token2
, &p
, 10);
2985 if (errno
!= 0 || id
<= 0x0 || id
> MAX_NODES
)
2987 ctx
.reportError("Illegal value for mandatory parameter %s from section "
2988 "[%s] starting at line: %d",
2989 buf
, ctx
.fname
, ctx
.m_sectionLineno
);
2992 require(ctx
.m_currentSection
->put(buf
, id
, true));
2993 require(ctx
.m_currentSection
->put(sysbuf
, token1
));
2999 * Connection rule: Fix hostname
3001 * Unless Hostname is not already specified, do steps:
3002 * -# Via Connection's NodeId lookup Node
3003 * -# Via Node's ExecuteOnComputer lookup Hostname
3004 * -# Add HostName to Connection
3007 fixHostname(InitConfigFileParser::Context
& ctx
, const char * data
){
3009 char buf
[] = "NodeIdX"; buf
[6] = data
[sizeof("HostNam")];
3010 char sysbuf
[] = "SystemX"; sysbuf
[6] = data
[sizeof("HostNam")];
3012 if(!ctx
.m_currentSection
->contains(data
)){
3014 require(ctx
.m_currentSection
->get(buf
, &id
));
3016 const Properties
* node
;
3017 if(!ctx
.m_config
->get("Node", id
, &node
))
3019 ctx
.reportError("Unknown node: \"%d\" specified in connection "
3020 "[%s] starting at line: %d",
3021 id
, ctx
.fname
, ctx
.m_sectionLineno
);
3025 const char * hostname
;
3026 require(node
->get("HostName", &hostname
));
3027 require(ctx
.m_currentSection
->put(data
, hostname
));
3033 * Connection rule: Fix port number (using a port number adder)
3036 fixPortNumber(InitConfigFileParser::Context
& ctx
, const char * data
){
3038 DBUG_ENTER("fixPortNumber");
3041 const char *hostName1
;
3042 const char *hostName2
;
3043 require(ctx
.m_currentSection
->get("NodeId1", &id1
));
3044 require(ctx
.m_currentSection
->get("NodeId2", &id2
));
3045 require(ctx
.m_currentSection
->get("HostName1", &hostName1
));
3046 require(ctx
.m_currentSection
->get("HostName2", &hostName2
));
3047 DBUG_PRINT("info",("NodeId1=%d HostName1=\"%s\"",id1
,hostName1
));
3048 DBUG_PRINT("info",("NodeId2=%d HostName2=\"%s\"",id2
,hostName2
));
3050 const Properties
*node1
, *node2
;
3051 require(ctx
.m_config
->get("Node", id1
, &node1
));
3052 require(ctx
.m_config
->get("Node", id2
, &node2
));
3054 const char *type1
, *type2
;
3055 require(node1
->get("Type", &type1
));
3056 require(node2
->get("Type", &type2
));
3058 /* add NodeIdServer info */
3060 Uint32 nodeIdServer
= id1
< id2
? id1
: id2
;
3061 if(strcmp(type1
, API_TOKEN
) == 0 || strcmp(type2
, MGM_TOKEN
) == 0)
3063 else if(strcmp(type2
, API_TOKEN
) == 0 || strcmp(type1
, MGM_TOKEN
) == 0)
3065 ctx
.m_currentSection
->put("NodeIdServer", nodeIdServer
);
3067 if (id2
== nodeIdServer
) {
3069 const char *tmp
= hostName1
;
3070 hostName1
= hostName2
;
3079 const Properties
*tmp
= node1
;
3084 const char *tmp
= type1
;
3091 BaseString
hostname(hostName1
);
3093 if (hostname
.c_str()[0] == 0) {
3094 ctx
.reportError("Hostname required on nodeid %d since it will "
3095 "act as server.", id1
);
3100 if(strcmp(type1
, MGM_TOKEN
)==0)
3101 node1
->get("PortNumber",&port
);
3102 else if(strcmp(type2
, MGM_TOKEN
)==0)
3103 node2
->get("PortNumber",&port
);
3106 !node1
->get("ServerPort", &port
) &&
3107 !ctx
.m_userProperties
.get("ServerPort_", id1
, &port
))
3111 * If the connection doesn't involve an mgm server,
3112 * and a default port number has been set, behave the old
3113 * way of allocating port numbers for transporters.
3115 if(ctx
.m_userDefaults
&& ctx
.m_userDefaults
->get("PortNumber", &base
))
3119 BaseString
server_port_adder(hostname
);
3120 server_port_adder
.append("_ServerPortAdder");
3121 ctx
.m_userProperties
.get(server_port_adder
.c_str(), &adder
);
3122 ctx
.m_userProperties
.put(server_port_adder
.c_str(), adder
+1, true);
3125 if (!ctx
.m_userProperties
.get("ServerPortBase", &base
)){
3126 if(!(ctx
.m_userDefaults
&&
3127 ctx
.m_userDefaults
->get("PortNumber", &base
)) &&
3128 !ctx
.m_systemDefaults
->get("PortNumber", &base
)) {
3129 base
= strtoll(NDB_TCP_BASE_PORT
,0,0);
3131 ctx
.m_userProperties
.put("ServerPortBase", base
);
3135 ctx
.m_userProperties
.put("ServerPort_", id1
, port
);
3139 if(ctx
.m_currentSection
->contains("PortNumber")) {
3140 ndbout
<< "PortNumber should no longer be specificied "
3141 << "per connection, please remove from config. "
3142 << "Will be changed to " << port
<< endl
;
3143 ctx
.m_currentSection
->put("PortNumber", port
, true);
3147 ctx
.m_currentSection
->put("PortNumber", port
);
3150 DBUG_PRINT("info", ("connection %d-%d port %d host %s",
3151 id1
, id2
, port
, hostname
.c_str()));
3157 fixShmUniqueId(InitConfigFileParser::Context
& ctx
, const char * data
)
3159 DBUG_ENTER("fixShmUniqueId");
3161 ctx
.m_userProperties
.get(ctx
.fname
, &nodes
);
3162 if (nodes
== 1) // first management server
3164 Uint32 portno
= atoi(NDB_PORT
);
3165 ctx
.m_currentSection
->get("PortNumber", &portno
);
3166 ctx
.m_userProperties
.put("ShmUniqueId", portno
);
3173 fixShmKey(InitConfigFileParser::Context
& ctx
, const char *)
3175 DBUG_ENTER("fixShmKey");
3177 static int last_signum
= -1;
3179 if(!ctx
.m_currentSection
->get("Signum", &signum
))
3181 signum
= OPT_NDB_SHM_SIGNUM_DEFAULT
;
3184 ctx
.reportError("Unable to set default parameter for [SHM]Signum"
3185 " please specify [SHM DEFAULT]Signum");
3188 ctx
.m_currentSection
->put("Signum", signum
);
3189 DBUG_PRINT("info",("Added Signum=%u", signum
));
3191 if ( last_signum
!= (int)signum
&& last_signum
>= 0 )
3193 ctx
.reportError("All shared memory transporters must have same [SHM]Signum defined."
3194 " Use [SHM DEFAULT]Signum");
3197 last_signum
= (int)signum
;
3200 Uint32 id1
= 0, id2
= 0, key
= 0;
3201 require(ctx
.m_currentSection
->get("NodeId1", &id1
));
3202 require(ctx
.m_currentSection
->get("NodeId2", &id2
));
3203 if(!ctx
.m_currentSection
->get("ShmKey", &key
))
3205 require(ctx
.m_userProperties
.get("ShmUniqueId", &key
));
3206 key
= key
<< 16 | (id1
> id2
? id1
<< 8 | id2
: id2
<< 8 | id1
);
3207 ctx
.m_currentSection
->put("ShmKey", key
);
3208 DBUG_PRINT("info",("Added ShmKey=0x%x", key
));
3215 * DB Node rule: Check various constraints
3218 checkDbConstraints(InitConfigFileParser::Context
& ctx
, const char *){
3220 Uint32 t1
= 0, t2
= 0;
3221 ctx
.m_currentSection
->get("MaxNoOfConcurrentOperations", &t1
);
3222 ctx
.m_currentSection
->get("MaxNoOfConcurrentTransactions", &t2
);
3225 ctx
.reportError("MaxNoOfConcurrentOperations must be greater than "
3226 "MaxNoOfConcurrentTransactions - [%s] starting at line: %d",
3227 ctx
.fname
, ctx
.m_sectionLineno
);
3231 Uint32 replicas
= 0, otherReplicas
;
3232 ctx
.m_currentSection
->get("NoOfReplicas", &replicas
);
3233 if(ctx
.m_userProperties
.get("NoOfReplicas", &otherReplicas
)){
3234 if(replicas
!= otherReplicas
){
3235 ctx
.reportError("NoOfReplicas defined differently on different nodes"
3236 " - [%s] starting at line: %d",
3237 ctx
.fname
, ctx
.m_sectionLineno
);
3241 ctx
.m_userProperties
.put("NoOfReplicas", replicas
);
3245 * In kernel, will calculate the MaxNoOfMeataTables use the following sum:
3246 * Uint32 noOfMetaTables = noOfTables + noOfOrderedIndexes +
3247 * noOfUniqueHashIndexes + 2
3248 * 2 is the number of the SysTables.
3249 * So must check that the sum does't exceed the max value of Uint32.
3251 Uint32 noOfTables
= 0,
3252 noOfOrderedIndexes
= 0,
3253 noOfUniqueHashIndexes
= 0;
3254 ctx
.m_currentSection
->get("MaxNoOfTables", &noOfTables
);
3255 ctx
.m_currentSection
->get("MaxNoOfOrderedIndexes", &noOfOrderedIndexes
);
3256 ctx
.m_currentSection
->get("MaxNoOfUniqueHashIndexes", &noOfUniqueHashIndexes
);
3258 Uint64 sum
= (Uint64
)noOfTables
+ noOfOrderedIndexes
+ noOfUniqueHashIndexes
;
3260 if (sum
> ((Uint32
)~0 - 2)) {
3261 ctx
.reportError("The sum of MaxNoOfTables, MaxNoOfOrderedIndexes and"
3262 " MaxNoOfUniqueHashIndexes must not exceed %u - [%s]"
3263 " starting at line: %d",
3264 ((Uint32
)~0 - 2), ctx
.fname
, ctx
.m_sectionLineno
);
3272 * Connection rule: Check varius constraints
3275 checkConnectionConstraints(InitConfigFileParser::Context
& ctx
, const char *){
3277 Uint32 id1
= 0, id2
= 0;
3278 ctx
.m_currentSection
->get("NodeId1", &id1
);
3279 ctx
.m_currentSection
->get("NodeId2", &id2
);
3282 ctx
.reportError("Illegal connection from node to itself"
3283 " - [%s] starting at line: %d",
3284 ctx
.fname
, ctx
.m_sectionLineno
);
3288 const Properties
* node1
;
3289 if(!ctx
.m_config
->get("Node", id1
, &node1
)){
3290 ctx
.reportError("Connection refering to undefined node: %d"
3291 " - [%s] starting at line: %d",
3292 id1
, ctx
.fname
, ctx
.m_sectionLineno
);
3296 const Properties
* node2
;
3297 if(!ctx
.m_config
->get("Node", id2
, &node2
)){
3298 ctx
.reportError("Connection refering to undefined node: %d"
3299 " - [%s] starting at line: %d",
3300 id2
, ctx
.fname
, ctx
.m_sectionLineno
);
3306 require(node1
->get("Type", &type1
));
3307 require(node2
->get("Type", &type2
));
3310 * Report error if the following are true
3311 * -# None of the nodes is of type DB
3312 * -# Not both of them are MGMs
3314 if((strcmp(type1
, DB_TOKEN
) != 0 && strcmp(type2
, DB_TOKEN
) != 0) &&
3315 !(strcmp(type1
, MGM_TOKEN
) == 0 && strcmp(type2
, MGM_TOKEN
) == 0))
3317 ctx
.reportError("Invalid connection between node %d (%s) and node %d (%s)"
3318 " - [%s] starting at line: %d",
3319 id1
, type1
, id2
, type2
,
3320 ctx
.fname
, ctx
.m_sectionLineno
);
3328 checkTCPConstraints(InitConfigFileParser::Context
& ctx
, const char * data
){
3331 struct in_addr addr
;
3332 if(ctx
.m_currentSection
->get(data
, &host
) && strlen(host
) &&
3333 Ndb_getInAddr(&addr
, host
)){
3334 ctx
.reportError("Unable to lookup/illegal hostname %s"
3335 " - [%s] starting at line: %d",
3336 host
, ctx
.fname
, ctx
.m_sectionLineno
);
3344 transform(InitConfigFileParser::Context
& ctx
,
3346 const char * oldName
,
3347 const char * newName
,
3348 double add
, double mul
){
3350 if(ctx
.m_currentSection
->contains(newName
)){
3351 ctx
.reportError("Both %s and %s specified"
3352 " - [%s] starting at line: %d",
3354 ctx
.fname
, ctx
.m_sectionLineno
);
3358 PropertiesType oldType
;
3359 require(ctx
.m_currentSection
->getTypeOf(oldName
, &oldType
));
3360 ConfigInfo::Type newType
= ctx
.m_info
->getType(ctx
.m_currentInfo
, newName
);
3362 if(!((oldType
== PropertiesType_Uint32
|| oldType
== PropertiesType_Uint64
)
3363 && (newType
== ConfigInfo::CI_INT
|| newType
== ConfigInfo::CI_INT64
|| newType
== ConfigInfo::CI_BOOL
))){
3364 ndbout
<< "oldType: " << (int)oldType
<< ", newType: " << (int)newType
<< endl
;
3365 ctx
.reportError("Unable to handle type conversion w.r.t deprication %s %s"
3366 "- [%s] starting at line: %d",
3368 ctx
.fname
, ctx
.m_sectionLineno
);
3372 require(ctx
.m_currentSection
->get(oldName
, &oldVal
));
3374 Uint64 newVal
= (Uint64
)((Int64
)oldVal
* mul
+ add
);
3375 if(!ctx
.m_info
->verify(ctx
.m_currentInfo
, newName
, newVal
)){
3376 ctx
.reportError("Unable to handle deprication, new value not within bounds"
3377 "%s %s - [%s] starting at line: %d",
3379 ctx
.fname
, ctx
.m_sectionLineno
);
3383 if(newType
== ConfigInfo::CI_INT
|| newType
== ConfigInfo::CI_BOOL
){
3384 require(dst
.put(newName
, (Uint32
)newVal
));
3385 } else if(newType
== ConfigInfo::CI_INT64
) {
3386 require(dst
.put64(newName
, newVal
));
3392 fixDepricated(InitConfigFileParser::Context
& ctx
, const char * data
){
3395 * Transform old values to new values
3396 * Transform new values to old values (backward compatible)
3398 Properties
tmp(true);
3399 Properties::Iterator
it(ctx
.m_currentSection
);
3400 for (name
= it
.first(); name
!= NULL
; name
= it
.next()) {
3401 const DepricationTransform
* p
= &f_deprication
[0];
3402 while(p
->m_section
!= 0){
3403 if(strcmp(p
->m_section
, ctx
.fname
) == 0){
3404 double mul
= p
->m_mul
;
3405 double add
= p
->m_add
;
3406 if(strcasecmp(name
, p
->m_oldName
) == 0){
3407 if(!transform(ctx
, tmp
, name
, p
->m_newName
, add
, mul
)){
3410 } else if(strcasecmp(name
, p
->m_newName
) == 0) {
3411 if(!transform(ctx
, tmp
, name
, p
->m_oldName
, -add
/mul
,1.0/mul
)){
3420 Properties::Iterator
it2(&tmp
);
3421 for (name
= it2
.first(); name
!= NULL
; name
= it2
.next()) {
3422 PropertiesType type
;
3423 require(tmp
.getTypeOf(name
, &type
));
3425 case PropertiesType_Uint32
:{
3427 require(tmp
.get(name
, &val
));
3428 ::require(ctx
.m_currentSection
->put(name
, val
));
3431 case PropertiesType_char
:{
3433 require(tmp
.get(name
, &val
));
3434 ::require(ctx
.m_currentSection
->put(name
, val
));
3437 case PropertiesType_Uint64
:{
3439 require(tmp
.get(name
, &val
));
3440 ::require(ctx
.m_currentSection
->put64(name
, val
));
3443 case PropertiesType_Properties
:
3451 extern int g_print_full_config
;
3454 saveInConfigValues(InitConfigFileParser::Context
& ctx
, const char * data
){
3455 const Properties
* sec
;
3456 if(!ctx
.m_currentInfo
->get(ctx
.fname
, &sec
)){
3462 const char *secName
;
3463 Uint32 id
, status
, typeVal
;
3464 require(sec
->get("Fname", &secName
));
3465 require(sec
->get("Id", &id
));
3466 require(sec
->get("Status", &status
));
3467 require(sec
->get("SectionType", &typeVal
));
3469 if(id
== KEY_INTERNAL
|| status
== ConfigInfo::CI_INTERNAL
){
3470 ndbout_c("skipping section %s", ctx
.fname
);
3474 if (g_print_full_config
)
3476 const char *alias
= ConfigInfo::nameToAlias(ctx
.fname
);
3477 printf("[%s]\n", alias
? alias
: ctx
.fname
);
3481 ctx
.m_userProperties
.get("$Section", id
, &no
);
3482 ctx
.m_userProperties
.put("$Section", id
, no
+1, true);
3484 ctx
.m_configValues
.openSection(id
, no
);
3485 ctx
.m_configValues
.put(CFG_TYPE_OF_SECTION
, typeVal
);
3487 Properties::Iterator
it(ctx
.m_currentSection
);
3488 for (const char* n
= it
.first(); n
!= NULL
; n
= it
.next()) {
3489 const Properties
* info
;
3490 if(!ctx
.m_currentInfo
->get(n
, &info
))
3494 info
->get("Id", &id
);
3496 if(id
== KEY_INTERNAL
)
3500 PropertiesType type
;
3501 require(ctx
.m_currentSection
->getTypeOf(n
, &type
));
3503 case PropertiesType_Uint32
:{
3505 require(ctx
.m_currentSection
->get(n
, &val
));
3506 ok
= ctx
.m_configValues
.put(id
, val
);
3507 if (g_print_full_config
)
3508 printf("%s=%u\n", n
, val
);
3511 case PropertiesType_Uint64
:{
3513 require(ctx
.m_currentSection
->get(n
, &val
));
3514 ok
= ctx
.m_configValues
.put64(id
, val
);
3515 if (g_print_full_config
)
3516 printf("%s=%llu\n", n
, val
);
3519 case PropertiesType_char
:{
3521 require(ctx
.m_currentSection
->get(n
, &val
));
3522 ok
= ctx
.m_configValues
.put(id
, val
);
3523 if (g_print_full_config
)
3524 printf("%s=%s\n", n
, val
);
3532 ctx
.m_configValues
.closeSection();
3538 sanity_checks(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
3539 struct InitConfigFileParser::Context
&ctx
,
3540 const char * rule_data
)
3542 Uint32 db_nodes
= 0;
3543 Uint32 mgm_nodes
= 0;
3544 Uint32 api_nodes
= 0;
3545 if (!ctx
.m_userProperties
.get("DB", &db_nodes
)) {
3546 ctx
.reportError("At least one database node (ndbd) should be defined in config file");
3549 if (!ctx
.m_userProperties
.get("MGM", &mgm_nodes
)) {
3550 ctx
.reportError("At least one management server node (ndb_mgmd) should be defined in config file");
3553 if (!ctx
.m_userProperties
.get("API", &api_nodes
)) {
3554 ctx
.reportError("At least one application node (for the mysqld) should be defined in config file");
3561 add_a_connection(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
3562 struct InitConfigFileParser::Context
&ctx
,
3563 Uint32 nodeId1
, Uint32 nodeId2
, bool use_shm
)
3565 ConfigInfo::ConfigRuleSection s
;
3566 const char *hostname1
= 0, *hostname2
= 0;
3567 const Properties
*tmp
;
3569 require(ctx
.m_config
->get("Node", nodeId1
, &tmp
));
3570 tmp
->get("HostName", &hostname1
);
3572 require(ctx
.m_config
->get("Node", nodeId2
, &tmp
));
3573 tmp
->get("HostName", &hostname2
);
3576 s
.m_sectionData
= new Properties(true);
3577 BaseString::snprintf(buf
, sizeof(buf
), "%u", nodeId1
);
3578 s
.m_sectionData
->put("NodeId1", buf
);
3579 BaseString::snprintf(buf
, sizeof(buf
), "%u", nodeId2
);
3580 s
.m_sectionData
->put("NodeId2", buf
);
3583 hostname1
&& hostname1
[0] &&
3584 hostname2
&& hostname2
[0] &&
3585 strcmp(hostname1
,hostname2
) == 0)
3587 s
.m_sectionType
= BaseString("SHM");
3588 DBUG_PRINT("info",("adding SHM connection %d %d",nodeId1
,nodeId2
));
3592 s
.m_sectionType
= BaseString("TCP");
3593 DBUG_PRINT("info",("adding TCP connection %d %d",nodeId1
,nodeId2
));
3596 sections
.push_back(s
);
3600 add_node_connections(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
3601 struct InitConfigFileParser::Context
&ctx
,
3602 const char * rule_data
)
3604 DBUG_ENTER("add_node_connections");
3606 Properties
* props
= ctx
.m_config
;
3607 Properties
p_connections(true);
3608 Properties
p_connections2(true);
3611 const Properties
* tmp
;
3612 Uint32 nodeId1
, nodeId2
;
3614 if(!props
->get("Connection", i
, &tmp
)) break;
3616 if(!tmp
->get("NodeId1", &nodeId1
)) continue;
3617 p_connections
.put("", nodeId1
, nodeId1
);
3618 if(!tmp
->get("NodeId2", &nodeId2
)) continue;
3619 p_connections
.put("", nodeId2
, nodeId2
);
3621 p_connections2
.put("", nodeId1
+ nodeId2
<<16, nodeId1
);
3622 p_connections2
.put("", nodeId2
+ nodeId1
<<16, nodeId2
);
3626 ctx
.m_userProperties
.get("NoOfNodes", &nNodes
);
3628 Properties
p_db_nodes(true);
3629 Properties
p_api_nodes(true);
3630 Properties
p_mgm_nodes(true);
3632 Uint32 i_db
= 0, i_api
= 0, i_mgm
= 0, n
;
3633 for (i
= 0, n
= 0; n
< nNodes
; i
++){
3634 const Properties
* tmp
;
3635 if(!props
->get("Node", i
, &tmp
)) continue;
3639 if(!tmp
->get("Type", &type
)) continue;
3641 if (strcmp(type
,DB_TOKEN
) == 0)
3642 p_db_nodes
.put("", i_db
++, i
);
3643 else if (strcmp(type
,API_TOKEN
) == 0)
3644 p_api_nodes
.put("", i_api
++, i
);
3645 else if (strcmp(type
,MGM_TOKEN
) == 0)
3646 p_mgm_nodes
.put("", i_mgm
++, i
);
3649 Uint32 nodeId1
, nodeId2
, dummy
;
3651 for (i
= 0; p_db_nodes
.get("", i
, &nodeId1
); i
++){
3652 for (Uint32 j
= i
+1;; j
++){
3653 if(!p_db_nodes
.get("", j
, &nodeId2
)) break;
3654 if(!p_connections2
.get("", nodeId1
+nodeId2
<<16, &dummy
)) {
3655 add_a_connection(sections
,ctx
,nodeId1
,nodeId2
,opt_ndb_shm
);
3660 for (i
= 0; p_api_nodes
.get("", i
, &nodeId1
); i
++){
3661 if(!p_connections
.get("", nodeId1
, &dummy
)) {
3662 for (Uint32 j
= 0;; j
++){
3663 if(!p_db_nodes
.get("", j
, &nodeId2
)) break;
3664 add_a_connection(sections
,ctx
,nodeId1
,nodeId2
,opt_ndb_shm
);
3669 for (i
= 0; p_mgm_nodes
.get("", i
, &nodeId1
); i
++){
3670 if(!p_connections
.get("", nodeId1
, &dummy
)) {
3671 for (Uint32 j
= 0;; j
++){
3672 if(!p_db_nodes
.get("", j
, &nodeId2
)) break;
3673 add_a_connection(sections
,ctx
,nodeId1
,nodeId2
,0);
3681 static bool set_connection_priorities(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
3682 struct InitConfigFileParser::Context
&ctx
,
3683 const char * rule_data
)
3685 DBUG_ENTER("set_connection_priorities");
3690 check_node_vs_replicas(Vector
<ConfigInfo::ConfigRuleSection
>§ions
,
3691 struct InitConfigFileParser::Context
&ctx
,
3692 const char * rule_data
)
3696 Uint32 db_host_count
= 0;
3697 bool with_arbitration_rank
= false;
3698 ctx
.m_userProperties
.get(DB_TOKEN
, &db_nodes
);
3699 ctx
.m_userProperties
.get("NoOfReplicas", &replicas
);
3700 if((db_nodes
% replicas
) != 0){
3701 ctx
.reportError("Invalid no of db nodes wrt no of replicas.\n"
3702 "No of nodes must be dividable with no or replicas");
3705 // check that node groups and arbitrators are ok
3706 // just issue warning if not
3708 Properties
* props
= ctx
.m_config
;
3709 Properties
p_db_hosts(true); // store hosts which db nodes run on
3710 Properties
p_arbitrators(true); // store hosts which arbitrators run on
3711 // arbitrator should not run together with db node on same host
3712 Uint32 i
, n
, group
= 0, i_group
= 0;
3714 BaseString node_group_warning
, arbitration_warning
;
3715 const char *arbit_warn_fmt
=
3716 "\n arbitrator with id %d and db node with id %d on same host %s";
3717 const char *arbit_warn_fmt2
=
3718 "\n arbitrator with id %d has no hostname specified";
3720 ctx
.m_userProperties
.get("NoOfNodes", &n_nodes
);
3721 for (i
= 0, n
= 0; n
< n_nodes
; i
++){
3722 const Properties
* tmp
;
3723 if(!props
->get("Node", i
, &tmp
)) continue;
3727 if(!tmp
->get("Type", &type
)) continue;
3729 const char* host
= 0;
3730 tmp
->get("HostName", &host
);
3732 if (strcmp(type
,DB_TOKEN
) == 0)
3736 if (!p_db_hosts
.get(host
,&ii
))
3738 p_db_hosts
.put(host
,i
);
3739 if (p_arbitrators
.get(host
,&ii
))
3741 arbitration_warning
.appfmt(arbit_warn_fmt
, ii
, i
, host
);
3742 p_arbitrators
.remove(host
); // only one warning per db node
3747 BaseString str
, str2
;
3748 str
.assfmt("#group%d_",group
);
3749 p_db_hosts
.put(str
.c_str(),i_group
,host
);
3750 str2
.assfmt("##group%d_",group
);
3751 p_db_hosts
.put(str2
.c_str(),i_group
,i
);
3752 for (j
= 0; j
< i_group
; j
++)
3754 const char *other_host
;
3755 p_db_hosts
.get(str
.c_str(),j
,&other_host
);
3756 if (strcmp(host
,other_host
) == 0) {
3757 unsigned int other_i
, c
= 0;
3758 p_db_hosts
.get(str2
.c_str(),j
,&other_i
);
3759 p_db_hosts
.get(str
.c_str(),&c
);
3760 if (c
== 0) // first warning in this node group
3761 node_group_warning
.appfmt(" Node group %d", group
);
3763 p_db_hosts
.put(str
.c_str(),c
);
3764 node_group_warning
.appfmt(",\n db node with id %d and id %d "
3765 "on same host %s", other_i
, i
, host
);
3769 DBUG_ASSERT(i_group
<= replicas
);
3770 if (i_group
== replicas
)
3773 p_db_hosts
.get(str
.c_str(),&c
);
3774 if (c
+1 == (1u << (replicas
-1))) // all nodes on same machine
3775 node_group_warning
.append(".\n Host failure will "
3776 "cause complete cluster shutdown.");
3778 node_group_warning
.append(".\n Host failure may "
3779 "cause complete cluster shutdown.");
3785 else if (strcmp(type
,API_TOKEN
) == 0 ||
3786 strcmp(type
,MGM_TOKEN
) == 0)
3789 if(tmp
->get("ArbitrationRank", &rank
) && rank
> 0)
3791 with_arbitration_rank
= true; //check whether MGM or API node configured with rank >0
3792 if(host
&& host
[0] != 0)
3795 p_arbitrators
.put(host
,i
);
3796 if (p_db_hosts
.get(host
,&ii
))
3798 arbitration_warning
.appfmt(arbit_warn_fmt
, i
, ii
, host
);
3803 arbitration_warning
.appfmt(arbit_warn_fmt2
, i
);
3808 if (db_host_count
> 1 && node_group_warning
.length() > 0)
3809 ctx
.reportWarning("Cluster configuration warning:\n%s",node_group_warning
.c_str());
3810 if (!with_arbitration_rank
)
3812 ctx
.reportWarning("Cluster configuration warning:"
3813 "\n Neither %s nor %s nodes are configured with arbitrator,"
3814 "\n may cause complete cluster shutdown in case of host failure.",
3815 MGM_TOKEN
, API_TOKEN
);
3817 if (db_host_count
> 1 && arbitration_warning
.length() > 0)
3818 ctx
.reportWarning("Cluster configuration warning:%s%s",arbitration_warning
.c_str(),
3819 "\n Running arbitrator on the same host as a database node may"
3820 "\n cause complete cluster shutdown in case of host failure.");
3825 template class Vector
<ConfigInfo::ConfigRuleSection
>;
3826 #endif /* NDB_MGMAPI */