2
Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
19
#include <ndb_global.h>
21
#include "CpcClient.hpp"
23
#include <portlib/NdbEnv.h>
24
#include <util/NdbOut.hpp>
26
#define DEFAULT_PORT 1234
27
#define ENV_HOSTS "NDB_CPCC_HOSTS"
32
} g_settings = { 0 , DEFAULT_PORT };
34
Vector<SimpleCpcClient*> g_hosts;
35
int connect(Vector<SimpleCpcClient*>&);
39
virtual ~Expression() {}
40
virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process &)= 0;
43
int for_each(Vector<SimpleCpcClient*>& list, Expression &);
44
int start_stop(const char * cmd, Vector<SimpleCpcClient*>& list,
45
Vector<Vector<Uint32> >& procs);
47
class True : public Expression {
50
virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
55
class FieldEQ : public Expression {
59
FieldEQ(const BaseString & field, const BaseString & value){
65
virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p){
67
if(m_field == "name") v = p.m_name;
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;
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;
86
class Match : public Expression {
90
Match(Expression& condition, Expression & rule)
91
: m_cond(condition), m_apply(rule) {
95
virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
96
if(m_cond.evaluate(c, p))
97
return m_apply.evaluate(c, p);
102
class Operate : public Expression {
104
SimpleCpcClient * host;
107
Operate(const char * c, settings & s) : sets(s) {
111
virtual ~Operate() {}
113
virtual bool evaluate(SimpleCpcClient*, const SimpleCpcClient::Process & p);
116
class ProcEQ : public Expression {
117
SimpleCpcClient * host;
120
ProcEQ(SimpleCpcClient* h, Uint32 i){
124
virtual bool evaluate(SimpleCpcClient* c,const SimpleCpcClient::Process & p){
125
return p.m_id == (int)id && c == host;
129
class OrExpr : public Expression {
131
Vector<Expression *> m_cond;
134
OrExpr(Expression * rule, bool onEmp = true){
141
virtual bool evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & p){
143
for(size_t i = 0; i<m_cond.size(); i++){
144
if(m_cond[i]->evaluate(c, p)){
150
return m_rule->evaluate(c, p);
154
void push_back(Expression * expr){
155
m_cond.push_back(expr);
160
add_host(Vector<SimpleCpcClient*> & hosts, BaseString tmp){
161
Vector<BaseString> split;
162
tmp.split(split, ":");
164
short port = g_settings.m_port;
166
port = atoi(split[1].c_str());
168
hosts.push_back(new SimpleCpcClient(split[0].c_str(), port));
172
add_hosts(Vector<SimpleCpcClient*> & hosts, BaseString list){
173
Vector<BaseString> split;
175
for(size_t i = 0; i<split.size(); i++){
176
add_host(hosts, split[i]);
181
main(int argc, const char** argv){
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)" }
201
const int num_args = 10;
204
char desc[] = "[host:[port]]\n";
206
if(getarg(args, num_args, argc, argv, &optind) || help) {
207
arg_printusage(args, num_args, argv[0], desc);
211
if(list + start + stop + rm > 1){
212
ndbout_c("Can only specify one command");
213
arg_printusage(args, num_args, argv[0], desc);
217
if(list) cmd = "list";
218
if(start) cmd = "start";
219
if(stop) cmd = "stop";
221
if(!cmd) cmd = "list";
223
Expression * m_expr = 0;
225
for(i = optind; i<argc; i++){
226
add_host(g_hosts, argv[i]);
229
OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
231
for(i = optind; i<argc; i++){
232
BaseString tmp(argv[i]);
233
Vector<BaseString> split;
234
tmp.split(split, ":");
236
if(split.size() > 2){
237
Uint32 id = atoi(split[2].c_str());
238
orE->push_back(new ProcEQ(g_hosts[i-optind], id));
242
if(g_hosts.size() == 0){
244
if(NdbEnv_GetEnv(ENV_HOSTS, buf, sizeof(buf))){
245
add_hosts(g_hosts, BaseString(buf));
249
if(g_hosts.size() == 0){
250
g_hosts.push_back(new SimpleCpcClient("localhost", g_settings.m_port));
254
Expression * tmp = new FieldEQ("group", group);
255
m_expr = new Match(* tmp, * m_expr);
259
Expression * tmp = new FieldEQ("name", name);
260
m_expr = new Match(* tmp, * m_expr);
264
Expression * tmp = new FieldEQ("owner", owner);
265
m_expr = new Match(* tmp, * m_expr);
269
for_each(g_hosts, * m_expr);
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;
287
for_each(Vector<SimpleCpcClient*>& list, Expression & expr){
288
for(size_t i = 0; i<list.size(); i++){
292
Vector<SimpleCpcClient::Process> procs;
293
if(list[i]->list_processes(procs, p) != 0){
294
ndbout << "Failed to list processes on "
295
<< list[i]->getHost() << ":" << list[i]->getPort() << endl;
297
for(size_t j = 0; j<procs.size(); j++)
298
expr.evaluate(list[i], procs[j]);
304
Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
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){
318
ndbout_c("--- %s:%d", c->getHost(), c->getPort());
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';
332
ndbout_c("%c%c\t%d\t%s\t%s\t%s(%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());
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());
347
p.get("errormessage", msg);
348
ndbout_c("Failed to %s %d on %s:%d - %s",
350
c->getHost(), c->getPort(), msg.c_str());
357
template class Vector<Expression*>;
358
template class Vector<SimpleCpcClient*>;