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

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 "CpcClient.hpp"
  16. #include <NdbEnv.h>
  17. #define DEFAULT_PORT 1234
  18. #define ENV_HOSTS "NDB_CPCC_HOSTS"
  19. struct settings {
  20.   int m_longl;
  21.   short m_port;
  22. } g_settings = { 0 , DEFAULT_PORT };
  23. Vector<SimpleCpcClient*> g_hosts;
  24. int connect(Vector<SimpleCpcClient*>&);
  25. class Expression {
  26. public:
  27.   virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process &)= 0;
  28. };
  29. int for_each(Vector<SimpleCpcClient*>& list, Expression &);
  30. int start_stop(const char * cmd, Vector<SimpleCpcClient*>& list, 
  31.        Vector<Vector<Uint32> >& procs);
  32. class True : public Expression {
  33. public:
  34.   virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
  35.     return true;
  36.   }
  37. };
  38. class FieldEQ : public Expression {
  39.   BaseString m_field;
  40.   BaseString m_value;
  41. public:
  42.   FieldEQ(const BaseString & field, const BaseString & value){
  43.     m_field = field;
  44.     m_value = value;
  45.   }
  46.   virtual ~FieldEQ(){}
  47.   virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
  48.     BaseString v;
  49.     if(m_field == "name") v = p.m_name;
  50.   
  51.     if(m_field == "type") v = p.m_type;
  52.     if(m_field == "status") v = p.m_status;
  53.     if(m_field == "owner") v = p.m_owner;
  54.     if(m_field == "group") v = p.m_group;
  55.     if(m_field == "path") v = p.m_path;
  56.     if(m_field == "args") v = p.m_args;
  57.     if(m_field == "env") v = p.m_env;
  58.     if(m_field == "cwd") v = p.m_cwd;
  59.     
  60.     if(m_field == "stdin") v = p.m_stdin;
  61.     if(m_field == "stdout") v = p.m_stdout;
  62.     if(m_field == "stderr") v = p.m_stderr;
  63.     
  64.     return v == m_value;
  65.   }
  66. };
  67. class Match : public Expression {
  68.   Expression & m_cond;
  69.   Expression & m_apply;
  70. public:
  71.   Match(Expression& condition, Expression & rule)
  72.     : m_cond(condition), m_apply(rule) {
  73.   }
  74.   virtual ~Match(){}
  75.   virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
  76.     if(m_cond.evaluate(c, p))
  77.       return m_apply.evaluate(c, p);
  78.     return false;
  79.   }
  80. };
  81. class Operate : public Expression {
  82.   const char * cmd;
  83.   SimpleCpcClient * host;
  84.   settings & sets;
  85. public:
  86.   Operate(const char * c, settings & s) : sets(s) {
  87.     cmd = c;
  88.     host = 0;
  89.   }
  90.   
  91.   virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p);
  92. };
  93. class ProcEQ : public Expression {
  94.   SimpleCpcClient * host;
  95.   Uint32 id;
  96. public:
  97.   ProcEQ(SimpleCpcClient* h, Uint32 i){
  98.     host = h; id = i;
  99.   }
  100.   virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
  101.     return p.m_id == (int)id && c == host;
  102.   }
  103. };
  104. class OrExpr : public Expression {
  105.   Expression * m_rule;
  106.   Vector<Expression *> m_cond;
  107.   bool on_empty;
  108. public:
  109.   OrExpr(Expression * rule, bool onEmp = true){
  110.     m_rule = rule;
  111.     on_empty = onEmp;
  112.   }
  113.   virtual ~OrExpr(){}
  114.   virtual bool evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & p){
  115.     bool run = on_empty;
  116.     for(size_t i = 0; i<m_cond.size(); i++){
  117.       if(m_cond[i]->evaluate(c, p)){
  118. run = true;
  119. break;
  120.       }
  121.     }
  122.     if(run)
  123.       return m_rule->evaluate(c, p);
  124.     return false;
  125.   }
  126.   void push_back(Expression * expr){
  127.     m_cond.push_back(expr);
  128.   }
  129. };
  130. void
  131. add_host(Vector<SimpleCpcClient*> & hosts, BaseString tmp){
  132.   Vector<BaseString> split;
  133.   tmp.split(split, ":");
  134.   
  135.   short port = g_settings.m_port;
  136.   if(split.size() > 1)
  137.     port = atoi(split[1].c_str());
  138.   
  139.   hosts.push_back(new SimpleCpcClient(split[0].c_str(), port));
  140. }
  141. void
  142. add_hosts(Vector<SimpleCpcClient*> & hosts, BaseString list){
  143.   Vector<BaseString> split;
  144.   list.split(split);
  145.   for(size_t i = 0; i<split.size(); i++){
  146.     add_host(hosts, split[i]);
  147.   }
  148. }
  149. int 
  150. main(int argc, const char** argv){
  151.   ndb_init();
  152.   int help = 0;
  153.   const char *cmd=0, *name=0, *group=0, *owner=0;
  154.   int list = 0, start = 0, stop = 0, rm = 0;
  155.   struct getargs args[] = {
  156.     { "cmd", 'c', arg_string, &cmd, "command", "command to run (default ls)" }
  157.     ,{ "name", 'n', arg_string, &name, 
  158.        "apply command for all processes with name" }
  159.     ,{ "group", 'g', arg_string, &group, 
  160.        "apply command for all processes in group" }
  161.     ,{ "owner", 'g', arg_string, &owner,
  162.        "apply command for all processes with owner" }
  163.     ,{ "long", 'l', arg_flag, &g_settings.m_longl, "long", "long listing"}
  164.     ,{ "usage", '?', arg_flag, &help, "Print help", "" }
  165.     ,{ "ls",  0, arg_flag, &list, "-c list", "list process(es)" }
  166.     ,{ "start", 0, arg_flag, &start, "-c start", "start process(es)" }
  167.     ,{ "stop",  0, arg_flag, &stop, "-c stop", "stop process(es)" }
  168.     ,{ "rm",    0, arg_flag, &rm, "-c rm", "undefine process(es)" }
  169.   };
  170.   const int num_args = 10;
  171.   int i; 
  172.   int optind = 0;
  173.   char desc[] = "[host:[port]]n";
  174.   
  175.   if(getarg(args, num_args, argc, argv, &optind) || help) {
  176.     arg_printusage(args, num_args, argv[0], desc);
  177.     return 1;
  178.   }
  179.   if(list + start + stop + rm > 1){
  180.     ndbout_c("Can only specify one command");
  181.     arg_printusage(args, num_args, argv[0], desc);
  182.     return 1;
  183.   }
  184.   
  185.   if(list) cmd = "list";
  186.   if(start) cmd = "start";
  187.   if(stop) cmd = "stop";
  188.   if(rm) cmd = "rm";
  189.   if(!cmd) cmd = "list";
  190.   
  191.   Expression * m_expr = 0;
  192.   for(i = optind; i<argc; i++){
  193.     add_host(g_hosts, argv[i]);
  194.   }
  195.   OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
  196.   m_expr = orE;
  197.   for(i = optind; i<argc; i++){
  198.     BaseString tmp(argv[i]);
  199.     Vector<BaseString> split;
  200.     tmp.split(split, ":");
  201.     
  202.     if(split.size() > 2){
  203.       Uint32 id = atoi(split[2].c_str());
  204.       orE->push_back(new ProcEQ(g_hosts[i-optind], id));
  205.     }
  206.   }
  207.   if(g_hosts.size() == 0){
  208.     char buf[1024];
  209.     if(NdbEnv_GetEnv(ENV_HOSTS, buf, sizeof(buf))){
  210.       add_hosts(g_hosts, BaseString(buf));
  211.     }
  212.   }
  213.   
  214.   if(g_hosts.size() == 0){
  215.     g_hosts.push_back(new SimpleCpcClient("localhost", g_settings.m_port));
  216.   }
  217.   
  218.   if(group != 0){
  219.     Expression * tmp = new FieldEQ("group", group);
  220.     m_expr = new Match(* tmp, * m_expr);
  221.   }
  222.   
  223.   if(name != 0){
  224.     Expression * tmp = new FieldEQ("name", name);
  225.     m_expr = new Match(* tmp, * m_expr);
  226.   }
  227.   if(owner != 0){
  228.     Expression * tmp = new FieldEQ("owner", owner);
  229.     m_expr = new Match(* tmp, * m_expr);
  230.   }
  231.   connect(g_hosts);
  232.   for_each(g_hosts, * m_expr);
  233.   
  234.   return 0;
  235. }
  236. int
  237. connect(Vector<SimpleCpcClient*>& list){
  238.   for(size_t i = 0; i<list.size(); i++){
  239.     if(list[i]->connect() != 0){
  240.       ndbout_c("Failed to connect to %s:%d", 
  241.        list[i]->getHost(), list[i]->getPort());
  242.       delete list[i]; list[i] = 0;
  243.     }
  244.   }
  245.   return 0;
  246. }
  247. int
  248. for_each(Vector<SimpleCpcClient*>& list, Expression & expr){
  249.   for(size_t i = 0; i<list.size(); i++){
  250.     if(list[i] == 0)
  251.       continue;
  252.     Properties p;
  253.     Vector<SimpleCpcClient::Process> procs;
  254.     if(list[i]->list_processes(procs, p) != 0){
  255.       ndbout << "Failed to list processes on " 
  256.      << list[i]->getHost() << ":" << list[i]->getPort() << endl;
  257.     }
  258.     for(size_t j = 0; j<procs.size(); j++)
  259.       expr.evaluate(list[i], procs[j]);
  260.   }
  261.   return 0;
  262. }
  263. bool
  264. Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
  265.   Uint32 id = pp.m_id;
  266.   Properties p;
  267.   int res;
  268.   if(strcasecmp(cmd, "start") == 0)
  269.     res = c->start_process(id, p);
  270.   else if(strcasecmp(cmd, "stop") == 0)
  271.     res = c->stop_process(id, p);
  272.   else if(strcasecmp(cmd, "rm") == 0)
  273.     res = c->undefine_process(id, p);
  274.   else if(strcasecmp(cmd, "list") == 0){
  275.     if(!sets.m_longl){
  276.       if(host != c){
  277. ndbout_c("--- %s:%d", c->getHost(), c->getPort());
  278. host = c;
  279.       }
  280.     }
  281.     
  282.     char s = 0;
  283.     const char * status = pp.m_status.c_str();
  284.     if(strcmp(status, "stopped") == 0)  s = '-';
  285.     if(strcmp(status, "starting") == 0) s = 's';
  286.     if(strcmp(status, "running") == 0)  s = 'r';
  287.     if(strcmp(status, "stopping") == 0)  s = 'k';    
  288.     if(s == 0) s = '?';
  289.     if(!sets.m_longl){
  290.       ndbout_c("%c%ct%dt%st%st%s(%s)", 
  291.        s, 
  292.        pp.m_type.c_str()[0], id, pp.m_owner.c_str(), 
  293.        pp.m_group.c_str(), pp.m_name.c_str(), pp.m_path.c_str());
  294.     } else {
  295.       ndbout_c("%c%c %s:%d:%d %s %s %s(%s)", 
  296.        s, pp.m_type.c_str()[0], c->getHost(), c->getPort(),
  297.        id, pp.m_owner.c_str(), pp.m_group.c_str(), 
  298.        pp.m_name.c_str(), pp.m_path.c_str());
  299.     }
  300.     return true;
  301.   }
  302.   
  303.   if(res != 0){
  304.     BaseString msg;
  305.     p.get("errormessage", msg);
  306.     ndbout_c("Failed to %s %d on %s:%d - %s",
  307.      cmd, id, 
  308.      c->getHost(), c->getPort(), msg.c_str());
  309.     return false;
  310.   }
  311.   
  312.   return true;
  313. }
  314. template class Vector<Expression*>;
  315. template class Vector<SimpleCpcClient*>;