MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
APIService.cpp
1 /*
2  Copyright (C) 2003-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 
20 #include <Parser.hpp>
21 #include <NdbOut.hpp>
22 #include <Properties.hpp>
23 #include <socket_io.h>
24 
25 #include "APIService.hpp"
26 #include "CPCD.hpp"
27 #include <NdbMutex.h>
28 #include <OutputStream.hpp>
29 
43 #define CPCD_CMD(name, fun, desc) \
44  { name, \
45  0, \
46  ParserRow<CPCDAPISession>::Cmd, \
47  ParserRow<CPCDAPISession>::String, \
48  ParserRow<CPCDAPISession>::Optional, \
49  ParserRow<CPCDAPISession>::IgnoreMinMax, \
50  0, 0, \
51  fun, \
52  desc, 0 }
53 
54 #define CPCD_ARG(name, type, opt, desc) \
55  { name, \
56  0, \
57  ParserRow<CPCDAPISession>::Arg, \
58  ParserRow<CPCDAPISession>::type, \
59  ParserRow<CPCDAPISession>::opt, \
60  ParserRow<CPCDAPISession>::IgnoreMinMax, \
61  0, 0, \
62  0, \
63  desc, 0 }
64 
65 #define CPCD_ARG2(name, type, opt, min, max, desc) \
66  { name, \
67  0, \
68  ParserRow<CPCDAPISession>::Arg, \
69  ParserRow<CPCDAPISession>::type, \
70  ParserRow<CPCDAPISession>::opt, \
71  ParserRow<CPCDAPISession>::IgnoreMinMax, \
72  min, max, \
73  0, \
74  desc, 0 }
75 
76 #define CPCD_END() \
77  { 0, \
78  0, \
79  ParserRow<CPCDAPISession>::Arg, \
80  ParserRow<CPCDAPISession>::Int, \
81  ParserRow<CPCDAPISession>::Optional, \
82  ParserRow<CPCDAPISession>::IgnoreMinMax, \
83  0, 0, \
84  0, \
85  0, 0 }
86 
87 #define CPCD_CMD_ALIAS(name, realName, fun) \
88  { name, \
89  realName, \
90  ParserRow<CPCDAPISession>::CmdAlias, \
91  ParserRow<CPCDAPISession>::Int, \
92  ParserRow<CPCDAPISession>::Optional, \
93  ParserRow<CPCDAPISession>::IgnoreMinMax, \
94  0, 0, \
95  0, \
96  0, 0 }
97 
98 #define CPCD_ARG_ALIAS(name, realName, fun) \
99  { name, \
100  realName, \
101  ParserRow<CPCDAPISession>::ArgAlias, \
102  ParserRow<CPCDAPISession>::Int, \
103  ParserRow<CPCDAPISession>::Optional, \
104  ParserRow<CPCDAPISession>::IgnoreMinMax, \
105  0, 0, \
106  0, \
107  0, 0 }
108 
109 const
110 ParserRow<CPCDAPISession> commands[] =
111 {
112  CPCD_CMD("define process" , &CPCDAPISession::defineProcess, ""),
113  CPCD_ARG("id", Int, Optional, "Id of process."),
114  CPCD_ARG("name", String, Mandatory, "Name of process"),
115  CPCD_ARG("group", String, Mandatory, "Group of process"),
116  CPCD_ARG("env", String, Optional, "Environment variables for process"),
117  CPCD_ARG("path", String, Mandatory, "Path to binary"),
118  CPCD_ARG("args", String, Optional, "Arguments to process"),
119  CPCD_ARG("type", String, Mandatory, "Type of process"),
120  CPCD_ARG("cwd", String, Mandatory, "Working directory of process"),
121  CPCD_ARG("owner", String, Mandatory, "Owner of process"),
122  CPCD_ARG("runas", String, Optional, "Run as user"),
123  CPCD_ARG("stdout", String, Optional, "Redirection of stdout"),
124  CPCD_ARG("stderr", String, Optional, "Redirection of stderr"),
125  CPCD_ARG("stdin", String, Optional, "Redirection of stderr"),
126  CPCD_ARG("ulimit", String, Optional, "ulimit"),
127  CPCD_ARG("shutdown", String, Optional, "shutdown options"),
128 
129  CPCD_CMD("undefine process", &CPCDAPISession::undefineProcess, ""),
130  CPCD_CMD_ALIAS("undef", "undefine process", 0),
131  CPCD_ARG("id", Int, Mandatory, "Id of process"),
132  CPCD_ARG_ALIAS("i", "id", 0),
133 
134  CPCD_CMD("start process", &CPCDAPISession::startProcess, ""),
135  CPCD_ARG("id", Int, Mandatory, "Id of process"),
136 
137  CPCD_CMD("stop process", &CPCDAPISession::stopProcess, ""),
138  CPCD_ARG("id", Int, Mandatory, "Id of process"),
139 
140  CPCD_CMD("list processes", &CPCDAPISession::listProcesses, ""),
141 
142  CPCD_CMD("show version", &CPCDAPISession::showVersion, ""),
143 
144  CPCD_END()
145 };
146 CPCDAPISession::CPCDAPISession(NDB_SOCKET_TYPE sock,
147  CPCD & cpcd)
148  : SocketServer::Session(sock)
149  , m_cpcd(cpcd)
150 {
151  m_input = new SocketInputStream(sock, 7*24*60*60000);
152  m_output = new SocketOutputStream(sock);
153  m_parser = new Parser<CPCDAPISession>(commands, *m_input, true, true, true);
154 }
155 
156 CPCDAPISession::CPCDAPISession(FILE * f, CPCD & cpcd)
157  : SocketServer::Session(my_socket_create_invalid())
158  , m_cpcd(cpcd)
159 {
160  m_input = new FileInputStream(f);
161  m_parser = new Parser<CPCDAPISession>(commands, *m_input, true, true, true);
162  m_output = 0;
163 }
164 
165 CPCDAPISession::~CPCDAPISession() {
166  delete m_input;
167  delete m_parser;
168  if (m_output)
169  delete m_output;
170 }
171 
172 void
173 CPCDAPISession::runSession(){
174  Parser_t::Context ctx;
175  while(!m_stop){
176  m_parser->run(ctx, * this);
177  if(ctx.m_currentToken == 0)
178  break;
179 
180  m_input->reset_timeout();
181  m_output->reset_timeout();
182 
183  switch(ctx.m_status){
184  case Parser_t::Ok:
185  for(size_t i = 0; i<ctx.m_aliasUsed.size(); i++)
186  ndbout_c("Used alias: %s -> %s",
187  ctx.m_aliasUsed[i]->name, ctx.m_aliasUsed[i]->realName);
188  break;
189  case Parser_t::NoLine:
190  case Parser_t::EmptyLine:
191  break;
192  default:
193  break;
194  }
195  }
196  NDB_CLOSE_SOCKET(m_socket);
197 }
198 
199 void
200 CPCDAPISession::stopSession(){
202  for(size_t i = 0; i<m_temporaryProcesses.size(); i++){
203  Uint32 id = m_temporaryProcesses[i];
204  m_cpcd.undefineProcess(&rs, id);
205  }
206 }
207 
208 void
209 CPCDAPISession::loadFile(){
210  Parser_t::Context ctx;
211  while(!m_stop){
212  m_parser->run(ctx, * this);
213  if(ctx.m_currentToken == 0)
214  break;
215 
216  switch(ctx.m_status){
217  case Parser_t::Ok:
218  for(size_t i = 0; i<ctx.m_aliasUsed.size(); i++)
219  ndbout_c("Used alias: %s -> %s",
220  ctx.m_aliasUsed[i]->name, ctx.m_aliasUsed[i]->realName);
221  break;
222  case Parser_t::NoLine:
223  case Parser_t::EmptyLine:
224  break;
225  default:
226  break;
227  }
228  }
229 }
230 
231 void
232 CPCDAPISession::defineProcess(Parser_t::Context & /* unused */,
233  const class Properties & args){
234 
235  CPCD::Process * p = new CPCD::Process(args, &m_cpcd);
236 
238 
239  bool ret = m_cpcd.defineProcess(&rs, p);
240  if(!m_cpcd.loadingProcessList) {
241  m_output->println("define process");
242  m_output->println("status: %d", rs.getStatus());
243  if(ret == true){
244  m_output->println("id: %d", p->m_id);
245  if(p->m_processType == TEMPORARY){
246  m_temporaryProcesses.push_back(p->m_id);
247  }
248  } else {
249  m_output->println("errormessage: %s", rs.getErrMsg());
250  }
251  m_output->println("%s", "");
252  }
253 }
254 
255 void
256 CPCDAPISession::undefineProcess(Parser_t::Context & /* unused */,
257  const class Properties & args){
258  Uint32 id;
260 
261  args.get("id", &id);
262  bool ret = m_cpcd.undefineProcess(&rs, id);
263 
264  m_output->println("undefine process");
265  m_output->println("id: %d", id);
266  m_output->println("status: %d", rs.getStatus());
267  if(!ret)
268  m_output->println("errormessage: %s", rs.getErrMsg());
269 
270  m_output->println("%s", "");
271 }
272 
273 void
274 CPCDAPISession::startProcess(Parser_t::Context & /* unused */,
275  const class Properties & args){
276  Uint32 id;
278 
279  args.get("id", &id);
280  const int ret = m_cpcd.startProcess(&rs, id);
281 
282  if(!m_cpcd.loadingProcessList) {
283  m_output->println("start process");
284  m_output->println("id: %d", id);
285  m_output->println("status: %d", rs.getStatus());
286  if(!ret)
287  m_output->println("errormessage: %s", rs.getErrMsg());
288  m_output->println("%s", "");
289  }
290 }
291 
292 void
293 CPCDAPISession::stopProcess(Parser_t::Context & /* unused */,
294  const class Properties & args){
295  Uint32 id;
297 
298  args.get("id", &id);
299  int ret = m_cpcd.stopProcess(&rs, id);
300 
301  m_output->println("stop process");
302  m_output->println("id: %d", id);
303  m_output->println("status: %d", rs.getStatus());
304  if(!ret)
305  m_output->println("errormessage: %s", rs.getErrMsg());
306 
307  m_output->println("%s", "");
308 }
309 
310 static const char *
311 propToString(Properties *prop, const char *key) {
312  static char buf[32];
313  const char *retval = NULL;
314  PropertiesType pt;
315 
316  prop->getTypeOf(key, &pt);
317  switch(pt) {
318  case PropertiesType_Uint32:
319  Uint32 val;
320  prop->get(key, &val);
321  BaseString::snprintf(buf, sizeof buf, "%d", val);
322  retval = buf;
323  break;
324  case PropertiesType_char:
325  const char *str;
326  prop->get(key, &str);
327  retval = str;
328  break;
329  default:
330  BaseString::snprintf(buf, sizeof buf, "(unknown)");
331  retval = buf;
332  }
333  return retval;
334 }
335 
336 void
337 CPCDAPISession::printProperty(Properties *prop, const char *key) {
338  m_output->println("%s: %s", key, propToString(prop, key));
339 }
340 
341 void
342 CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
343  const class Properties & /* unused */){
344  m_cpcd.m_processes.lock();
345  MutexVector<CPCD::Process *> *proclist = m_cpcd.getProcessList();
346 
347  m_output->println("start processes");
348  m_output->println("%s", "");
349 
350 
351  for(size_t i = 0; i < proclist->size(); i++) {
352  CPCD::Process *p = (*proclist)[i];
353 
354  m_output->println("process");
355 
356  m_output->println("id: %d", p->m_id);
357  m_output->println("name: %s", p->m_name.c_str());
358  m_output->println("path: %s", p->m_path.c_str());
359  m_output->println("args: %s", p->m_args.c_str());
360  m_output->println("type: %s", p->m_type.c_str());
361  m_output->println("cwd: %s", p->m_cwd.c_str());
362  m_output->println("env: %s", p->m_env.c_str());
363  m_output->println("owner: %s", p->m_owner.c_str());
364  m_output->println("group: %s", p->m_group.c_str());
365  m_output->println("runas: %s", p->m_runas.c_str());
366  m_output->println("stdin: %s", p->m_stdin.c_str());
367  m_output->println("stdout: %s", p->m_stdout.c_str());
368  m_output->println("stderr: %s", p->m_stderr.c_str());
369  m_output->println("ulimit: %s", p->m_ulimit.c_str());
370  m_output->println("shutdown: %s", p->m_shutdown_options.c_str());
371  switch(p->m_status){
372  case STOPPED:
373  m_output->println("status: stopped");
374  break;
375  case STARTING:
376  m_output->println("status: starting");
377  break;
378  case RUNNING:
379  m_output->println("status: running");
380  break;
381  case STOPPING:
382  m_output->println("status: stopping");
383  break;
384  }
385 
386  m_output->println("%s", "");
387 
388  }
389 
390  m_output->println("end processes");
391  m_output->println("%s", "");
392 
393  m_cpcd.m_processes.unlock();
394 }
395 
396 void
397 CPCDAPISession::showVersion(Parser_t::Context & /* unused */,
398  const class Properties & args){
400 
401  m_output->println("show version");
402  m_output->println("compile time: %s %s", __DATE__, __TIME__);
403 
404  m_output->println("%s", "");
405 }
406 
407 template class Vector<ParserRow<CPCDAPISession> const*>;