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 */
19 #include <Properties.hpp>
20 #include <socket_io.h>
22 #include "APIService.hpp"
25 #include <OutputStream.hpp>
29 const char * realName;
31 const ArgType argType;
32 const ArgRequired argRequired;
33 const ArgMinMax argMinMax;
36 void (T::* function)(const class Properties & args);
37 const char * description;
40 #define CPCD_CMD(name, fun, desc) \
43 ParserRow<CPCDAPISession>::Cmd, \
44 ParserRow<CPCDAPISession>::String, \
45 ParserRow<CPCDAPISession>::Optional, \
46 ParserRow<CPCDAPISession>::IgnoreMinMax, \
51 #define CPCD_ARG(name, type, opt, desc) \
54 ParserRow<CPCDAPISession>::Arg, \
55 ParserRow<CPCDAPISession>::type, \
56 ParserRow<CPCDAPISession>::opt, \
57 ParserRow<CPCDAPISession>::IgnoreMinMax, \
62 #define CPCD_ARG2(name, type, opt, min, max, desc) \
65 ParserRow<CPCDAPISession>::Arg, \
66 ParserRow<CPCDAPISession>::type, \
67 ParserRow<CPCDAPISession>::opt, \
68 ParserRow<CPCDAPISession>::IgnoreMinMax, \
76 ParserRow<CPCDAPISession>::Arg, \
77 ParserRow<CPCDAPISession>::Int, \
78 ParserRow<CPCDAPISession>::Optional, \
79 ParserRow<CPCDAPISession>::IgnoreMinMax, \
84 #define CPCD_CMD_ALIAS(name, realName, fun) \
87 ParserRow<CPCDAPISession>::CmdAlias, \
88 ParserRow<CPCDAPISession>::Int, \
89 ParserRow<CPCDAPISession>::Optional, \
90 ParserRow<CPCDAPISession>::IgnoreMinMax, \
95 #define CPCD_ARG_ALIAS(name, realName, fun) \
98 ParserRow<CPCDAPISession>::ArgAlias, \
99 ParserRow<CPCDAPISession>::Int, \
100 ParserRow<CPCDAPISession>::Optional, \
101 ParserRow<CPCDAPISession>::IgnoreMinMax, \
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
, ""),
143 CPCDAPISession::CPCDAPISession(NDB_SOCKET_TYPE sock
,
145 : SocketServer::Session(sock
)
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)
157 m_input
= new FileInputStream(f
);
158 m_parser
= new Parser
<CPCDAPISession
>(commands
, *m_input
, true, true, true);
161 CPCDAPISession::~CPCDAPISession() {
167 CPCDAPISession::runSession(){
168 Parser_t::Context ctx
;
170 m_parser
->run(ctx
, * this);
171 if(ctx
.m_currentToken
== 0)
174 switch(ctx
.m_status
){
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
);
180 case Parser_t::NoLine
:
181 case Parser_t::EmptyLine
:
187 NDB_CLOSE_SOCKET(m_socket
);
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
);
200 CPCDAPISession::loadFile(){
201 Parser_t::Context ctx
;
203 m_parser
->run(ctx
, * this);
204 if(ctx
.m_currentToken
== 0)
207 switch(ctx
.m_status
){
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
);
213 case Parser_t::NoLine
:
214 case Parser_t::EmptyLine
:
222 static const int g_TimeOut
= 1000;
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());
237 m_output
->println("id: %d", p
->m_id
);
238 if(p
->m_processType
== TEMPORARY
){
239 m_temporaryProcesses
.push_back(p
->m_id
);
242 m_output
->println("errormessage: %s", rs
.getErrMsg());
244 m_output
->println("");
249 CPCDAPISession::undefineProcess(Parser_t::Context
& /* unused */,
250 const class Properties
& args
){
252 CPCD::RequestStatus rs
;
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());
261 m_output
->println("errormessage: %s", rs
.getErrMsg());
263 m_output
->println("");
267 CPCDAPISession::startProcess(Parser_t::Context
& /* unused */,
268 const class Properties
& args
){
270 CPCD::RequestStatus rs
;
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());
280 m_output
->println("errormessage: %s", rs
.getErrMsg());
281 m_output
->println("");
286 CPCDAPISession::stopProcess(Parser_t::Context
& /* unused */,
287 const class Properties
& args
){
289 CPCD::RequestStatus rs
;
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());
298 m_output
->println("errormessage: %s", rs
.getErrMsg());
300 m_output
->println("");
304 propToString(Properties
*prop
, const char *key
) {
306 const char *retval
= NULL
;
309 prop
->getTypeOf(key
, &pt
);
311 case PropertiesType_Uint32
:
313 prop
->get(key
, &val
);
314 BaseString::snprintf(buf
, sizeof buf
, "%d", val
);
317 case PropertiesType_char
:
319 prop
->get(key
, &str
);
323 BaseString::snprintf(buf
, sizeof buf
, "(unknown)");
330 CPCDAPISession::printProperty(Properties
*prop
, const char *key
) {
331 m_output
->println("%s: %s", key
, propToString(prop
, key
));
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());
366 m_output
->println("status: stopped");
369 m_output
->println("status: starting");
372 m_output
->println("status: running");
375 m_output
->println("status: stopping");
379 m_output
->println("");
383 m_output
->println("end processes");
384 m_output
->println("");
386 m_cpcd
.m_processes
.unlock();
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*>;