ConfigInfo.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:93k
源码类别:

MySQL数据库

开发平台:

Visual C++

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