MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cpcc.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 
19 #include <ndb_global.h>
20 #include <getarg.h>
21 #include "CpcClient.hpp"
22 
23 #include <portlib/NdbEnv.h>
24 #include <util/NdbOut.hpp>
25 
26 #define DEFAULT_PORT 1234
27 #define ENV_HOSTS "NDB_CPCC_HOSTS"
28 
29 struct settings {
30  int m_longl;
31  short m_port;
32 } g_settings = { 0 , DEFAULT_PORT };
33 
35 int connect(Vector<SimpleCpcClient*>&);
36 
37 class Expression {
38 public:
39  virtual ~Expression() {}
40  virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process &)= 0;
41 };
42 
43 int for_each(Vector<SimpleCpcClient*>& list, Expression &);
44 int start_stop(const char * cmd, Vector<SimpleCpcClient*>& list,
45  Vector<Vector<Uint32> >& procs);
46 
47 class True : public Expression {
48 public:
49  virtual ~True() {}
50  virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
51  return true;
52  }
53 };
54 
55 class FieldEQ : public Expression {
56  BaseString m_field;
57  BaseString m_value;
58 public:
59  FieldEQ(const BaseString & field, const BaseString & value){
60  m_field = field;
61  m_value = value;
62  }
63  virtual ~FieldEQ(){}
64 
65  virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
66  BaseString v;
67  if(m_field == "name") v = p.m_name;
68 
69  if(m_field == "type") v = p.m_type;
70  if(m_field == "status") v = p.m_status;
71  if(m_field == "owner") v = p.m_owner;
72  if(m_field == "group") v = p.m_group;
73  if(m_field == "path") v = p.m_path;
74  if(m_field == "args") v = p.m_args;
75  if(m_field == "env") v = p.m_env;
76  if(m_field == "cwd") v = p.m_cwd;
77 
78  if(m_field == "stdin") v = p.m_stdin;
79  if(m_field == "stdout") v = p.m_stdout;
80  if(m_field == "stderr") v = p.m_stderr;
81 
82  return v == m_value;
83  }
84 };
85 
86 class Match : public Expression {
87  Expression & m_cond;
88  Expression & m_apply;
89 public:
90  Match(Expression& condition, Expression & rule)
91  : m_cond(condition), m_apply(rule) {
92  }
93  virtual ~Match(){}
94 
95  virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
96  if(m_cond.evaluate(c, p))
97  return m_apply.evaluate(c, p);
98  return false;
99  }
100 };
101 
102 class Operate : public Expression {
103  const char * cmd;
104  SimpleCpcClient * host;
105  settings & sets;
106 public:
107  Operate(const char * c, settings & s) : sets(s) {
108  cmd = c;
109  host = 0;
110  }
111  virtual ~Operate() {}
112 
113  virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p);
114 };
115 
116 class ProcEQ : public Expression {
117  SimpleCpcClient * host;
118  Uint32 id;
119 public:
120  ProcEQ(SimpleCpcClient* h, Uint32 i){
121  host = h; id = i;
122  }
123  virtual ~ProcEQ() {}
124  virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
125  return p.m_id == (int)id && c == host;
126  }
127 };
128 
129 class OrExpr : public Expression {
130  Expression * m_rule;
131  Vector<Expression *> m_cond;
132  bool on_empty;
133 public:
134  OrExpr(Expression * rule, bool onEmp = true){
135  m_rule = rule;
136  on_empty = onEmp;
137  }
138 
139  virtual ~OrExpr(){}
140 
141  virtual bool evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & p){
142  bool run = on_empty;
143  for(size_t i = 0; i<m_cond.size(); i++){
144  if(m_cond[i]->evaluate(c, p)){
145  run = true;
146  break;
147  }
148  }
149  if(run)
150  return m_rule->evaluate(c, p);
151  return false;
152  }
153 
154  void push_back(Expression * expr){
155  m_cond.push_back(expr);
156  }
157 };
158 
159 void
160 add_host(Vector<SimpleCpcClient*> & hosts, BaseString tmp){
161  Vector<BaseString> split;
162  tmp.split(split, ":");
163 
164  short port = g_settings.m_port;
165  if(split.size() > 1)
166  port = atoi(split[1].c_str());
167 
168  hosts.push_back(new SimpleCpcClient(split[0].c_str(), port));
169 }
170 
171 void
172 add_hosts(Vector<SimpleCpcClient*> & hosts, BaseString list){
173  Vector<BaseString> split;
174  list.split(split);
175  for(size_t i = 0; i<split.size(); i++){
176  add_host(hosts, split[i]);
177  }
178 }
179 
180 int
181 main(int argc, const char** argv){
182  ndb_init();
183  int help = 0;
184  const char *cmd=0, *name=0, *group=0, *owner=0;
185  int list = 0, start = 0, stop = 0, rm = 0;
186  struct getargs args[] = {
187  { "cmd", 'c', arg_string, &cmd, "command", "command to run (default ls)" }
188  ,{ "name", 'n', arg_string, &name,
189  "apply command for all processes with name", "" }
190  ,{ "group", 'g', arg_string, &group,
191  "apply command for all processes in group", "" }
192  ,{ "owner", 'g', arg_string, &owner,
193  "apply command for all processes with owner", "" }
194  ,{ "long", 'l', arg_flag, &g_settings.m_longl, "long", "long listing"}
195  ,{ "usage", '?', arg_flag, &help, "Print help", "" }
196  ,{ "ls", 0, arg_flag, &list, "-c list", "list process(es)" }
197  ,{ "start", 0, arg_flag, &start, "-c start", "start process(es)" }
198  ,{ "stop", 0, arg_flag, &stop, "-c stop", "stop process(es)" }
199  ,{ "rm", 0, arg_flag, &rm, "-c rm", "undefine process(es)" }
200  };
201  const int num_args = 10;
202  int i;
203  int optind = 0;
204  char desc[] = "[host:[port]]\n";
205 
206  if(getarg(args, num_args, argc, argv, &optind) || help) {
207  arg_printusage(args, num_args, argv[0], desc);
208  return 1;
209  }
210 
211  if(list + start + stop + rm > 1){
212  ndbout_c("Can only specify one command");
213  arg_printusage(args, num_args, argv[0], desc);
214  return 1;
215  }
216 
217  if(list) cmd = "list";
218  if(start) cmd = "start";
219  if(stop) cmd = "stop";
220  if(rm) cmd = "rm";
221  if(!cmd) cmd = "list";
222 
223  Expression * m_expr = 0;
224 
225  for(i = optind; i<argc; i++){
226  add_host(g_hosts, argv[i]);
227  }
228 
229  OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
230  m_expr = orE;
231  for(i = optind; i<argc; i++){
232  BaseString tmp(argv[i]);
233  Vector<BaseString> split;
234  tmp.split(split, ":");
235 
236  if(split.size() > 2){
237  Uint32 id = atoi(split[2].c_str());
238  orE->push_back(new ProcEQ(g_hosts[i-optind], id));
239  }
240  }
241 
242  if(g_hosts.size() == 0){
243  char buf[1024];
244  if(NdbEnv_GetEnv(ENV_HOSTS, buf, sizeof(buf))){
245  add_hosts(g_hosts, BaseString(buf));
246  }
247  }
248 
249  if(g_hosts.size() == 0){
250  g_hosts.push_back(new SimpleCpcClient("localhost", g_settings.m_port));
251  }
252 
253  if(group != 0){
254  Expression * tmp = new FieldEQ("group", group);
255  m_expr = new Match(* tmp, * m_expr);
256  }
257 
258  if(name != 0){
259  Expression * tmp = new FieldEQ("name", name);
260  m_expr = new Match(* tmp, * m_expr);
261  }
262 
263  if(owner != 0){
264  Expression * tmp = new FieldEQ("owner", owner);
265  m_expr = new Match(* tmp, * m_expr);
266  }
267 
268  connect(g_hosts);
269  for_each(g_hosts, * m_expr);
270 
271  return 0;
272 }
273 
274 int
275 connect(Vector<SimpleCpcClient*>& list){
276  for(size_t i = 0; i<list.size(); i++){
277  if(list[i]->connect() != 0){
278  ndbout_c("Failed to connect to %s:%d",
279  list[i]->getHost(), list[i]->getPort());
280  delete list[i]; list[i] = 0;
281  }
282  }
283  return 0;
284 }
285 
286 int
287 for_each(Vector<SimpleCpcClient*>& list, Expression & expr){
288  for(size_t i = 0; i<list.size(); i++){
289  if(list[i] == 0)
290  continue;
291  Properties p;
293  if(list[i]->list_processes(procs, p) != 0){
294  ndbout << "Failed to list processes on "
295  << list[i]->getHost() << ":" << list[i]->getPort() << endl;
296  }
297  for(size_t j = 0; j<procs.size(); j++)
298  expr.evaluate(list[i], procs[j]);
299  }
300  return 0;
301 }
302 
303 bool
304 Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
305  Uint32 id = pp.m_id;
306  Properties p;
307  int res;
308 
309  if(strcasecmp(cmd, "start") == 0)
310  res = c->start_process(id, p);
311  else if(strcasecmp(cmd, "stop") == 0)
312  res = c->stop_process(id, p);
313  else if(strcasecmp(cmd, "rm") == 0)
314  res = c->undefine_process(id, p);
315  else if(strcasecmp(cmd, "list") == 0){
316  if(!sets.m_longl){
317  if(host != c){
318  ndbout_c("--- %s:%d", c->getHost(), c->getPort());
319  host = c;
320  }
321  }
322 
323  char s = 0;
324  const char * status = pp.m_status.c_str();
325  if(strcmp(status, "stopped") == 0) s = '-';
326  if(strcmp(status, "starting") == 0) s = 's';
327  if(strcmp(status, "running") == 0) s = 'r';
328  if(strcmp(status, "stopping") == 0) s = 'k';
329  if(s == 0) s = '?';
330 
331  if(!sets.m_longl){
332  ndbout_c("%c%c\t%d\t%s\t%s\t%s(%s)",
333  s,
334  pp.m_type.c_str()[0], id, pp.m_owner.c_str(),
335  pp.m_group.c_str(), pp.m_name.c_str(), pp.m_path.c_str());
336  } else {
337  ndbout_c("%c%c %s:%d:%d %s %s %s(%s)",
338  s, pp.m_type.c_str()[0], c->getHost(), c->getPort(),
339  id, pp.m_owner.c_str(), pp.m_group.c_str(),
340  pp.m_name.c_str(), pp.m_path.c_str());
341  }
342  return true;
343  }
344 
345  if(res != 0){
346  BaseString msg;
347  p.get("errormessage", msg);
348  ndbout_c("Failed to %s %d on %s:%d - %s",
349  cmd, id,
350  c->getHost(), c->getPort(), msg.c_str());
351  return false;
352  }
353 
354  return true;
355 }
356 
357 template class Vector<Expression*>;
358 template class Vector<SimpleCpcClient*>;