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

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 <getarg.h>
  15. #include <BaseString.hpp>
  16. #include <Parser.hpp>
  17. #include <NdbOut.hpp>
  18. #include <Properties.hpp>
  19. #include <NdbAutoPtr.hpp>
  20. #include "run-test.hpp"
  21. #include <SysLogHandler.hpp>
  22. #include <FileLogHandler.hpp>
  23. #include <mgmapi.h>
  24. #include "CpcClient.hpp"
  25. /** Global variables */
  26. static const char progname[] = "ndb_atrt";
  27. static const char * g_gather_progname = "atrt-gather-result.sh";
  28. static const char * g_analyze_progname = "atrt-analyze-result.sh";
  29. static const char * g_clear_progname = "atrt-clear-result.sh";
  30. static const char * g_setup_progname = "atrt-setup.sh";
  31. static const char * g_setup_path = 0;
  32. static const char * g_process_config_filename = "d.txt";
  33. static const char * g_log_filename = 0;
  34. static const char * g_test_case_filename = 0;
  35. static const char * g_report_filename = 0;
  36. static const char * g_default_user = 0;
  37. static const char * g_default_base_dir = 0;
  38. static int          g_default_base_port = 0;
  39. static int          g_mysqld_use_base = 1;
  40. static int g_report = 0;
  41. static int g_verbosity = 0;
  42. static FILE * g_report_file = 0;
  43. static FILE * g_test_case_file = stdin;
  44. Logger g_logger;
  45. atrt_config g_config;
  46. static int g_mode_bench = 0;
  47. static int g_mode_regression = 0;
  48. static int g_mode_interactive = 0;
  49. static int g_mode = 0;
  50. static
  51. struct getargs args[] = {
  52.   { "process-config", 0, arg_string, &g_process_config_filename, 0, 0 },
  53.   { "setup-path", 0, arg_string, &g_setup_path, 0, 0 },
  54.   { 0, 'v', arg_counter, &g_verbosity, 0, 0 },
  55.   { "log-file", 0, arg_string, &g_log_filename, 0, 0 },
  56.   { "testcase-file", 'f', arg_string, &g_test_case_filename, 0, 0 },
  57.   { 0, 'R', arg_flag, &g_report, 0, 0 },
  58.   { "report-file", 0, arg_string, &g_report_filename, 0, 0 },
  59.   { "interactive", 'i', arg_flag, &g_mode_interactive, 0, 0 },
  60.   { "regression", 'r', arg_flag, &g_mode_regression, 0, 0 },
  61.   { "bench", 'b', arg_flag, &g_mode_bench, 0, 0 },
  62. };
  63. const int arg_count = 10;
  64. int
  65. main(int argc, const char ** argv){
  66.   ndb_init();
  67.   
  68.   bool restart = true;
  69.   int lineno = 1;
  70.   int test_no = 1; 
  71.   const int p_ndb     = atrt_process::NDB_MGM | atrt_process::NDB_DB;
  72.   const int p_servers = atrt_process::MYSQL_SERVER | atrt_process::NDB_REP;
  73.   const int p_clients = atrt_process::MYSQL_CLIENT | atrt_process::NDB_API;
  74.   
  75.   g_logger.setCategory(progname);
  76.   g_logger.enable(Logger::LL_ALL);
  77.   g_logger.createConsoleHandler();
  78.   
  79.   if(!parse_args(argc, argv))
  80.     goto end;
  81.   g_logger.info("Starting...");
  82.   if(!setup_config(g_config))
  83.     goto end;
  84.   
  85.   g_logger.info("Connecting to hosts");
  86.   if(!connect_hosts(g_config))
  87.     goto end;
  88.   if(!setup_hosts(g_config))
  89.     goto end;
  90.   /**
  91.    * Main loop
  92.    */
  93.   while(!feof(g_test_case_file)){
  94.     /**
  95.      * Do we need to restart ndb
  96.      */
  97.     if(restart){
  98.       g_logger.info("(Re)starting ndb processes");
  99.       if(!stop_processes(g_config, ~0))
  100. goto end;
  101.       if(!start_processes(g_config, atrt_process::NDB_MGM))
  102. goto end;
  103.       
  104.       if(!connect_ndb_mgm(g_config)){
  105. goto end;
  106.       }
  107.       
  108.       if(!start_processes(g_config, atrt_process::NDB_DB))
  109. goto end;
  110.       
  111.       if(!wait_ndb(g_config, NDB_MGM_NODE_STATUS_NOT_STARTED))
  112.         goto end;
  113.       
  114.       for(Uint32 i = 0; i<3; i++)      
  115.         if(wait_ndb(g_config, NDB_MGM_NODE_STATUS_STARTED))
  116.   goto started;
  117.       
  118.       goto end;
  119.       
  120.     started:
  121.       if(!start_processes(g_config, p_servers))
  122.         goto end;
  123.       g_logger.info("Ndb start completed");
  124.     }
  125.     
  126.     const int start_line = lineno;
  127.     atrt_testcase test_case;
  128.     if(!read_test_case(g_test_case_file, test_case, lineno))
  129.       goto end;
  130.     
  131.     g_logger.info("#%d - %s %s", 
  132.   test_no,
  133.   test_case.m_command.c_str(), test_case.m_args.c_str());
  134.     
  135.     // Assign processes to programs
  136.     if(!setup_test_case(g_config, test_case))
  137.       goto end;
  138.     
  139.     if(!start_processes(g_config, p_clients))
  140.       goto end;
  141.     int result = 0;
  142.     
  143.     const time_t start = time(0);
  144.     time_t now = start;
  145.     do {
  146.       if(!update_status(g_config, atrt_process::ALL))
  147. goto end;
  148.       int count = 0;
  149.       if((count = is_running(g_config, p_ndb)) != 2){
  150. result = ERR_NDB_FAILED;
  151. break;
  152.       }
  153.       if((count = is_running(g_config, p_servers)) != 2){
  154. result = ERR_SERVERS_FAILED;
  155. break;
  156.       }
  157.       if((count = is_running(g_config, p_clients)) == 0){
  158. break;
  159.       }
  160.       
  161.       now = time(0);
  162.       if(now  > (start + test_case.m_max_time)){
  163. result = ERR_MAX_TIME_ELAPSED;
  164. break;
  165.       }
  166.       sleep(1);
  167.     } while(true);
  168.     
  169.     const time_t elapsed = time(0) - start;
  170.    
  171.     if(!stop_processes(g_config, p_clients))
  172.       goto end;
  173.     
  174.     if(!gather_result(g_config, &result))
  175.       goto end;
  176.     
  177.     g_logger.info("#%d %s(%d)", 
  178.   test_no, 
  179.   (result == 0 ? "OK" : "FAILED"), result);
  180.     if(g_report_file != 0){
  181.       fprintf(g_report_file, "%s %s ; %d ; %d ; %ldn",
  182.       test_case.m_command.c_str(),
  183.       test_case.m_args.c_str(),
  184.       test_no, result, elapsed);
  185.       fflush(g_report_file);
  186.     }    
  187.     if(test_case.m_report || g_mode_bench || (g_mode_regression && result)){
  188.       BaseString tmp;
  189.       tmp.assfmt("result.%d", test_no);
  190.       if(rename("result", tmp.c_str()) != 0){
  191. g_logger.critical("Failed to rename %s as %s",
  192.   "result", tmp.c_str());
  193. goto end;
  194.       }
  195.     }
  196.     
  197.     if(g_mode_interactive && result){
  198.       g_logger.info
  199. ("Encountered failed test in interactive mode - terminating");
  200.       break;
  201.     }
  202.     if(result != 0){
  203.       restart = true;
  204.     } else {
  205.       restart = false;
  206.     }
  207.     test_no++;
  208.   }
  209.   
  210.  end:
  211.   if(g_report_file != 0){
  212.     fclose(g_report_file);
  213.     g_report_file = 0;
  214.   }
  215.   if(g_test_case_file != 0 && g_test_case_file != stdin){
  216.     fclose(g_test_case_file);
  217.     g_test_case_file = 0;
  218.   }
  219.   stop_processes(g_config, atrt_process::ALL);
  220.   return 0;
  221. }
  222. bool
  223. parse_args(int argc, const char** argv){
  224.   int optind = 0;
  225.   if(getarg(args, arg_count, argc, argv, &optind)) {
  226.     arg_printusage(args, arg_count, progname, "");
  227.     return false;
  228.   }
  229.   if(g_log_filename != 0){
  230.     g_logger.removeConsoleHandler();
  231.     g_logger.addHandler(new FileLogHandler(g_log_filename));
  232.   }
  233.   {
  234.     int tmp = Logger::LL_WARNING - g_verbosity;
  235.     tmp = (tmp < Logger::LL_DEBUG ? Logger::LL_DEBUG : tmp);
  236.     g_logger.disable(Logger::LL_ALL);
  237.     g_logger.enable(Logger::LL_ON);
  238.     g_logger.enable((Logger::LoggerLevel)tmp, Logger::LL_ALERT);
  239.   }
  240.   if(!g_process_config_filename){
  241.     g_logger.critical("Process config not specified!");
  242.     return false;
  243.   }
  244.   
  245.   if(!g_setup_path){
  246.     char buf[1024];
  247.     if(getcwd(buf, sizeof(buf))){
  248.       g_setup_path = strdup(buf);
  249.       g_logger.info("Setup path not specified, using %s", buf);
  250.     } else {
  251.       g_logger.critical("Setup path not specified!n");
  252.       return false;
  253.     }
  254.   }
  255.   
  256.   if(g_report & !g_report_filename){
  257.     g_report_filename = "report.txt";
  258.   }
  259.   if(g_report_filename){
  260.     g_report_file = fopen(g_report_filename, "w");
  261.     if(g_report_file == 0){
  262.       g_logger.critical("Unable to create report file: %s", g_report_filename);
  263.       return false;
  264.     }
  265.   }
  266.   if(g_test_case_filename){
  267.     g_test_case_file = fopen(g_test_case_filename, "r");
  268.     if(g_test_case_file == 0){
  269.       g_logger.critical("Unable to open file: %s", g_test_case_filename);
  270.       return false;
  271.     }
  272.   }
  273.   
  274.   int sum = g_mode_interactive + g_mode_regression + g_mode_bench;
  275.   if(sum == 0){
  276.     g_mode_interactive = 1;
  277.   }
  278.   if(sum > 1){
  279.     g_logger.critical
  280.       ("Only one of bench/regression/interactive can be specified");
  281.     return false;
  282.   }
  283.   
  284.   g_default_user = strdup(getenv("LOGNAME"));
  285.   return true;
  286. }
  287. static
  288. atrt_host *
  289. find(const BaseString& host, Vector<atrt_host> & hosts){
  290.   for(size_t i = 0; i<hosts.size(); i++){
  291.     if(hosts[i].m_hostname == host){
  292.       return &hosts[i];
  293.     }
  294.   }
  295.   return 0;
  296. }
  297. bool
  298. setup_config(atrt_config& config){
  299.   FILE * f = fopen(g_process_config_filename, "r");
  300.   if(!f){
  301.     g_logger.critical("Failed to open process config file: %s",
  302.       g_process_config_filename);
  303.     return false;
  304.   }
  305.   bool result = true;
  306.   int lineno = 0;
  307.   char buf[2048];
  308.   BaseString connect_string;
  309.   int mysql_port_offset = 0;
  310.   while(fgets(buf, 2048, f)){
  311.     lineno++;
  312.     BaseString tmp(buf);
  313.     tmp.trim(" tnr");
  314.     if(tmp.length() == 0 || tmp == "" || tmp.c_str()[0] == '#')
  315.       continue;
  316.     Vector<BaseString> split1;
  317.     if(tmp.split(split1, ":", 2) != 2){
  318.       g_logger.warning("Invalid line %d in %s - ignoring",
  319.        lineno, g_process_config_filename);
  320.       continue;
  321.     }
  322.     if(split1[0].trim() == "basedir"){
  323.       g_default_base_dir = strdup(split1[1].trim().c_str());
  324.       continue;
  325.     }
  326.     if(split1[0].trim() == "baseport"){
  327.       g_default_base_port = atoi(split1[1].trim().c_str());
  328.       continue;
  329.     }
  330.     if(split1[0].trim() == "user"){
  331.       g_default_user = strdup(split1[1].trim().c_str());
  332.       continue;
  333.     }
  334.     if(split1[0].trim() == "mysqld-use-base" && split1[1].trim() == "no"){
  335.       g_mysqld_use_base = 0;
  336.       continue;
  337.     }
  338.     Vector<BaseString> hosts;
  339.     if(split1[1].trim().split(hosts) <= 0){
  340.       g_logger.warning("Invalid line %d in %s - ignoring", 
  341.        lineno, g_process_config_filename);
  342.     }
  343.     // 1 - Check hosts
  344.     for(size_t i = 0; i<hosts.size(); i++){
  345.       Vector<BaseString> tmp;
  346.       hosts[i].split(tmp, ":");
  347.       BaseString hostname = tmp[0].trim();
  348.       BaseString base_dir;
  349.       if(tmp.size() >= 2)
  350.         base_dir = tmp[1];
  351.       else if(g_default_base_dir == 0){
  352. g_logger.critical("Basedir not specified...");
  353.         return false;
  354.       }
  355.       atrt_host * host_ptr;
  356.       if((host_ptr = find(hostname, config.m_hosts)) == 0){
  357. atrt_host host;
  358. host.m_index = config.m_hosts.size();
  359. host.m_cpcd = new SimpleCpcClient(hostname.c_str(), 1234);
  360. host.m_base_dir = (base_dir.empty() ? g_default_base_dir : base_dir);
  361. host.m_user = g_default_user;
  362. host.m_hostname = hostname.c_str();
  363. config.m_hosts.push_back(host);
  364.       } else {
  365.         if(!base_dir.empty() && (base_dir == host_ptr->m_base_dir)){
  366.           g_logger.critical("Inconsistent base dir definition for host %s"
  367.                             ", "%s" != "%s"", hostname.c_str(), 
  368.                             base_dir.c_str(), host_ptr->m_base_dir.c_str());
  369.           return false;
  370.         }
  371.       }
  372.     }
  373.     
  374.     for(size_t i = 0; i<hosts.size(); i++){
  375.       BaseString & tmp = hosts[i];
  376.       atrt_host * host = find(tmp, config.m_hosts);
  377.       BaseString & dir = host->m_base_dir;
  378.       const int index = config.m_processes.size() + 1;
  379.       atrt_process proc;
  380.       proc.m_index = index;
  381.       proc.m_host = host;
  382.       proc.m_proc.m_id = -1;
  383.       proc.m_proc.m_type = "temporary";
  384.       proc.m_proc.m_owner = "atrt";  
  385.       proc.m_proc.m_group = "group";    
  386.       proc.m_proc.m_cwd.assign(dir).append("/run/");
  387.       proc.m_proc.m_stdout = "log.out";
  388.       proc.m_proc.m_stderr = "2>&1";
  389.       proc.m_proc.m_runas = proc.m_host->m_user;
  390.       proc.m_proc.m_ulimit = "c:unlimited";
  391.       proc.m_proc.m_env.assfmt("MYSQL_BASE_DIR=%s", dir.c_str());
  392.       proc.m_proc.m_shutdown_options = "";
  393.       proc.m_hostname = proc.m_host->m_hostname;
  394.       proc.m_ndb_mgm_port = g_default_base_port;
  395.       if(split1[0] == "mgm"){
  396. proc.m_type = atrt_process::NDB_MGM;
  397. proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_mgmd");
  398. proc.m_proc.m_path.assign(dir).append("/libexec/ndb_mgmd");
  399. proc.m_proc.m_args = "--nodaemon -f config.ini";
  400. proc.m_proc.m_cwd.appfmt("%d.ndb_mgmd", index);
  401. connect_string.appfmt("host=%s:%d;", 
  402.       proc.m_hostname.c_str(), proc.m_ndb_mgm_port);
  403.       } else if(split1[0] == "ndb"){
  404. proc.m_type = atrt_process::NDB_DB;
  405. proc.m_proc.m_name.assfmt("%d-%s", index, "ndbd");
  406. proc.m_proc.m_path.assign(dir).append("/libexec/ndbd");
  407. proc.m_proc.m_args = "--initial --nodaemon -n";
  408. proc.m_proc.m_cwd.appfmt("%d.ndbd", index);
  409.       } else if(split1[0] == "mysqld"){
  410. proc.m_type = atrt_process::MYSQL_SERVER;
  411. proc.m_proc.m_name.assfmt("%d-%s", index, "mysqld");
  412. proc.m_proc.m_path.assign(dir).append("/libexec/mysqld");
  413. proc.m_proc.m_args = "--core-file --ndbcluster";
  414. proc.m_proc.m_cwd.appfmt("%d.mysqld", index);
  415. proc.m_proc.m_shutdown_options = "SIGKILL"; // not nice
  416.       } else if(split1[0] == "api"){
  417. proc.m_type = atrt_process::NDB_API;
  418. proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_api");
  419. proc.m_proc.m_path = "";
  420. proc.m_proc.m_args = "";
  421. proc.m_proc.m_cwd.appfmt("%d.ndb_api", index);
  422.       } else if(split1[0] == "mysql"){
  423.         proc.m_type = atrt_process::MYSQL_CLIENT;
  424.         proc.m_proc.m_name.assfmt("%d-%s", index, "mysql");
  425.         proc.m_proc.m_path = "";
  426.         proc.m_proc.m_args = "";
  427.         proc.m_proc.m_cwd.appfmt("%d.mysql", index);
  428.       } else {
  429. g_logger.critical("%s:%d: Unhandled process type: %s",
  430.   g_process_config_filename, lineno,
  431.   split1[0].c_str());
  432. result = false;
  433. goto end;
  434.       }
  435.       config.m_processes.push_back(proc);
  436.     }
  437.   }
  438.   // Setup connect string
  439.   for(size_t i = 0; i<config.m_processes.size(); i++){
  440.     config.m_processes[i].m_proc.m_env.appfmt(" NDB_CONNECTSTRING=%s", 
  441.       connect_string.c_str());
  442.   }
  443.   
  444.  end:
  445.   fclose(f);
  446.   return result;
  447. }
  448. bool
  449. connect_hosts(atrt_config& config){
  450.   for(size_t i = 0; i<config.m_hosts.size(); i++){
  451.     if(config.m_hosts[i].m_cpcd->connect() != 0){
  452.       g_logger.error("Unable to connect to cpc %s:%d",
  453.      config.m_hosts[i].m_cpcd->getHost(),
  454.      config.m_hosts[i].m_cpcd->getPort());
  455.       return false;
  456.     }
  457.     g_logger.debug("Connected to %s:%d",
  458.    config.m_hosts[i].m_cpcd->getHost(),
  459.    config.m_hosts[i].m_cpcd->getPort());
  460.   }
  461.   
  462.   return true;
  463. }
  464. bool
  465. connect_ndb_mgm(atrt_process & proc){
  466.   NdbMgmHandle handle = ndb_mgm_create_handle();
  467.   if(handle == 0){
  468.     g_logger.critical("Unable to create mgm handle");
  469.     return false;
  470.   }
  471.   BaseString tmp = proc.m_hostname;
  472.   tmp.appfmt(":%d", proc.m_ndb_mgm_port);
  473.   if (ndb_mgm_set_connectstring(handle,tmp.c_str()))
  474.   {
  475.     g_logger.critical("Unable to create parse connectstring");
  476.     return false;
  477.   }
  478.   if(ndb_mgm_connect(handle, 30, 1, 0) != -1)
  479.   {
  480.     proc.m_ndb_mgm_handle = handle;
  481.     return true;
  482.   }
  483.   g_logger.critical("Unable to connect to ndb mgm %s", tmp.c_str());
  484.   return false;
  485. }
  486. bool
  487. connect_ndb_mgm(atrt_config& config){
  488.   for(size_t i = 0; i<config.m_processes.size(); i++){
  489.     atrt_process & proc = config.m_processes[i];
  490.     if((proc.m_type & atrt_process::NDB_MGM) != 0){
  491.       if(!connect_ndb_mgm(proc)){
  492. return false;
  493.       }
  494.     }
  495.   }
  496.   
  497.   return true;
  498. }
  499. static int remap(int i){
  500.   if(i == NDB_MGM_NODE_STATUS_NO_CONTACT) return NDB_MGM_NODE_STATUS_UNKNOWN;
  501.   if(i == NDB_MGM_NODE_STATUS_UNKNOWN) return NDB_MGM_NODE_STATUS_NO_CONTACT;
  502.   return i;
  503. }
  504. bool
  505. wait_ndb(atrt_config& config, int goal){
  506.   goal = remap(goal);
  507.   /**
  508.    * Get mgm handle for cluster
  509.    */
  510.   NdbMgmHandle handle = 0;
  511.   for(size_t i = 0; i<config.m_processes.size(); i++){
  512.     atrt_process & proc = config.m_processes[i];
  513.     if((proc.m_type & atrt_process::NDB_MGM) != 0){
  514.       handle = proc.m_ndb_mgm_handle;
  515.       break;
  516.     }
  517.   }
  518.   if(handle == 0){
  519.     g_logger.critical("Unable to find mgm handle");
  520.     return false;
  521.   }
  522.   if(goal == NDB_MGM_NODE_STATUS_STARTED){
  523.     /**
  524.      * 1) wait NOT_STARTED
  525.      * 2) send start
  526.      * 3) wait STARTED
  527.      */
  528.     if(!wait_ndb(config, NDB_MGM_NODE_STATUS_NOT_STARTED))
  529.       return false;
  530.     
  531.     ndb_mgm_start(handle, 0, 0);
  532.   }
  533.   struct ndb_mgm_cluster_state * state;
  534.   time_t now = time(0);
  535.   time_t end = now + 360;
  536.   int min = remap(NDB_MGM_NODE_STATUS_NO_CONTACT);
  537.   int min2 = goal;
  538.   while(now < end){
  539.     /**
  540.      * 1) retreive current state
  541.      */
  542.     state = 0;
  543.     do {
  544.       state = ndb_mgm_get_status(handle);
  545.       if(state == 0){
  546. const int err = ndb_mgm_get_latest_error(handle);
  547. g_logger.error("Unable to poll db state: %d %s %s",
  548.        ndb_mgm_get_latest_error(handle),
  549.        ndb_mgm_get_latest_error_msg(handle),
  550.        ndb_mgm_get_latest_error_desc(handle));
  551. if(err == NDB_MGM_SERVER_NOT_CONNECTED && connect_ndb_mgm(config)){
  552.   g_logger.error("Reconnected...");
  553.   continue;
  554. }
  555. return false;
  556.       }
  557.     } while(state == 0);
  558.     NdbAutoPtr<void> tmp(state);
  559.     
  560.     min2 = goal;
  561.     for(int i = 0; i<state->no_of_nodes; i++){
  562.       if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_NDB){
  563. const int s = remap(state->node_states[i].node_status);
  564. min2 = (min2 < s ? min2 : s );
  565. if(s < remap(NDB_MGM_NODE_STATUS_NO_CONTACT) || 
  566.    s > NDB_MGM_NODE_STATUS_STARTED){
  567.   g_logger.critical("Strange DB status during start: %d %d", i, min2);
  568.   return false;
  569. }
  570. if(min2 < min){
  571.   g_logger.critical("wait ndb failed node: %d %d %d %d", 
  572.     state->node_states[i].node_id, min, min2, goal);
  573. }
  574.       }
  575.     }
  576.     
  577.     if(min2 < min){
  578.       g_logger.critical("wait ndb failed %d %d %d", min, min2, goal);
  579.       return false;
  580.     }
  581.     
  582.     if(min2 == goal){
  583.       return true;
  584.       break;
  585.     }
  586.     
  587.     min = min2;
  588.     now = time(0);
  589.   }
  590.   
  591.   g_logger.critical("wait ndb timed out %d %d %d", min, min2, goal);
  592.   
  593.   return false;
  594. }
  595. bool
  596. start_process(atrt_process & proc){
  597.   if(proc.m_proc.m_id != -1){
  598.     g_logger.critical("starting already started process: %d", proc.m_index);
  599.     return false;
  600.   }
  601.   
  602.   BaseString path = proc.m_proc.m_cwd.substr(proc.m_host->m_base_dir.length()+BaseString("/run").length());
  603.   
  604.   BaseString tmp = g_setup_progname;
  605.   tmp.appfmt(" %s %s/%s/ %s",
  606.      proc.m_host->m_hostname.c_str(),
  607.      g_setup_path,
  608.      path.c_str(),
  609.      proc.m_proc.m_cwd.c_str());
  610.   const int r1 = system(tmp.c_str());
  611.   if(r1 != 0){
  612.     g_logger.critical("Failed to setup process");
  613.     return false;
  614.   }
  615.   {
  616.     Properties reply;
  617.     if(proc.m_host->m_cpcd->define_process(proc.m_proc, reply) != 0){
  618.       BaseString msg;
  619.       reply.get("errormessage", msg);
  620.       g_logger.error("Unable to define process: %s", msg.c_str());      
  621.       return false;
  622.     }
  623.   }
  624.   {
  625.     Properties reply;
  626.     if(proc.m_host->m_cpcd->start_process(proc.m_proc.m_id, reply) != 0){
  627.       BaseString msg;
  628.       reply.get("errormessage", msg);
  629.       g_logger.error("Unable to start process: %s", msg.c_str());
  630.       return false;
  631.     }
  632.   }
  633.   return true;
  634. }
  635. bool
  636. start_processes(atrt_config& config, int types){
  637.   for(size_t i = 0; i<config.m_processes.size(); i++){
  638.     atrt_process & proc = config.m_processes[i];
  639.     if((types & proc.m_type) != 0 && proc.m_proc.m_path != ""){
  640.       if(!start_process(proc)){
  641. return false;
  642.       }
  643.     }
  644.   }
  645.   return true;
  646. }
  647. bool
  648. stop_process(atrt_process & proc){
  649.   if(proc.m_proc.m_id == -1){
  650.     return true;
  651.   }
  652.   {
  653.     Properties reply;
  654.     if(proc.m_host->m_cpcd->stop_process(proc.m_proc.m_id, reply) != 0){
  655.       Uint32 status;
  656.       reply.get("status", &status);
  657.       if(status != 4){
  658. BaseString msg;
  659. reply.get("errormessage", msg);
  660. g_logger.error("Unable to stop process: %s(%d)", msg.c_str(), status);
  661. return false;
  662.       }
  663.     }
  664.   }
  665.   {
  666.     Properties reply;
  667.     if(proc.m_host->m_cpcd->undefine_process(proc.m_proc.m_id, reply) != 0){
  668.       BaseString msg;
  669.       reply.get("errormessage", msg);
  670.       g_logger.error("Unable to undefine process: %s", msg.c_str());      
  671.       return false;
  672.     }
  673.     proc.m_proc.m_id = -1;
  674.   }
  675.   return true;
  676. }
  677. bool
  678. stop_processes(atrt_config& config, int types){
  679.   for(size_t i = 0; i<config.m_processes.size(); i++){
  680.     atrt_process & proc = config.m_processes[i];
  681.     if((types & proc.m_type) != 0){
  682.       if(!stop_process(proc)){
  683. return false;
  684.       }
  685.     }
  686.   }
  687.   return true;
  688. }
  689. bool
  690. update_status(atrt_config& config, int){
  691.   
  692.   Vector<Vector<SimpleCpcClient::Process> > m_procs;
  693.   
  694.   Vector<SimpleCpcClient::Process> dummy;
  695.   m_procs.fill(config.m_hosts.size(), dummy);
  696.   for(size_t i = 0; i<config.m_hosts.size(); i++){
  697.     Properties p;
  698.     config.m_hosts[i].m_cpcd->list_processes(m_procs[i], p);
  699.   }
  700.   for(size_t i = 0; i<config.m_processes.size(); i++){
  701.     atrt_process & proc = config.m_processes[i];
  702.     if(proc.m_proc.m_id != -1){
  703.       Vector<SimpleCpcClient::Process> &h_procs= m_procs[proc.m_host->m_index];
  704.       bool found = false;
  705.       for(size_t j = 0; j<h_procs.size(); j++){
  706. if(proc.m_proc.m_id == h_procs[j].m_id){
  707.   found = true;
  708.   proc.m_proc.m_status = h_procs[j].m_status;
  709.   break;
  710. }
  711.       }
  712.       if(!found){
  713. g_logger.error("update_status: not found");
  714. g_logger.error("id: %d host: %s cmd: %s", 
  715.        proc.m_proc.m_id,
  716.        proc.m_hostname.c_str(),
  717.        proc.m_proc.m_path.c_str());
  718. for(size_t j = 0; j<h_procs.size(); j++){
  719.   g_logger.error("found: %d %s", h_procs[j].m_id, 
  720.  h_procs[j].m_path.c_str());
  721. }
  722. return false;
  723.       }
  724.     }
  725.   }
  726.   return true;
  727. }
  728. int
  729. is_running(atrt_config& config, int types){
  730.   int found = 0, running = 0;
  731.   for(size_t i = 0; i<config.m_processes.size(); i++){
  732.     atrt_process & proc = config.m_processes[i]; 
  733.     if((types & proc.m_type) != 0){
  734.       found++;
  735.       if(proc.m_proc.m_status == "running")
  736. running++;
  737.     }
  738.   }
  739.   
  740.   if(found == running)
  741.     return 2;
  742.   if(running == 0)
  743.     return 0;
  744.   return 1;
  745. }
  746. int
  747. insert(const char * pair, Properties & p){
  748.   BaseString tmp(pair);
  749.   
  750.   tmp.trim(" tnr");
  751.   Vector<BaseString> split;
  752.   tmp.split(split, ":=", 2);
  753.   if(split.size() != 2)
  754.     return -1;
  755.   p.put(split[0].trim().c_str(), split[1].trim().c_str()); 
  756.   return 0;
  757. }
  758. bool
  759. read_test_case(FILE * file, atrt_testcase& tc, int& line){
  760.   Properties p;
  761.   int elements = 0;
  762.   char buf[1024];
  763.   while(!feof(file)){
  764.     if(!fgets(buf, 1024, file))
  765.       break;
  766.     line++;
  767.     BaseString tmp = buf;
  768.     
  769.     if(tmp.length() > 0 && tmp.c_str()[0] == '#')
  770.       continue;
  771.     
  772.     if(insert(tmp.c_str(), p) != 0)
  773.       break;
  774.     
  775.     elements++;
  776.   }
  777.   
  778.   if(elements == 0){
  779.     if(file == stdin){
  780.       BaseString tmp(buf); 
  781.       tmp.trim(" tnr");
  782.       Vector<BaseString> split;
  783.       tmp.split(split, " ", 2);
  784.       tc.m_command = split[0];
  785.       if(split.size() == 2)
  786. tc.m_args = split[1];
  787.       else
  788. tc.m_args = "";
  789.       tc.m_max_time = 60000;
  790.       return true;
  791.     }
  792.     return false;
  793.   }
  794.   if(!p.get("cmd", tc.m_command)){
  795.     g_logger.critical("Invalid test file: cmd is missing near line: %d", line);
  796.     return false;
  797.   }
  798.   
  799.   if(!p.get("args", tc.m_args))
  800.     tc.m_args = "";
  801.   const char * mt = 0;
  802.   if(!p.get("max-time", &mt))
  803.     tc.m_max_time = 60000;
  804.   else
  805.     tc.m_max_time = atoi(mt);
  806.   if(p.get("type", &mt) && strcmp(mt, "bench") == 0)
  807.     tc.m_report= true;
  808.   else
  809.     tc.m_report= false;
  810.   if(p.get("run-all", &mt) && strcmp(mt, "yes") == 0)
  811.     tc.m_run_all= true;
  812.   else
  813.     tc.m_run_all= false;
  814.   
  815.   return true;
  816. }
  817. bool
  818. setup_test_case(atrt_config& config, const atrt_testcase& tc){
  819.   const int r1 = system(g_clear_progname);
  820.   if(r1 != 0){
  821.     g_logger.critical("Failed to clear result");
  822.     return false;
  823.   }
  824.   
  825.   size_t i = 0;
  826.   for(; i<config.m_processes.size(); i++){
  827.     atrt_process & proc = config.m_processes[i]; 
  828.     if(proc.m_type == atrt_process::NDB_API || proc.m_type == atrt_process::MYSQL_CLIENT){
  829.       proc.m_proc.m_path.assfmt("%s/bin/%s", proc.m_host->m_base_dir.c_str(),
  830. tc.m_command.c_str());
  831.       proc.m_proc.m_args.assign(tc.m_args);
  832.       if(!tc.m_run_all)
  833.         break;
  834.     }
  835.   }
  836.   for(i++; i<config.m_processes.size(); i++){
  837.     atrt_process & proc = config.m_processes[i]; 
  838.     if(proc.m_type == atrt_process::NDB_API || proc.m_type == atrt_process::MYSQL_CLIENT){
  839.       proc.m_proc.m_path.assign("");
  840.       proc.m_proc.m_args.assign("");
  841.     }
  842.   }
  843.   return true;
  844. }
  845. bool
  846. gather_result(atrt_config& config, int * result){
  847.   BaseString tmp = g_gather_progname;
  848.   for(size_t i = 0; i<config.m_processes.size(); i++){
  849.     atrt_process & proc = config.m_processes[i]; 
  850.     if(proc.m_proc.m_path != ""){
  851.       tmp.appfmt(" %s:%s", 
  852.  proc.m_hostname.c_str(),
  853.  proc.m_proc.m_cwd.c_str());
  854.     }
  855.   }
  856.   
  857.   const int r1 = system(tmp.c_str());
  858.   if(r1 != 0){
  859.     g_logger.critical("Failed to gather result");
  860.     return false;
  861.   }
  862.   const int r2 = system(g_analyze_progname);
  863.   if(r2 == -1 || r2 == (127 << 8)){
  864.     g_logger.critical("Failed to analyze results");
  865.     return false;
  866.   }
  867.   
  868.   * result = r2 ;
  869.   return true;
  870. }
  871. bool
  872. setup_hosts(atrt_config& config){
  873.   const int r1 = system(g_clear_progname);
  874.   if(r1 != 0){
  875.     g_logger.critical("Failed to clear result");
  876.     return false;
  877.   }
  878.   for(size_t i = 0; i<config.m_hosts.size(); i++){
  879.     BaseString tmp = g_setup_progname;
  880.     tmp.appfmt(" %s %s/ %s/run", 
  881.        config.m_hosts[i].m_hostname.c_str(),
  882.        g_setup_path,
  883.        config.m_hosts[i].m_base_dir.c_str());
  884.     
  885.     const int r1 = system(tmp.c_str());
  886.     if(r1 != 0){
  887.       g_logger.critical("Failed to setup %s",
  888. config.m_hosts[i].m_hostname.c_str());
  889.       return false;
  890.     }
  891.   }
  892.   return true;
  893. }
  894. template class Vector<Vector<SimpleCpcClient::Process> >;
  895. template class Vector<atrt_host>;
  896. template class Vector<atrt_process>;