~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/test/src/CpcClient.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include <ndb_global.h>
 
17
 
 
18
#include <NdbOut.hpp>
 
19
#include <NdbTCP.h>
 
20
#include "CpcClient.hpp"
 
21
 
 
22
#define CPC_CMD(name, value, desc) \
 
23
 { (name), \
 
24
   0, \
 
25
   ParserRow_t::Cmd, \
 
26
   ParserRow_t::String, \
 
27
   ParserRow_t::Optional, \
 
28
   ParserRow_t::IgnoreMinMax, \
 
29
   0, 0, \
 
30
   0, \
 
31
   (desc), \
 
32
   (value) }
 
33
 
 
34
#define CPC_ARG(name, type, opt, desc) \
 
35
 { (name), \
 
36
   0, \
 
37
   ParserRow_t::Arg, \
 
38
   ParserRow_t::type, \
 
39
   ParserRow_t::opt, \
 
40
   ParserRow_t::IgnoreMinMax, \
 
41
   0, 0, \
 
42
   0, \
 
43
  (desc), 0 }
 
44
 
 
45
#define CPC_END() \
 
46
 { 0, \
 
47
   0, \
 
48
   ParserRow_t::Arg, \
 
49
   ParserRow_t::Int, \
 
50
   ParserRow_t::Optional, \
 
51
   ParserRow_t::IgnoreMinMax, \
 
52
   0, 0, \
 
53
   0, \
 
54
   0, 0 }
 
55
 
 
56
#ifdef DEBUG_PRINT_PROPERTIES 
 
57
static void printprop(const Properties &p) {
 
58
  Properties::Iterator iter(&p);
 
59
  const char *name;
 
60
  while((name = iter.next()) != NULL) {
 
61
    PropertiesType t;
 
62
    Uint32 val_i;
 
63
    BaseString val_s;
 
64
 
 
65
    p.getTypeOf(name, &t);
 
66
    switch(t) {
 
67
    case PropertiesType_Uint32:
 
68
      p.get(name, &val_i);
 
69
      ndbout << name << " (Uint32): " << val_i << endl;
 
70
      break;
 
71
    case PropertiesType_char:
 
72
      p.get(name, val_s);
 
73
      ndbout << name << " (string): " << val_s << endl;
 
74
      break;
 
75
    default:
 
76
      ndbout << "Unknown type " << t << endl;
 
77
      break;
 
78
    }
 
79
  }
 
80
}
 
81
#endif
 
82
 
 
83
void
 
84
SimpleCpcClient::cmd_stop(char *arg) {
 
85
  Properties p;
 
86
  Vector<Process> proc_list;
 
87
 
 
88
  list_processes(proc_list, p);
 
89
  bool stopped = false;
 
90
 
 
91
  for(size_t i = 0; i < proc_list.size(); i++) {
 
92
    if(strcmp(proc_list[i].m_name.c_str(), arg) == 0) {
 
93
      stopped = true;
 
94
      Properties reply;
 
95
      stop_process(proc_list[i].m_id, reply);
 
96
 
 
97
      Uint32 status;
 
98
      reply.get("status", &status);
 
99
      if(status != 0) {
 
100
        BaseString msg;
 
101
        reply.get("errormessage", msg);
 
102
        ndbout << "Stop failed: " << msg << endl;
 
103
      }
 
104
    }
 
105
  }
 
106
  
 
107
  if(!stopped)
 
108
    ndbout << "No such process" << endl;
 
109
}
 
110
 
 
111
int
 
112
SimpleCpcClient::stop_process(Uint32 id, Properties& reply){
 
113
  const ParserRow_t stop_reply[] = {
 
114
    CPC_CMD("stop process", NULL, ""),
 
115
    CPC_ARG("status", Int, Mandatory, ""),
 
116
    CPC_ARG("id", Int, Optional, ""),
 
117
    CPC_ARG("errormessage", String, Optional, ""),
 
118
    
 
119
    CPC_END()
 
120
  };
 
121
 
 
122
  Properties args;
 
123
  args.put("id", id);
 
124
  
 
125
  const Properties* ret = cpc_call("stop process", args, stop_reply);
 
126
  if(ret == 0){
 
127
    reply.put("status", (Uint32)0);
 
128
    reply.put("errormessage", "unknown error");
 
129
    return -1;
 
130
  }
 
131
 
 
132
  Uint32 status = 0;
 
133
  ret->get("status", &status);
 
134
  reply.put("status", status);
 
135
  if(status != 0) {
 
136
    BaseString msg;
 
137
    ret->get("errormessage", msg);
 
138
    reply.put("errormessage", msg.c_str());
 
139
  }
 
140
 
 
141
  return status;
 
142
}
 
143
 
 
144
void
 
145
SimpleCpcClient::cmd_start(char *arg) {
 
146
  Properties p;
 
147
  Vector<Process> proc_list;
 
148
  list_processes(proc_list, p);
 
149
  bool startped = false;
 
150
 
 
151
  for(size_t i = 0; i < proc_list.size(); i++) {
 
152
    if(strcmp(proc_list[i].m_name.c_str(), arg) == 0) {
 
153
      startped = true;
 
154
 
 
155
      Properties reply;
 
156
      start_process(proc_list[i].m_id, reply);
 
157
 
 
158
      Uint32 status;
 
159
      reply.get("status", &status);
 
160
      if(status != 0) {
 
161
        BaseString msg;
 
162
        reply.get("errormessage", msg);
 
163
        ndbout << "Start failed: " << msg << endl;
 
164
      }
 
165
    }
 
166
  }
 
167
  
 
168
  if(!startped)
 
169
    ndbout << "No such process" << endl;
 
170
}
 
171
 
 
172
int
 
173
SimpleCpcClient::start_process(Uint32 id, Properties& reply){
 
174
  const ParserRow_t start_reply[] = {
 
175
    CPC_CMD("start process", NULL, ""),
 
176
    CPC_ARG("status", Int, Mandatory, ""),
 
177
    CPC_ARG("id", Int, Optional, ""),
 
178
    CPC_ARG("errormessage", String, Optional, ""),
 
179
    
 
180
    CPC_END()
 
181
  };
 
182
 
 
183
  Properties args;
 
184
  args.put("id", id);
 
185
  
 
186
  const Properties* ret = cpc_call("start process", args, start_reply);
 
187
  if(ret == 0){
 
188
    reply.put("status", (Uint32)0);
 
189
    reply.put("errormessage", "unknown error");
 
190
    return -1;
 
191
  }
 
192
 
 
193
  Uint32 status = 0;
 
194
  ret->get("status", &status);
 
195
  reply.put("status", status);
 
196
  if(status != 0) {
 
197
    BaseString msg;
 
198
    ret->get("errormessage", msg);
 
199
    reply.put("errormessage", msg.c_str());
 
200
  }
 
201
 
 
202
  return status;
 
203
}
 
204
 
 
205
int
 
206
SimpleCpcClient::undefine_process(Uint32 id, Properties& reply){
 
207
  const ParserRow_t stop_reply[] = {
 
208
    CPC_CMD("undefine process", NULL, ""),
 
209
    CPC_ARG("status", Int, Mandatory, ""),
 
210
    CPC_ARG("id", Int, Optional, ""),
 
211
    CPC_ARG("errormessage", String, Optional, ""),
 
212
    
 
213
    CPC_END()
 
214
  };
 
215
 
 
216
  Properties args;
 
217
  args.put("id", id);
 
218
  
 
219
  const Properties* ret = cpc_call("undefine process", args, stop_reply);
 
220
  if(ret == 0){
 
221
    reply.put("status", (Uint32)0);
 
222
    reply.put("errormessage", "unknown error");
 
223
    return -1;
 
224
  }
 
225
 
 
226
  Uint32 status = 0;
 
227
  ret->get("status", &status);
 
228
  reply.put("status", status);
 
229
  if(status != 0) {
 
230
    BaseString msg;
 
231
    ret->get("errormessage", msg);
 
232
    reply.put("errormessage", msg.c_str());
 
233
  }
 
234
 
 
235
  return status;
 
236
}
 
237
 
 
238
static void
 
239
printproc(SimpleCpcClient::Process & p) {
 
240
  ndbout.println("Name:                %s", p.m_name.c_str());
 
241
  ndbout.println("Id:                  %d", p.m_id);
 
242
  ndbout.println("Type:                %s", p.m_type.c_str());
 
243
  ndbout.println("Group:               %s", p.m_group.c_str());
 
244
  ndbout.println("Program path:        %s", p.m_path.c_str());
 
245
  ndbout.println("Arguments:           %s", p.m_args.c_str());
 
246
  ndbout.println("Environment:         %s", p.m_env.c_str());
 
247
  ndbout.println("Working directory:   %s", p.m_cwd.c_str());
 
248
  ndbout.println("Owner:               %s", p.m_owner.c_str());
 
249
  ndbout.println("Runas:               %s", p.m_runas.c_str());
 
250
  ndbout.println("Ulimit:              %s", p.m_ulimit.c_str());
 
251
  ndbout.println("");
 
252
}
 
253
 
 
254
void
 
255
SimpleCpcClient::cmd_list(char *arg) {
 
256
  Properties p;
 
257
  Vector<Process> proc_list;
 
258
  list_processes(proc_list, p);
 
259
 
 
260
  for(size_t i = 0; i < proc_list.size(); i++) {
 
261
    printproc(proc_list[i]);
 
262
  }
 
263
}
 
264
 
 
265
static int
 
266
convert(const Properties & src, SimpleCpcClient::Process & dst){
 
267
  bool b = true;
 
268
  b &= src.get("id", (Uint32*)&dst.m_id);
 
269
  b &= src.get("name",   dst.m_name);
 
270
  b &= src.get("type",   dst.m_type);
 
271
  b &= src.get("status", dst.m_status);
 
272
  b &= src.get("owner",  dst.m_owner);
 
273
  b &= src.get("group",  dst.m_group);
 
274
  b &= src.get("path",   dst.m_path);
 
275
  b &= src.get("args",   dst.m_args);
 
276
  b &= src.get("env",    dst.m_env);
 
277
  b &= src.get("cwd",    dst.m_cwd);
 
278
  b &= src.get("runas",  dst.m_runas);
 
279
 
 
280
  b &= src.get("stdin",  dst.m_stdin);
 
281
  b &= src.get("stdout", dst.m_stdout);
 
282
  b &= src.get("stderr", dst.m_stderr);
 
283
  b &= src.get("ulimit", dst.m_ulimit);
 
284
  b &= src.get("shutdown", dst.m_shutdown_options);
 
285
 
 
286
  return b;
 
287
}
 
288
 
 
289
static int
 
290
convert(const SimpleCpcClient::Process & src, Properties & dst ){
 
291
  bool b = true;
 
292
  //b &= dst.put("id",     (Uint32)src.m_id);
 
293
  b &= dst.put("name",   src.m_name.c_str());
 
294
  b &= dst.put("type",   src.m_type.c_str());
 
295
  //b &= dst.put("status", src.m_status.c_str());
 
296
  b &= dst.put("owner",  src.m_owner.c_str());
 
297
  b &= dst.put("group",  src.m_group.c_str());
 
298
  b &= dst.put("path",   src.m_path.c_str());
 
299
  b &= dst.put("args",   src.m_args.c_str());
 
300
  b &= dst.put("env",    src.m_env.c_str());
 
301
  b &= dst.put("cwd",    src.m_cwd.c_str());
 
302
  b &= dst.put("runas",  src.m_runas.c_str());
 
303
 
 
304
  b &= dst.put("stdin",  src.m_stdin.c_str());
 
305
  b &= dst.put("stdout", src.m_stdout.c_str());
 
306
  b &= dst.put("stderr", src.m_stderr.c_str());
 
307
  b &= dst.put("ulimit", src.m_ulimit.c_str());
 
308
  b &= dst.put("shutdown", src.m_shutdown_options.c_str());
 
309
  
 
310
  return b;
 
311
}
 
312
 
 
313
int
 
314
SimpleCpcClient::define_process(Process & p, Properties& reply){
 
315
  const ParserRow_t define_reply[] = {
 
316
    CPC_CMD("define process", NULL, ""),
 
317
    CPC_ARG("status", Int, Mandatory, ""),
 
318
    CPC_ARG("id", Int, Optional, ""),
 
319
    CPC_ARG("errormessage", String, Optional, ""),
 
320
    
 
321
    CPC_END()
 
322
  };
 
323
 
 
324
  Properties args;
 
325
  convert(p, args);
 
326
 
 
327
  const Properties* ret = cpc_call("define process", args, define_reply);
 
328
  if(ret == 0){
 
329
    reply.put("status", (Uint32)0);
 
330
    reply.put("errormessage", "unknown error");
 
331
    return -1;
 
332
  }
 
333
 
 
334
  Uint32 status = 0;
 
335
  ret->get("status", &status);
 
336
  reply.put("status", status);
 
337
  if(status != 0) {
 
338
    BaseString msg;
 
339
    ret->get("errormessage", msg);
 
340
    reply.put("errormessage", msg.c_str());
 
341
  }
 
342
 
 
343
  Uint32 id;
 
344
  if(!ret->get("id", &id)){
 
345
    return -1;
 
346
  }
 
347
 
 
348
  p.m_id = id;
 
349
  
 
350
  return status;
 
351
}
 
352
 
 
353
int
 
354
SimpleCpcClient::list_processes(Vector<Process> &procs, Properties& reply) {
 
355
  int start, end, entry; 
 
356
  const ParserRow_t list_reply[] = {
 
357
    CPC_CMD("start processes", &start, ""),
 
358
    CPC_CMD("end processes", &end, ""),
 
359
 
 
360
    CPC_CMD("process", &entry, ""),
 
361
    CPC_ARG("id",    Int,    Mandatory, "Id of process."),
 
362
    CPC_ARG("name",  String, Mandatory, "Name of process"),
 
363
    CPC_ARG("group", String, Mandatory, "Group of process"),
 
364
    CPC_ARG("env",   String, Mandatory, "Environment variables for process"),
 
365
    CPC_ARG("path",  String, Mandatory, "Path to binary"),
 
366
    CPC_ARG("args",  String, Mandatory, "Arguments to process"),
 
367
    CPC_ARG("type",  String, Mandatory, "Type of process"),
 
368
    CPC_ARG("cwd",   String, Mandatory, "Working directory of process"),
 
369
    CPC_ARG("owner", String, Mandatory, "Owner of process"),
 
370
    CPC_ARG("status",String, Mandatory, "Status of process"),
 
371
    CPC_ARG("runas", String, Mandatory, "Run as user"),
 
372
    CPC_ARG("stdin", String, Mandatory, "Redirect stdin"),
 
373
    CPC_ARG("stdout",String, Mandatory, "Redirect stdout"),
 
374
    CPC_ARG("stderr",String, Mandatory, "Redirect stderr"),
 
375
    CPC_ARG("ulimit",String, Mandatory, "ulimit"),    
 
376
    CPC_ARG("shutdown",String, Mandatory, "shutdown"),    
 
377
    
 
378
    CPC_END()
 
379
  };
 
380
 
 
381
  reply.clear();
 
382
 
 
383
  const Properties args;
 
384
 
 
385
  cpc_send("list processes", args);
 
386
 
 
387
  bool done = false;
 
388
  while(!done) {
 
389
    const Properties *proc;
 
390
    void *p;
 
391
    cpc_recv(list_reply, &proc, &p);
 
392
 
 
393
    if(p == &start)
 
394
    {
 
395
      /* do nothing */
 
396
    }
 
397
    else if(p == &end)
 
398
    {
 
399
      done = true;
 
400
    }
 
401
    else if(p == &entry)
 
402
    {
 
403
      if(proc != NULL){
 
404
        Process p;
 
405
        convert(* proc, p);
 
406
        procs.push_back(p);
 
407
      }
 
408
    }
 
409
    else
 
410
    {
 
411
      ndbout_c("internal error: %d", __LINE__);
 
412
      return -1;
 
413
    }
 
414
  }
 
415
  return 0;
 
416
}
 
417
 
 
418
void
 
419
SimpleCpcClient::cmd_help(char *arg) {
 
420
  ndbout
 
421
    << "HELP                            Print help text" << endl
 
422
    << "LIST                            List processes" << endl
 
423
    << "START                           Start process" << endl
 
424
    << "STOP                            Stop process" << endl;
 
425
}
 
426
 
 
427
SimpleCpcClient::SimpleCpcClient(const char *_host, int _port) {
 
428
  host = strdup(_host);
 
429
  port = _port;
 
430
  cpc_sock = -1;
 
431
}
 
432
 
 
433
SimpleCpcClient::~SimpleCpcClient() {
 
434
  if(host != NULL) {
 
435
    free(host);
 
436
    host = NULL;
 
437
  }
 
438
 
 
439
  port = 0;
 
440
 
 
441
  if(cpc_sock == -1) {
 
442
    close(cpc_sock);
 
443
    cpc_sock = -1;
 
444
  }
 
445
}
 
446
 
 
447
int
 
448
SimpleCpcClient::connect() {
 
449
  struct sockaddr_in sa;
 
450
  struct hostent *hp;
 
451
 
 
452
  /* Create socket */
 
453
  cpc_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
454
  if(cpc_sock < 0)
 
455
    return -1;
 
456
 
 
457
  /* Connect socket */
 
458
  sa.sin_family = AF_INET;
 
459
  hp = gethostbyname(host);
 
460
  if(hp == NULL) {
 
461
    errno = ENOENT;
 
462
    return -1;
 
463
  }
 
464
 
 
465
  memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
 
466
  sa.sin_port = htons(port);
 
467
  if (::connect(cpc_sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
 
468
    return -1;
 
469
 
 
470
  return 0;
 
471
}
 
472
 
 
473
int
 
474
SimpleCpcClient::cpc_send(const char *cmd,
 
475
                          const Properties &args) {
 
476
  SocketOutputStream cpc_out(cpc_sock);
 
477
 
 
478
  cpc_out.println(cmd);
 
479
 
 
480
  Properties::Iterator iter(&args);
 
481
  const char *name;
 
482
  while((name = iter.next()) != NULL) {
 
483
    PropertiesType t;
 
484
    Uint32 val_i;
 
485
    BaseString val_s;
 
486
 
 
487
    args.getTypeOf(name, &t);
 
488
    switch(t) {
 
489
    case PropertiesType_Uint32:
 
490
      args.get(name, &val_i);
 
491
      cpc_out.println("%s: %d", name, val_i);
 
492
      break;
 
493
    case PropertiesType_char:
 
494
      args.get(name, val_s);
 
495
      cpc_out.println("%s: %s", name, val_s.c_str());
 
496
      break;
 
497
    default:
 
498
      /* Silently ignore */
 
499
      break;
 
500
    }
 
501
  }
 
502
  cpc_out.println("");
 
503
 
 
504
  return 0;
 
505
}
 
506
 
 
507
/**
 
508
 * Receive a response from the CPCD. The argument reply will point
 
509
 * to a Properties object describing the reply. Note that the caller
 
510
 * is responsible for deleting the Properties object returned.
 
511
 */
 
512
SimpleCpcClient::Parser_t::ParserStatus
 
513
SimpleCpcClient::cpc_recv(const ParserRow_t *syntax,
 
514
                          const Properties **reply,
 
515
                          void **user_value) {
 
516
  SocketInputStream cpc_in(cpc_sock);
 
517
 
 
518
  Parser_t::Context ctx;
 
519
  ParserDummy session(cpc_sock);
 
520
  Parser_t parser(syntax, cpc_in, true, true, true);
 
521
  *reply = parser.parse(ctx, session);
 
522
  if(user_value != NULL)
 
523
    *user_value = ctx.m_currentCmd->user_value;
 
524
  return ctx.m_status;
 
525
}
 
526
 
 
527
const Properties *
 
528
SimpleCpcClient::cpc_call(const char *cmd,
 
529
                          const Properties &args,
 
530
                          const ParserRow_t *reply_syntax) {
 
531
  cpc_send(cmd, args);
 
532
 
 
533
#if 0
 
534
  Parser_t::Context ctx;
 
535
  ParserDummy session(cpc_sock);
 
536
  Parser_t parser(reply_syntax, *cpc_in, true, true, true);
 
537
  const Properties *ret = parser.parse(ctx, session);
 
538
  return ret;
 
539
#endif
 
540
  const Properties *ret;
 
541
  cpc_recv(reply_syntax, &ret);
 
542
  return ret;
 
543
}
 
544
 
 
545
 
 
546
SimpleCpcClient::ParserDummy::ParserDummy(NDB_SOCKET_TYPE sock)
 
547
  : SocketServer::Session(sock) {
 
548
}
 
549
 
 
550
template class Vector<SimpleCpcClient::Process>; 
 
551
template class Vector<ParserRow<SimpleCpcClient::ParserDummy> const*>;