/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include "CpcClient.hpp" #include #define DEFAULT_PORT 1234 #define ENV_HOSTS "NDB_CPCC_HOSTS" struct settings { int m_longl; short m_port; } g_settings = { 0 , DEFAULT_PORT }; Vector g_hosts; int connect(Vector&); class Expression { public: virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process &)= 0; }; int for_each(Vector& list, Expression &); int start_stop(const char * cmd, Vector& list, Vector >& procs); class True : public Expression { public: virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){ return true; } }; class FieldEQ : public Expression { BaseString m_field; BaseString m_value; public: FieldEQ(const BaseString & field, const BaseString & value){ m_field = field; m_value = value; } virtual ~FieldEQ(){} virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){ BaseString v; if(m_field == "name") v = p.m_name; if(m_field == "type") v = p.m_type; if(m_field == "status") v = p.m_status; if(m_field == "owner") v = p.m_owner; if(m_field == "group") v = p.m_group; if(m_field == "path") v = p.m_path; if(m_field == "args") v = p.m_args; if(m_field == "env") v = p.m_env; if(m_field == "cwd") v = p.m_cwd; if(m_field == "stdin") v = p.m_stdin; if(m_field == "stdout") v = p.m_stdout; if(m_field == "stderr") v = p.m_stderr; return v == m_value; } }; class Match : public Expression { Expression & m_cond; Expression & m_apply; public: Match(Expression& condition, Expression & rule) : m_cond(condition), m_apply(rule) { } virtual ~Match(){} virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){ if(m_cond.evaluate(c, p)) return m_apply.evaluate(c, p); return false; } }; class Operate : public Expression { const char * cmd; SimpleCpcClient * host; settings & sets; public: Operate(const char * c, settings & s) : sets(s) { cmd = c; host = 0; } virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p); }; class ProcEQ : public Expression { SimpleCpcClient * host; Uint32 id; public: ProcEQ(SimpleCpcClient* h, Uint32 i){ host = h; id = i; } virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){ return p.m_id == (int)id && c == host; } }; class OrExpr : public Expression { Expression * m_rule; Vector m_cond; bool on_empty; public: OrExpr(Expression * rule, bool onEmp = true){ m_rule = rule; on_empty = onEmp; } virtual ~OrExpr(){} virtual bool evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & p){ bool run = on_empty; for(size_t i = 0; ievaluate(c, p)){ run = true; break; } } if(run) return m_rule->evaluate(c, p); return false; } void push_back(Expression * expr){ m_cond.push_back(expr); } }; void add_host(Vector & hosts, BaseString tmp){ Vector split; tmp.split(split, ":"); short port = g_settings.m_port; if(split.size() > 1) port = atoi(split[1].c_str()); hosts.push_back(new SimpleCpcClient(split[0].c_str(), port)); } void add_hosts(Vector & hosts, BaseString list){ Vector split; list.split(split); for(size_t i = 0; i 1){ ndbout_c("Can only specify one command"); arg_printusage(args, num_args, argv[0], desc); return 1; } if(list) cmd = "list"; if(start) cmd = "start"; if(stop) cmd = "stop"; if(rm) cmd = "rm"; if(!cmd) cmd = "list"; Expression * m_expr = 0; for(i = optind; i split; tmp.split(split, ":"); if(split.size() > 2){ Uint32 id = atoi(split[2].c_str()); orE->push_back(new ProcEQ(g_hosts[i-optind], id)); } } if(g_hosts.size() == 0){ char buf[1024]; if(NdbEnv_GetEnv(ENV_HOSTS, buf, sizeof(buf))){ add_hosts(g_hosts, BaseString(buf)); } } if(g_hosts.size() == 0){ g_hosts.push_back(new SimpleCpcClient("localhost", g_settings.m_port)); } if(group != 0){ Expression * tmp = new FieldEQ("group", group); m_expr = new Match(* tmp, * m_expr); } if(name != 0){ Expression * tmp = new FieldEQ("name", name); m_expr = new Match(* tmp, * m_expr); } if(owner != 0){ Expression * tmp = new FieldEQ("owner", owner); m_expr = new Match(* tmp, * m_expr); } connect(g_hosts); for_each(g_hosts, * m_expr); return 0; } int connect(Vector& list){ for(size_t i = 0; iconnect() != 0){ ndbout_c("Failed to connect to %s:%d", list[i]->getHost(), list[i]->getPort()); delete list[i]; list[i] = 0; } } return 0; } int for_each(Vector& list, Expression & expr){ for(size_t i = 0; i procs; if(list[i]->list_processes(procs, p) != 0){ ndbout << "Failed to list processes on " << list[i]->getHost() << ":" << list[i]->getPort() << endl; } for(size_t j = 0; jstart_process(id, p); else if(strcasecmp(cmd, "stop") == 0) res = c->stop_process(id, p); else if(strcasecmp(cmd, "rm") == 0) res = c->undefine_process(id, p); else if(strcasecmp(cmd, "list") == 0){ if(!sets.m_longl){ if(host != c){ ndbout_c("--- %s:%d", c->getHost(), c->getPort()); host = c; } } char s = 0; const char * status = pp.m_status.c_str(); if(strcmp(status, "stopped") == 0) s = '-'; if(strcmp(status, "starting") == 0) s = 's'; if(strcmp(status, "running") == 0) s = 'r'; if(strcmp(status, "stopping") == 0) s = 'k'; if(s == 0) s = '?'; if(!sets.m_longl){ ndbout_c("%c%c\t%d\t%s\t%s\t%s(%s)", s, pp.m_type.c_str()[0], id, pp.m_owner.c_str(), pp.m_group.c_str(), pp.m_name.c_str(), pp.m_path.c_str()); } else { ndbout_c("%c%c %s:%d:%d %s %s %s(%s)", s, pp.m_type.c_str()[0], c->getHost(), c->getPort(), id, pp.m_owner.c_str(), pp.m_group.c_str(), pp.m_name.c_str(), pp.m_path.c_str()); } return true; } if(res != 0){ BaseString msg; p.get("errormessage", msg); ndbout_c("Failed to %s %d on %s:%d - %s", cmd, id, c->getHost(), c->getPort(), msg.c_str()); return false; } return true; } template class Vector; template class Vector;