summaryrefslogtreecommitdiff
path: root/ndb/test/tools/cpcc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/test/tools/cpcc.cpp')
-rw-r--r--ndb/test/tools/cpcc.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/ndb/test/tools/cpcc.cpp b/ndb/test/tools/cpcc.cpp
new file mode 100644
index 00000000000..e768d707bbc
--- /dev/null
+++ b/ndb/test/tools/cpcc.cpp
@@ -0,0 +1,349 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <getarg.h>
+#include "CpcClient.hpp"
+#include <NdbEnv.h>
+
+#define DEFAULT_PORT 1234
+#define ENV_HOSTS "NDB_CPCC_HOSTS"
+
+struct settings {
+ int m_longl;
+ short m_port;
+} g_settings = { 0 , DEFAULT_PORT };
+
+Vector<SimpleCpcClient*> g_hosts;
+int connect(Vector<SimpleCpcClient*>&);
+
+class Expression {
+public:
+ virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process &)= 0;
+};
+
+int for_each(Vector<SimpleCpcClient*>& list, Expression &);
+int start_stop(const char * cmd, Vector<SimpleCpcClient*>& list,
+ Vector<Vector<Uint32> >& 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<Expression *> 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; i<m_cond.size(); i++){
+ if(m_cond[i]->evaluate(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<SimpleCpcClient*> & hosts, BaseString tmp){
+ Vector<BaseString> 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<SimpleCpcClient*> & hosts, BaseString list){
+ Vector<BaseString> split;
+ list.split(split);
+ for(size_t i = 0; i<split.size(); i++){
+ add_host(hosts, split[i]);
+ }
+}
+
+int
+main(int argc, const char** argv){
+ int help = 0;
+ const char *cmd=0, *name=0, *group=0, *owner=0;
+ int list = 0, start = 0, stop = 0, rm = 0;
+ struct getargs args[] = {
+ { "cmd", 'c', arg_string, &cmd, "command", "command to run (default ls)" }
+ ,{ "name", 'n', arg_string, &name,
+ "apply command for all processes with name" }
+ ,{ "group", 'g', arg_string, &group,
+ "apply command for all processes in group" }
+ ,{ "owner", 'g', arg_string, &owner,
+ "apply command for all processes with owner" }
+ ,{ "long", 'l', arg_flag, &g_settings.m_longl, "long", "long listing"}
+ ,{ "usage", '?', arg_flag, &help, "Print help", "" }
+ ,{ "ls", 0, arg_flag, &list, "-c list", "list process(es)" }
+ ,{ "start", 0, arg_flag, &start, "-c start", "start process(es)" }
+ ,{ "stop", 0, arg_flag, &stop, "-c stop", "stop process(es)" }
+ ,{ "rm", 0, arg_flag, &rm, "-c rm", "undefine process(es)" }
+ };
+ const int num_args = 10;
+
+ int optind = 0;
+ char desc[] = "[host:[port]]\n";
+
+ if(getarg(args, num_args, argc, argv, &optind) || help) {
+ arg_printusage(args, num_args, argv[0], desc);
+ return 1;
+ }
+
+ if(list + start + stop + rm > 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(int i = optind; i<argc; i++){
+ add_host(g_hosts, argv[i]);
+ }
+
+ OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
+ m_expr = orE;
+ for(int i = optind; i<argc; i++){
+ BaseString tmp(argv[i]);
+ Vector<BaseString> 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<SimpleCpcClient*>& list){
+ for(size_t i = 0; i<list.size(); i++){
+ if(list[i]->connect() != 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<SimpleCpcClient*>& list, Expression & expr){
+ for(size_t i = 0; i<list.size(); i++){
+ if(list[i] == 0)
+ continue;
+ Properties p;
+ Vector<SimpleCpcClient::Process> 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; j<procs.size(); j++)
+ expr.evaluate(list[i], procs[j]);
+ }
+ return 0;
+}
+
+bool
+Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
+ Uint32 id = pp.m_id;
+ Properties p;
+ int res;
+
+ if(strcasecmp(cmd, "start") == 0)
+ res = c->start_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;
+}
+