mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / src / cw / cpcd / APIService.cpp
blobd5cb079849fd39bfaef44377ff8b588635accae4
1 /* Copyright (c) 2003-2007 MySQL AB
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
17 #include <Parser.hpp>
18 #include <NdbOut.hpp>
19 #include <Properties.hpp>
20 #include <socket_io.h>
22 #include "APIService.hpp"
23 #include "CPCD.hpp"
24 #include <NdbMutex.h>
25 #include <OutputStream.hpp>
27 /**
28 const char * name;
29 const char * realName;
30 const Type type;
31 const ArgType argType;
32 const ArgRequired argRequired;
33 const ArgMinMax argMinMax;
34 const int minVal;
35 const int maxVal;
36 void (T::* function)(const class Properties & args);
37 const char * description;
40 #define CPCD_CMD(name, fun, desc) \
41 { name, \
42 0, \
43 ParserRow<CPCDAPISession>::Cmd, \
44 ParserRow<CPCDAPISession>::String, \
45 ParserRow<CPCDAPISession>::Optional, \
46 ParserRow<CPCDAPISession>::IgnoreMinMax, \
47 0, 0, \
48 fun, \
49 desc, 0 }
51 #define CPCD_ARG(name, type, opt, desc) \
52 { name, \
53 0, \
54 ParserRow<CPCDAPISession>::Arg, \
55 ParserRow<CPCDAPISession>::type, \
56 ParserRow<CPCDAPISession>::opt, \
57 ParserRow<CPCDAPISession>::IgnoreMinMax, \
58 0, 0, \
59 0, \
60 desc, 0 }
62 #define CPCD_ARG2(name, type, opt, min, max, desc) \
63 { name, \
64 0, \
65 ParserRow<CPCDAPISession>::Arg, \
66 ParserRow<CPCDAPISession>::type, \
67 ParserRow<CPCDAPISession>::opt, \
68 ParserRow<CPCDAPISession>::IgnoreMinMax, \
69 min, max, \
70 0, \
71 desc, 0 }
73 #define CPCD_END() \
74 { 0, \
75 0, \
76 ParserRow<CPCDAPISession>::Arg, \
77 ParserRow<CPCDAPISession>::Int, \
78 ParserRow<CPCDAPISession>::Optional, \
79 ParserRow<CPCDAPISession>::IgnoreMinMax, \
80 0, 0, \
81 0, \
82 0, 0 }
84 #define CPCD_CMD_ALIAS(name, realName, fun) \
85 { name, \
86 realName, \
87 ParserRow<CPCDAPISession>::CmdAlias, \
88 ParserRow<CPCDAPISession>::Int, \
89 ParserRow<CPCDAPISession>::Optional, \
90 ParserRow<CPCDAPISession>::IgnoreMinMax, \
91 0, 0, \
92 0, \
93 0, 0 }
95 #define CPCD_ARG_ALIAS(name, realName, fun) \
96 { name, \
97 realName, \
98 ParserRow<CPCDAPISession>::ArgAlias, \
99 ParserRow<CPCDAPISession>::Int, \
100 ParserRow<CPCDAPISession>::Optional, \
101 ParserRow<CPCDAPISession>::IgnoreMinMax, \
102 0, 0, \
103 0, \
104 0, 0 }
106 const
107 ParserRow<CPCDAPISession> commands[] =
109 CPCD_CMD("define process" , &CPCDAPISession::defineProcess, ""),
110 CPCD_ARG("id", Int, Optional, "Id of process."),
111 CPCD_ARG("name", String, Mandatory, "Name of process"),
112 CPCD_ARG("group", String, Mandatory, "Group of process"),
113 CPCD_ARG("env", String, Optional, "Environment variables for process"),
114 CPCD_ARG("path", String, Mandatory, "Path to binary"),
115 CPCD_ARG("args", String, Optional, "Arguments to process"),
116 CPCD_ARG("type", String, Mandatory, "Type of process"),
117 CPCD_ARG("cwd", String, Mandatory, "Working directory of process"),
118 CPCD_ARG("owner", String, Mandatory, "Owner of process"),
119 CPCD_ARG("runas", String, Optional, "Run as user"),
120 CPCD_ARG("stdout", String, Optional, "Redirection of stdout"),
121 CPCD_ARG("stderr", String, Optional, "Redirection of stderr"),
122 CPCD_ARG("stdin", String, Optional, "Redirection of stderr"),
123 CPCD_ARG("ulimit", String, Optional, "ulimit"),
124 CPCD_ARG("shutdown", String, Optional, "shutdown options"),
126 CPCD_CMD("undefine process", &CPCDAPISession::undefineProcess, ""),
127 CPCD_CMD_ALIAS("undef", "undefine process", 0),
128 CPCD_ARG("id", Int, Mandatory, "Id of process"),
129 CPCD_ARG_ALIAS("i", "id", 0),
131 CPCD_CMD("start process", &CPCDAPISession::startProcess, ""),
132 CPCD_ARG("id", Int, Mandatory, "Id of process"),
134 CPCD_CMD("stop process", &CPCDAPISession::stopProcess, ""),
135 CPCD_ARG("id", Int, Mandatory, "Id of process"),
137 CPCD_CMD("list processes", &CPCDAPISession::listProcesses, ""),
139 CPCD_CMD("show version", &CPCDAPISession::showVersion, ""),
141 CPCD_END()
143 CPCDAPISession::CPCDAPISession(NDB_SOCKET_TYPE sock,
144 CPCD & cpcd)
145 : SocketServer::Session(sock)
146 , m_cpcd(cpcd)
148 m_input = new SocketInputStream(sock, 7*24*60*60000);
149 m_output = new SocketOutputStream(sock);
150 m_parser = new Parser<CPCDAPISession>(commands, *m_input, true, true, true);
153 CPCDAPISession::CPCDAPISession(FILE * f, CPCD & cpcd)
154 : SocketServer::Session(1)
155 , m_cpcd(cpcd)
157 m_input = new FileInputStream(f);
158 m_parser = new Parser<CPCDAPISession>(commands, *m_input, true, true, true);
161 CPCDAPISession::~CPCDAPISession() {
162 delete m_input;
163 delete m_parser;
166 void
167 CPCDAPISession::runSession(){
168 Parser_t::Context ctx;
169 while(!m_stop){
170 m_parser->run(ctx, * this);
171 if(ctx.m_currentToken == 0)
172 break;
174 switch(ctx.m_status){
175 case Parser_t::Ok:
176 for(size_t i = 0; i<ctx.m_aliasUsed.size(); i++)
177 ndbout_c("Used alias: %s -> %s",
178 ctx.m_aliasUsed[i]->name, ctx.m_aliasUsed[i]->realName);
179 break;
180 case Parser_t::NoLine:
181 case Parser_t::EmptyLine:
182 break;
183 default:
184 break;
187 NDB_CLOSE_SOCKET(m_socket);
190 void
191 CPCDAPISession::stopSession(){
192 CPCD::RequestStatus rs;
193 for(size_t i = 0; i<m_temporaryProcesses.size(); i++){
194 Uint32 id = m_temporaryProcesses[i];
195 m_cpcd.undefineProcess(&rs, id);
199 void
200 CPCDAPISession::loadFile(){
201 Parser_t::Context ctx;
202 while(!m_stop){
203 m_parser->run(ctx, * this);
204 if(ctx.m_currentToken == 0)
205 break;
207 switch(ctx.m_status){
208 case Parser_t::Ok:
209 for(size_t i = 0; i<ctx.m_aliasUsed.size(); i++)
210 ndbout_c("Used alias: %s -> %s",
211 ctx.m_aliasUsed[i]->name, ctx.m_aliasUsed[i]->realName);
212 break;
213 case Parser_t::NoLine:
214 case Parser_t::EmptyLine:
215 break;
216 default:
217 break;
222 static const int g_TimeOut = 1000;
224 void
225 CPCDAPISession::defineProcess(Parser_t::Context & /* unused */,
226 const class Properties & args){
228 CPCD::Process * p = new CPCD::Process(args, &m_cpcd);
230 CPCD::RequestStatus rs;
232 bool ret = m_cpcd.defineProcess(&rs, p);
233 if(!m_cpcd.loadingProcessList) {
234 m_output->println("define process");
235 m_output->println("status: %d", rs.getStatus());
236 if(ret == true){
237 m_output->println("id: %d", p->m_id);
238 if(p->m_processType == TEMPORARY){
239 m_temporaryProcesses.push_back(p->m_id);
241 } else {
242 m_output->println("errormessage: %s", rs.getErrMsg());
244 m_output->println("");
248 void
249 CPCDAPISession::undefineProcess(Parser_t::Context & /* unused */,
250 const class Properties & args){
251 Uint32 id;
252 CPCD::RequestStatus rs;
254 args.get("id", &id);
255 bool ret = m_cpcd.undefineProcess(&rs, id);
257 m_output->println("undefine process");
258 m_output->println("id: %d", id);
259 m_output->println("status: %d", rs.getStatus());
260 if(!ret)
261 m_output->println("errormessage: %s", rs.getErrMsg());
263 m_output->println("");
266 void
267 CPCDAPISession::startProcess(Parser_t::Context & /* unused */,
268 const class Properties & args){
269 Uint32 id;
270 CPCD::RequestStatus rs;
272 args.get("id", &id);
273 const int ret = m_cpcd.startProcess(&rs, id);
275 if(!m_cpcd.loadingProcessList) {
276 m_output->println("start process");
277 m_output->println("id: %d", id);
278 m_output->println("status: %d", rs.getStatus());
279 if(!ret)
280 m_output->println("errormessage: %s", rs.getErrMsg());
281 m_output->println("");
285 void
286 CPCDAPISession::stopProcess(Parser_t::Context & /* unused */,
287 const class Properties & args){
288 Uint32 id;
289 CPCD::RequestStatus rs;
291 args.get("id", &id);
292 int ret = m_cpcd.stopProcess(&rs, id);
294 m_output->println("stop process");
295 m_output->println("id: %d", id);
296 m_output->println("status: %d", rs.getStatus());
297 if(!ret)
298 m_output->println("errormessage: %s", rs.getErrMsg());
300 m_output->println("");
303 static const char *
304 propToString(Properties *prop, const char *key) {
305 static char buf[32];
306 const char *retval = NULL;
307 PropertiesType pt;
309 prop->getTypeOf(key, &pt);
310 switch(pt) {
311 case PropertiesType_Uint32:
312 Uint32 val;
313 prop->get(key, &val);
314 BaseString::snprintf(buf, sizeof buf, "%d", val);
315 retval = buf;
316 break;
317 case PropertiesType_char:
318 const char *str;
319 prop->get(key, &str);
320 retval = str;
321 break;
322 default:
323 BaseString::snprintf(buf, sizeof buf, "(unknown)");
324 retval = buf;
326 return retval;
329 void
330 CPCDAPISession::printProperty(Properties *prop, const char *key) {
331 m_output->println("%s: %s", key, propToString(prop, key));
334 void
335 CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
336 const class Properties & /* unused */){
337 m_cpcd.m_processes.lock();
338 MutexVector<CPCD::Process *> *proclist = m_cpcd.getProcessList();
340 m_output->println("start processes");
341 m_output->println("");
344 for(size_t i = 0; i < proclist->size(); i++) {
345 CPCD::Process *p = (*proclist)[i];
347 m_output->println("process");
349 m_output->println("id: %d", p->m_id);
350 m_output->println("name: %s", p->m_name.c_str());
351 m_output->println("path: %s", p->m_path.c_str());
352 m_output->println("args: %s", p->m_args.c_str());
353 m_output->println("type: %s", p->m_type.c_str());
354 m_output->println("cwd: %s", p->m_cwd.c_str());
355 m_output->println("env: %s", p->m_env.c_str());
356 m_output->println("owner: %s", p->m_owner.c_str());
357 m_output->println("group: %s", p->m_group.c_str());
358 m_output->println("runas: %s", p->m_runas.c_str());
359 m_output->println("stdin: %s", p->m_stdin.c_str());
360 m_output->println("stdout: %s", p->m_stdout.c_str());
361 m_output->println("stderr: %s", p->m_stderr.c_str());
362 m_output->println("ulimit: %s", p->m_ulimit.c_str());
363 m_output->println("shutdown: %s", p->m_shutdown_options.c_str());
364 switch(p->m_status){
365 case STOPPED:
366 m_output->println("status: stopped");
367 break;
368 case STARTING:
369 m_output->println("status: starting");
370 break;
371 case RUNNING:
372 m_output->println("status: running");
373 break;
374 case STOPPING:
375 m_output->println("status: stopping");
376 break;
379 m_output->println("");
383 m_output->println("end processes");
384 m_output->println("");
386 m_cpcd.m_processes.unlock();
389 void
390 CPCDAPISession::showVersion(Parser_t::Context & /* unused */,
391 const class Properties & args){
392 CPCD::RequestStatus rs;
394 m_output->println("show version");
395 m_output->println("compile time: %s %s", __DATE__, __TIME__);
397 m_output->println("");
400 template class Vector<ParserRow<CPCDAPISession> const*>;