00001 /* Copyright (C) 2003 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #include <ndb_global.h> 00018 #include <ctype.h> 00019 00020 #include <uucode.h> 00021 #include <socket_io.h> 00022 #include <ndb_version.h> 00023 #include <mgmapi.h> 00024 #include <EventLogger.hpp> 00025 #include <signaldata/SetLogLevelOrd.hpp> 00026 #include <LogLevel.hpp> 00027 #include <BaseString.hpp> 00028 00029 #include <ConfigValues.hpp> 00030 #include <mgmapi_configuration.hpp> 00031 #include <Vector.hpp> 00032 #include "Services.hpp" 00033 #include "../mgmapi/ndb_logevent.hpp" 00034 00035 #include <base64.h> 00036 00037 extern bool g_StopServer; 00038 extern bool g_RestartServer; 00039 extern EventLogger g_eventLogger; 00040 00041 static const unsigned int MAX_READ_TIMEOUT = 1000 ; 00042 static const unsigned int MAX_WRITE_TIMEOUT = 100 ; 00043 00057 #define MGM_CMD(name, fun, desc) \ 00058 { name, \ 00059 0, \ 00060 ParserRow<MgmApiSession>::Cmd, \ 00061 ParserRow<MgmApiSession>::String, \ 00062 ParserRow<MgmApiSession>::Optional, \ 00063 ParserRow<MgmApiSession>::IgnoreMinMax, \ 00064 0, 0, \ 00065 fun, \ 00066 desc, 0 } 00067 00068 #define MGM_ARG(name, type, opt, desc) \ 00069 { name, \ 00070 0, \ 00071 ParserRow<MgmApiSession>::Arg, \ 00072 ParserRow<MgmApiSession>::type, \ 00073 ParserRow<MgmApiSession>::opt, \ 00074 ParserRow<MgmApiSession>::IgnoreMinMax, \ 00075 0, 0, \ 00076 0, \ 00077 desc, 0 } 00078 00079 #define MGM_ARG2(name, type, opt, min, max, desc) \ 00080 { name, \ 00081 0, \ 00082 ParserRow<MgmApiSession>::Arg, \ 00083 ParserRow<MgmApiSession>::type, \ 00084 ParserRow<MgmApiSession>::opt, \ 00085 ParserRow<MgmApiSession>::IgnoreMinMax, \ 00086 min, max, \ 00087 0, \ 00088 desc, 0 } 00089 00090 #define MGM_END() \ 00091 { 0, \ 00092 0, \ 00093 ParserRow<MgmApiSession>::Arg, \ 00094 ParserRow<MgmApiSession>::Int, \ 00095 ParserRow<MgmApiSession>::Optional, \ 00096 ParserRow<MgmApiSession>::IgnoreMinMax, \ 00097 0, 0, \ 00098 0, \ 00099 0, 0 } 00100 00101 #define MGM_CMD_ALIAS(name, realName, fun) \ 00102 { name, \ 00103 realName, \ 00104 ParserRow<MgmApiSession>::CmdAlias, \ 00105 ParserRow<MgmApiSession>::Int, \ 00106 ParserRow<MgmApiSession>::Optional, \ 00107 ParserRow<MgmApiSession>::IgnoreMinMax, \ 00108 0, 0, \ 00109 0, \ 00110 0, 0 } 00111 00112 #define MGM_ARG_ALIAS(name, realName, fun) \ 00113 { name, \ 00114 realName, \ 00115 ParserRow<MgmApiSession>::ArgAlias, \ 00116 ParserRow<MgmApiSession>::Int, \ 00117 ParserRow<MgmApiSession>::Optional, \ 00118 ParserRow<MgmApiSession>::IgnoreMinMax, \ 00119 0, 0, \ 00120 0, \ 00121 0, 0 } 00122 00123 const 00124 ParserRow<MgmApiSession> commands[] = { 00125 MGM_CMD("get config", &MgmApiSession::getConfig, ""), 00126 MGM_ARG("version", Int, Mandatory, "Configuration version number"), 00127 MGM_ARG("node", Int, Optional, "Node ID"), 00128 00129 MGM_CMD("get nodeid", &MgmApiSession::get_nodeid, ""), 00130 MGM_ARG("version", Int, Mandatory, "Configuration version number"), 00131 MGM_ARG("nodetype", Int, Mandatory, "Node type"), 00132 MGM_ARG("transporter", String, Optional, "Transporter type"), 00133 MGM_ARG("nodeid", Int, Optional, "Node ID"), 00134 MGM_ARG("user", String, Mandatory, "Password"), 00135 MGM_ARG("password", String, Mandatory, "Password"), 00136 MGM_ARG("public key", String, Mandatory, "Public key"), 00137 MGM_ARG("endian", String, Optional, "Endianness"), 00138 MGM_ARG("name", String, Optional, "Name of connection"), 00139 MGM_ARG("timeout", Int, Optional, "Timeout in seconds"), 00140 MGM_ARG("log_event", Int, Optional, "Log failure in cluster log"), 00141 00142 MGM_CMD("get version", &MgmApiSession::getVersion, ""), 00143 00144 MGM_CMD("get status", &MgmApiSession::getStatus, ""), 00145 00146 MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""), 00147 00148 MGM_CMD("restart node", &MgmApiSession::restart_v1, ""), 00149 MGM_ARG("node", String, Mandatory, "Nodes to restart"), 00150 MGM_ARG("initialstart", Int, Optional, "Initial start"), 00151 MGM_ARG("nostart", Int, Optional, "No start"), 00152 MGM_ARG("abort", Int, Optional, "Abort"), 00153 00154 MGM_CMD("restart node v2", &MgmApiSession::restart_v2, ""), 00155 MGM_ARG("node", String, Mandatory, "Nodes to restart"), 00156 MGM_ARG("initialstart", Int, Optional, "Initial start"), 00157 MGM_ARG("nostart", Int, Optional, "No start"), 00158 MGM_ARG("abort", Int, Optional, "Abort"), 00159 00160 MGM_CMD("restart all", &MgmApiSession::restartAll, ""), 00161 MGM_ARG("initialstart", Int, Optional, "Initial start"), 00162 MGM_ARG("nostart", Int, Optional, "No start"), 00163 MGM_ARG("abort", Int, Optional, "Abort"), 00164 00165 MGM_CMD("insert error", &MgmApiSession::insertError, ""), 00166 MGM_ARG("node", Int, Mandatory, "Node to receive error"), 00167 MGM_ARG("error", Int, Mandatory, "Errorcode to insert"), 00168 00169 MGM_CMD("set trace", &MgmApiSession::setTrace, ""), 00170 MGM_ARG("node", Int, Mandatory, "Node"), 00171 MGM_ARG("trace", Int, Mandatory, "Trace number"), 00172 00173 MGM_CMD("log signals", &MgmApiSession::logSignals, ""), 00174 MGM_ARG("node", Int, Mandatory, "Node"), 00175 MGM_ARG("blocks", String, Mandatory, "Blocks (space separated)"), 00176 MGM_ARG("in", Int, Mandatory, "Log input signals"), 00177 MGM_ARG("out", Int, Mandatory, "Log output signals"), 00178 00179 MGM_CMD("start signallog", &MgmApiSession::startSignalLog, ""), 00180 MGM_ARG("node", Int, Mandatory, "Node"), 00181 00182 MGM_CMD("stop signallog", &MgmApiSession::stopSignalLog, ""), 00183 MGM_ARG("node", Int, Mandatory, "Node"), 00184 00185 MGM_CMD("dump state", &MgmApiSession::dumpState, ""), 00186 MGM_ARG("node", Int, Mandatory ,"Node"), 00187 MGM_ARG("args", String, Mandatory, "Args(space separated int's)"), 00188 00189 MGM_CMD("start backup", &MgmApiSession::startBackup, ""), 00190 MGM_ARG("completed", Int, Optional ,"Wait until completed"), 00191 00192 MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""), 00193 MGM_ARG("id", Int, Mandatory, "Backup id"), 00194 00195 MGM_CMD("stop", &MgmApiSession::stop_v1, ""), 00196 MGM_ARG("node", String, Mandatory, "Node"), 00197 MGM_ARG("abort", Int, Mandatory, "Node"), 00198 00199 MGM_CMD("stop v2", &MgmApiSession::stop_v2, ""), 00200 MGM_ARG("node", String, Mandatory, "Node"), 00201 MGM_ARG("abort", Int, Mandatory, "Node"), 00202 00203 MGM_CMD("stop all", &MgmApiSession::stopAll, ""), 00204 MGM_ARG("abort", Int, Mandatory, "Node"), 00205 MGM_ARG("stop", String, Optional, "MGM/DB or both"), 00206 00207 MGM_CMD("enter single user", &MgmApiSession::enterSingleUser, ""), 00208 MGM_ARG("nodeId", Int, Mandatory, "Node"), 00209 00210 MGM_CMD("exit single user", &MgmApiSession::exitSingleUser, ""), 00211 00212 00213 MGM_CMD("start", &MgmApiSession::start, ""), 00214 MGM_ARG("node", Int, Mandatory, "Node"), 00215 00216 MGM_CMD("start all", &MgmApiSession::startAll, ""), 00217 00218 MGM_CMD("bye", &MgmApiSession::bye, ""), 00219 00220 MGM_CMD("end session", &MgmApiSession::endSession, ""), 00221 00222 MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""), 00223 MGM_ARG("node", Int, Mandatory, "Node"), 00224 MGM_ARG("category", Int, Mandatory, "Event category"), 00225 MGM_ARG("level", Int, Mandatory, "Log level (0-15)"), 00226 00227 MGM_CMD("set cluster loglevel", &MgmApiSession::setClusterLogLevel, ""), 00228 MGM_ARG("node", Int, Mandatory, "Node"), 00229 MGM_ARG("category", Int, Mandatory, "Event category"), 00230 MGM_ARG("level", Int, Mandatory, "Log level (0-15)"), 00231 00232 MGM_CMD("set logfilter", &MgmApiSession::setLogFilter, ""), 00233 MGM_ARG("level", Int, Mandatory, "Severety level"), 00234 MGM_ARG("enable", Int, Mandatory, "1=disable, 0=enable, -1=toggle"), 00235 00236 MGM_CMD("set parameter", &MgmApiSession::setParameter, ""), 00237 MGM_ARG("node", String, Mandatory, "Node"), 00238 MGM_ARG("parameter", String, Mandatory, "Parameter"), 00239 MGM_ARG("value", String, Mandatory, "Value"), 00240 00241 MGM_CMD("set connection parameter", 00242 &MgmApiSession::setConnectionParameter, ""), 00243 MGM_ARG("node1", String, Mandatory, "Node1 ID"), 00244 MGM_ARG("node2", String, Mandatory, "Node2 ID"), 00245 MGM_ARG("param", String, Mandatory, "Parameter"), 00246 MGM_ARG("value", String, Mandatory, "Value"), 00247 00248 MGM_CMD("get connection parameter", 00249 &MgmApiSession::getConnectionParameter, ""), 00250 MGM_ARG("node1", String, Mandatory, "Node1 ID"), 00251 MGM_ARG("node2", String, Mandatory, "Node2 ID"), 00252 MGM_ARG("param", String, Mandatory, "Parameter"), 00253 00254 MGM_CMD("listen event", &MgmApiSession::listen_event, ""), 00255 MGM_ARG("node", Int, Optional, "Node"), 00256 MGM_ARG("parsable", Int, Optional, "Parsable"), 00257 MGM_ARG("filter", String, Mandatory, "Event category"), 00258 00259 MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""), 00260 00261 MGM_CMD("check connection", &MgmApiSession::check_connection, ""), 00262 00263 MGM_CMD("transporter connect", &MgmApiSession::transporter_connect, ""), 00264 00265 MGM_CMD("get mgmd nodeid", &MgmApiSession::get_mgmd_nodeid, ""), 00266 00267 MGM_CMD("report event", &MgmApiSession::report_event, ""), 00268 MGM_ARG("length", Int, Mandatory, "Length"), 00269 MGM_ARG("data", String, Mandatory, "Data"), 00270 00271 MGM_END() 00272 }; 00273 00274 struct PurgeStruct 00275 { 00276 NodeBitmask free_nodes;/* free nodes as reported 00277 * by ndbd in apiRegReqConf 00278 */ 00279 BaseString *str; 00280 NDB_TICKS tick; 00281 }; 00282 00283 MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock) 00284 : SocketServer::Session(sock), m_mgmsrv(mgm) 00285 { 00286 DBUG_ENTER("MgmApiSession::MgmApiSession"); 00287 m_input = new SocketInputStream(sock); 00288 m_output = new SocketOutputStream(sock); 00289 m_parser = new Parser_t(commands, *m_input, true, true, true); 00290 m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); 00291 m_stopSelf= 0; 00292 DBUG_VOID_RETURN; 00293 } 00294 00295 MgmApiSession::~MgmApiSession() 00296 { 00297 DBUG_ENTER("MgmApiSession::~MgmApiSession"); 00298 if (m_input) 00299 delete m_input; 00300 if (m_output) 00301 delete m_output; 00302 if (m_parser) 00303 delete m_parser; 00304 if (m_allocated_resources) 00305 delete m_allocated_resources; 00306 if(m_socket != NDB_INVALID_SOCKET) 00307 { 00308 NDB_CLOSE_SOCKET(m_socket); 00309 m_socket= NDB_INVALID_SOCKET; 00310 } 00311 if(m_stopSelf < 0) 00312 g_RestartServer= true; 00313 if(m_stopSelf) 00314 g_StopServer= true; 00315 DBUG_VOID_RETURN; 00316 } 00317 00318 void 00319 MgmApiSession::runSession() 00320 { 00321 DBUG_ENTER("MgmApiSession::runSession"); 00322 00323 Parser_t::Context ctx; 00324 while(!m_stop) { 00325 m_parser->run(ctx, *this); 00326 00327 if(ctx.m_currentToken == 0) 00328 break; 00329 00330 switch(ctx.m_status) { 00331 case Parser_t::UnknownCommand: 00332 #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT 00333 /* Backwards compatibility for old NDBs that still use 00334 * the old "GET CONFIG" command. 00335 */ 00336 size_t i; 00337 for(i=0; i<strlen(ctx.m_currentToken); i++) 00338 ctx.m_currentToken[i] = toupper(ctx.m_currentToken[i]); 00339 00340 if(strncmp("GET CONFIG ", 00341 ctx.m_currentToken, 00342 strlen("GET CONFIG ")) == 0) 00343 getConfig_old(ctx); 00344 #endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */ 00345 break; 00346 default: 00347 break; 00348 } 00349 } 00350 if(m_socket != NDB_INVALID_SOCKET) 00351 { 00352 NDB_CLOSE_SOCKET(m_socket); 00353 m_socket= NDB_INVALID_SOCKET; 00354 } 00355 00356 DBUG_VOID_RETURN; 00357 } 00358 00359 #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT 00360 void 00361 MgmApiSession::getConfig_old(Parser_t::Context &ctx) { 00362 Properties args; 00363 00364 Uint32 version, node; 00365 00366 if(sscanf(ctx.m_currentToken, "GET CONFIG %d %d", 00367 (int *)&version, (int *)&node) != 2) { 00368 m_output->println("Expected 2 arguments for GET CONFIG"); 00369 return; 00370 } 00371 00372 /* Put arguments in properties object so we can call the real function */ 00373 args.put("version", version); 00374 args.put("node", node); 00375 getConfig_common(ctx, args, true); 00376 } 00377 #endif /* MGM_GET_CONFIG_BACKWARDS_COMPAT */ 00378 00379 void 00380 MgmApiSession::getConfig(Parser_t::Context &ctx, 00381 const class Properties &args) { 00382 getConfig_common(ctx, args); 00383 } 00384 00385 static Properties * 00386 backward(const char * base, const Properties* reply){ 00387 Properties * ret = new Properties(); 00388 Properties::Iterator it(reply); 00389 for(const char * name = it.first(); name != 0; name=it.next()){ 00390 PropertiesType type; 00391 reply->getTypeOf(name, &type); 00392 switch(type){ 00393 case PropertiesType_Uint32:{ 00394 Uint32 val; 00395 reply->get(name, &val); 00396 ret->put(name, val); 00397 } 00398 break; 00399 case PropertiesType_char: 00400 { 00401 const char * val; 00402 reply->get(name, &val); 00403 ret->put(name, val); 00404 if(!strcmp(name, "Type") && !strcmp(val, "DB")){ 00405 ret->put("NoOfDiskBufferPages", (unsigned)0); 00406 ret->put("NoOfDiskFiles", (unsigned)0); 00407 ret->put("NoOfDiskClusters", (unsigned)0); 00408 ret->put("NoOfFreeDiskClusters", (unsigned)0); 00409 ret->put("NoOfDiskClustersPerDiskFile", (unsigned)0); 00410 ret->put("NoOfConcurrentCheckpointsDuringRestart", (unsigned)1); 00411 ret->put("NoOfConcurrentCheckpointsAfterRestart", (unsigned)1); 00412 ret->put("NoOfConcurrentProcessesHandleTakeover", (unsigned)1); 00413 } 00414 } 00415 break; 00416 case PropertiesType_Properties: 00417 { 00418 const Properties * recurse; 00419 reply->get(name, &recurse); 00420 Properties * val = backward(name, recurse); 00421 ret->put(name, val); 00422 } 00423 break; 00424 case PropertiesType_Uint64: 00425 break; 00426 } 00427 } 00428 return ret; 00429 } 00430 00431 void 00432 MgmApiSession::get_nodeid(Parser_t::Context &, 00433 const class Properties &args) 00434 { 00435 const char *cmd= "get nodeid reply"; 00436 Uint32 version, nodeid= 0, nodetype= 0xff; 00437 Uint32 timeout= 20; // default seconds timeout 00438 const char * transporter; 00439 const char * user; 00440 const char * password; 00441 const char * public_key; 00442 const char * endian= NULL; 00443 const char * name= NULL; 00444 Uint32 log_event= 1; 00445 bool log_event_version; 00446 union { long l; char c[sizeof(long)]; } endian_check; 00447 00448 args.get("version", &version); 00449 args.get("nodetype", &nodetype); 00450 args.get("transporter", &transporter); 00451 args.get("nodeid", &nodeid); 00452 args.get("user", &user); 00453 args.get("password", &password); 00454 args.get("public key", &public_key); 00455 args.get("endian", &endian); 00456 args.get("name", &name); 00457 args.get("timeout", &timeout); 00458 /* for backwards compatability keep track if client uses new protocol */ 00459 log_event_version= args.get("log_event", &log_event); 00460 00461 endian_check.l = 1; 00462 if(endian 00463 && strcmp(endian,(endian_check.c[sizeof(long)-1])?"big":"little")!=0) { 00464 m_output->println(cmd); 00465 m_output->println("result: Node does not have the same endianness as the management server."); 00466 m_output->println(""); 00467 return; 00468 } 00469 00470 bool compatible; 00471 switch (nodetype) { 00472 case NODE_TYPE_MGM: 00473 case NODE_TYPE_API: 00474 compatible = ndbCompatible_mgmt_api(NDB_VERSION, version); 00475 break; 00476 case NODE_TYPE_DB: 00477 compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version); 00478 break; 00479 default: 00480 m_output->println(cmd); 00481 m_output->println("result: unknown nodetype %d", nodetype); 00482 m_output->println(""); 00483 return; 00484 } 00485 00486 struct sockaddr_in addr; 00487 SOCKET_SIZE_TYPE addrlen= sizeof(addr); 00488 int r = getpeername(m_socket, (struct sockaddr*)&addr, &addrlen); 00489 if (r != 0 ) { 00490 m_output->println(cmd); 00491 m_output->println("result: getpeername(%d) failed, err= %d", m_socket, r); 00492 m_output->println(""); 00493 return; 00494 } 00495 00496 NodeId tmp= nodeid; 00497 if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){ 00498 BaseString error_string; 00499 int error_code; 00500 NDB_TICKS tick= 0; 00501 /* only report error on second attempt as not to clog the cluster log */ 00502 while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, 00503 (struct sockaddr*)&addr, &addrlen, 00504 error_code, error_string, 00505 tick == 0 ? 0 : log_event)) 00506 { 00507 /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */ 00508 if (tick == 0 && error_code != NDB_MGM_ALLOCID_CONFIG_MISMATCH) 00509 { 00510 // attempt to free any timed out reservations 00511 tick= NdbTick_CurrentMillisecond(); 00512 struct PurgeStruct ps; 00513 m_mgmsrv.get_connected_nodes(ps.free_nodes); 00514 // invert connected_nodes to get free nodes 00515 ps.free_nodes.bitXORC(NodeBitmask()); 00516 ps.str= 0; 00517 ps.tick= tick; 00518 m_mgmsrv.get_socket_server()-> 00519 foreachSession(stop_session_if_timed_out,&ps); 00520 m_mgmsrv.get_socket_server()->checkSessions(); 00521 error_string = ""; 00522 continue; 00523 } 00524 const char *alias; 00525 const char *str; 00526 alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type) 00527 nodetype, &str); 00528 m_output->println(cmd); 00529 m_output->println("result: %s", error_string.c_str()); 00530 /* only use error_code protocol if client knows about it */ 00531 if (log_event_version) 00532 m_output->println("error_code: %d", error_code); 00533 m_output->println(""); 00534 return; 00535 } 00536 } 00537 00538 #if 0 00539 if (!compatible){ 00540 m_output->println(cmd); 00541 m_output->println("result: incompatible version mgmt 0x%x and node 0x%x", 00542 NDB_VERSION, version); 00543 m_output->println(""); 00544 return; 00545 } 00546 #endif 00547 00548 m_output->println(cmd); 00549 m_output->println("nodeid: %u", tmp); 00550 m_output->println("result: Ok"); 00551 m_output->println(""); 00552 m_allocated_resources->reserve_node(tmp, timeout*1000); 00553 00554 if (name) 00555 g_eventLogger.info("Node %d: %s", tmp, name); 00556 00557 return; 00558 } 00559 00560 void 00561 MgmApiSession::getConfig_common(Parser_t::Context &, 00562 const class Properties &args, 00563 bool compat) { 00564 Uint32 version, node = 0; 00565 00566 args.get("version", &version); 00567 args.get("node", &node); 00568 00569 const Config *conf = m_mgmsrv.getConfig(); 00570 if(conf == NULL) { 00571 m_output->println("get config reply"); 00572 m_output->println("result: Could not fetch configuration"); 00573 m_output->println(""); 00574 return; 00575 } 00576 00577 if(version > 0 && version < makeVersion(3, 5, 0) && compat){ 00578 Properties *reply = backward("", conf->m_oldConfig); 00579 reply->put("Version", version); 00580 reply->put("LocalNodeId", node); 00581 00582 backward("", reply); 00583 //reply->print(); 00584 00585 const Uint32 size = reply->getPackedSize(); 00586 Uint32 *buffer = new Uint32[size/4+1]; 00587 00588 reply->pack(buffer); 00589 delete reply; 00590 00591 const int uurows = (size + 44)/45; 00592 char * uubuf = new char[uurows * 62+5]; 00593 00594 const int uusz = uuencode_mem(uubuf, (char *)buffer, size); 00595 delete[] buffer; 00596 00597 m_output->println("GET CONFIG %d %d %d %d %d", 00598 0, version, node, size, uusz); 00599 00600 m_output->println("begin 664 Ndb_cfg.bin"); 00601 00602 /* XXX Need to write directly to the socket, because the uubuf is not 00603 * NUL-terminated. This could/should probably be done in a nicer way. 00604 */ 00605 write_socket(m_socket, MAX_WRITE_TIMEOUT, uubuf, uusz); 00606 delete[] uubuf; 00607 00608 m_output->println("end"); 00609 m_output->println(""); 00610 return; 00611 } 00612 00613 if(compat){ 00614 m_output->println("GET CONFIG %d %d %d %d %d",1, version, 0, 0, 0); 00615 return; 00616 } 00617 00618 if(node != 0){ 00619 bool compatible; 00620 switch (m_mgmsrv.getNodeType(node)) { 00621 case NDB_MGM_NODE_TYPE_NDB: 00622 compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version); 00623 break; 00624 case NDB_MGM_NODE_TYPE_API: 00625 case NDB_MGM_NODE_TYPE_MGM: 00626 compatible = ndbCompatible_mgmt_api(NDB_VERSION, version); 00627 break; 00628 default: 00629 m_output->println("get config"); 00630 m_output->println("result: unrecognignized node type"); 00631 m_output->println(""); 00632 return; 00633 } 00634 00635 if (!compatible){ 00636 m_output->println("get config"); 00637 m_output->println("result: incompatible version mgmt 0x%x and node 0x%x", 00638 NDB_VERSION, version); 00639 m_output->println(""); 00640 return; 00641 } 00642 } 00643 00644 NdbMutex_Lock(m_mgmsrv.m_configMutex); 00645 const ConfigValues * cfg = &conf->m_configValues->m_config; 00646 const Uint32 size = cfg->getPackedSize(); 00647 00648 UtilBuffer src; 00649 cfg->pack(src); 00650 NdbMutex_Unlock(m_mgmsrv.m_configMutex); 00651 00652 char *tmp_str = (char *) malloc(base64_needed_encoded_length(src.length())); 00653 int res = base64_encode(src.get_data(), src.length(), tmp_str); 00654 00655 m_output->println("get config reply"); 00656 m_output->println("result: Ok"); 00657 m_output->println("Content-Length: %d", strlen(tmp_str)); 00658 m_output->println("Content-Type: ndbconfig/octet-stream"); 00659 m_output->println("Content-Transfer-Encoding: base64"); 00660 m_output->println(""); 00661 m_output->println(tmp_str); 00662 00663 free(tmp_str); 00664 return; 00665 } 00666 00667 void 00668 MgmApiSession::insertError(Parser<MgmApiSession>::Context &, 00669 Properties const &args) { 00670 Uint32 node = 0, error = 0; 00671 00672 args.get("node", &node); 00673 args.get("error", &error); 00674 00675 int result = m_mgmsrv.insertError(node, error); 00676 00677 m_output->println("insert error reply"); 00678 if(result != 0) 00679 m_output->println("result: %s", get_error_text(result)); 00680 else 00681 m_output->println("result: Ok"); 00682 m_output->println(""); 00683 } 00684 00685 void 00686 MgmApiSession::setTrace(Parser<MgmApiSession>::Context &, 00687 Properties const &args) { 00688 Uint32 node = 0, trace = 0; 00689 00690 args.get("node", &node); 00691 args.get("trace", &trace); 00692 00693 int result = m_mgmsrv.setTraceNo(node, trace); 00694 00695 m_output->println("set trace reply"); 00696 if(result != 0) 00697 m_output->println("result: %s", get_error_text(result)); 00698 else 00699 m_output->println("result: Ok"); 00700 m_output->println(""); 00701 } 00702 00703 void 00704 MgmApiSession::getVersion(Parser<MgmApiSession>::Context &, 00705 Properties const &) { 00706 m_output->println("version"); 00707 m_output->println("id: %d", NDB_VERSION); 00708 m_output->println("major: %d", getMajor(NDB_VERSION)); 00709 m_output->println("minor: %d", getMinor(NDB_VERSION)); 00710 m_output->println("string: %s", NDB_VERSION_STRING); 00711 m_output->println(""); 00712 } 00713 00714 void 00715 MgmApiSession::startBackup(Parser<MgmApiSession>::Context &, 00716 Properties const &args) { 00717 DBUG_ENTER("MgmApiSession::startBackup"); 00718 unsigned backupId; 00719 Uint32 completed= 2; 00720 int result; 00721 00722 args.get("completed", &completed); 00723 00724 result = m_mgmsrv.startBackup(backupId, completed); 00725 00726 m_output->println("start backup reply"); 00727 if(result != 0) 00728 { 00729 m_output->println("result: %s", get_error_text(result)); 00730 } 00731 else{ 00732 m_output->println("result: Ok"); 00733 if (completed) 00734 m_output->println("id: %d", backupId); 00735 } 00736 m_output->println(""); 00737 DBUG_VOID_RETURN; 00738 } 00739 00740 void 00741 MgmApiSession::abortBackup(Parser<MgmApiSession>::Context &, 00742 Properties const &args) { 00743 Uint32 id = 0; 00744 00745 args.get("id", &id); 00746 00747 int result = m_mgmsrv.abortBackup(id); 00748 00749 m_output->println("abort backup reply"); 00750 if(result != 0) 00751 m_output->println("result: %s", get_error_text(result)); 00752 else 00753 m_output->println("result: Ok"); 00754 m_output->println(""); 00755 } 00756 00757 /*****************************************************************************/ 00758 00759 void 00760 MgmApiSession::dumpState(Parser<MgmApiSession>::Context &, 00761 Properties const &args) { 00762 Uint32 node; 00763 BaseString args_str; 00764 00765 args.get("node", &node); 00766 args.get("args", args_str); 00767 00768 int result = m_mgmsrv.dumpState(node, args_str.c_str()); 00769 m_output->println("dump state reply"); 00770 if(result != 0) 00771 m_output->println("result: %s", get_error_text(result)); 00772 else 00773 m_output->println("result: Ok"); 00774 m_output->println(""); 00775 } 00776 00777 00778 void 00779 MgmApiSession::bye(Parser<MgmApiSession>::Context &, 00780 Properties const &) { 00781 m_stop = true; 00782 } 00783 00784 void 00785 MgmApiSession::endSession(Parser<MgmApiSession>::Context &, 00786 Properties const &) { 00787 if(m_allocated_resources) 00788 delete m_allocated_resources; 00789 00790 m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); 00791 00792 m_output->println("end session reply"); 00793 } 00794 00795 void 00796 MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &, 00797 Properties const &args) { 00798 const char *reply= "set cluster loglevel reply"; 00799 Uint32 node, level, cat; 00800 BaseString errorString; 00801 SetLogLevelOrd logLevel; 00802 int result; 00803 DBUG_ENTER("MgmApiSession::setClusterLogLevel"); 00804 args.get("node", &node); 00805 args.get("category", &cat); 00806 args.get("level", &level); 00807 00808 DBUG_PRINT("enter",("node=%d, category=%d, level=%d", node, cat, level)); 00809 00810 /* XXX should use constants for this value */ 00811 if(level > 15) { 00812 m_output->println(reply); 00813 m_output->println("result: Invalid loglevel %d", level); 00814 m_output->println(""); 00815 DBUG_VOID_RETURN; 00816 } 00817 00818 LogLevel::EventCategory category= 00819 (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL); 00820 00821 m_mgmsrv.m_event_listner.lock(); 00822 if (m_mgmsrv.m_event_listner[0].m_logLevel.setLogLevel(category,level)) 00823 { 00824 m_output->println(reply); 00825 m_output->println("result: Invalid category %d", category); 00826 m_output->println(""); 00827 m_mgmsrv.m_event_listner.unlock(); 00828 DBUG_VOID_RETURN; 00829 } 00830 m_mgmsrv.m_event_listner.unlock(); 00831 00832 { 00833 LogLevel tmp; 00834 m_mgmsrv.m_event_listner.update_max_log_level(tmp); 00835 } 00836 00837 m_output->println(reply); 00838 m_output->println("result: Ok"); 00839 m_output->println(""); 00840 DBUG_VOID_RETURN; 00841 } 00842 00843 void 00844 MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &, 00845 Properties const &args) { 00846 Uint32 node = 0, level = 0, cat; 00847 BaseString errorString; 00848 SetLogLevelOrd logLevel; 00849 int result; 00850 logLevel.clear(); 00851 args.get("node", &node); 00852 args.get("category", &cat); 00853 args.get("level", &level); 00854 00855 /* XXX should use constants for this value */ 00856 if(level > 15) { 00857 m_output->println("set loglevel reply"); 00858 m_output->println("result: Invalid loglevel", errorString.c_str()); 00859 m_output->println(""); 00860 return; 00861 } 00862 00863 LogLevel::EventCategory category= 00864 (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL); 00865 00866 { 00867 LogLevel ll; 00868 ll.setLogLevel(category,level); 00869 m_mgmsrv.m_event_listner.update_max_log_level(ll); 00870 } 00871 00872 m_output->println("set loglevel reply"); 00873 m_output->println("result: Ok"); 00874 m_output->println(""); 00875 } 00876 00877 void 00878 MgmApiSession::stopSignalLog(Parser<MgmApiSession>::Context &, 00879 Properties const &args) { 00880 Uint32 node; 00881 00882 args.get("node", &node); 00883 00884 int result = m_mgmsrv.stopSignalTracing(node); 00885 00886 m_output->println("stop signallog"); 00887 if(result != 0) 00888 m_output->println("result: %s", get_error_text(result)); 00889 else 00890 m_output->println("result: Ok"); 00891 m_output->println(""); 00892 } 00893 00894 void 00895 MgmApiSession::restart_v1(Parser<MgmApiSession>::Context &, 00896 Properties const &args) { 00897 restart(args,1); 00898 } 00899 00900 void 00901 MgmApiSession::restart_v2(Parser<MgmApiSession>::Context &, 00902 Properties const &args) { 00903 restart(args,2); 00904 } 00905 00906 void 00907 MgmApiSession::restart(Properties const &args, int version) { 00908 Uint32 00909 nostart = 0, 00910 initialstart = 0, 00911 abort = 0; 00912 char *nodes_str; 00913 Vector<NodeId> nodes; 00914 00915 args.get("initialstart", &initialstart); 00916 args.get("nostart", &nostart); 00917 args.get("abort", &abort); 00918 args.get("node", (const char **)&nodes_str); 00919 00920 char *p, *last; 00921 for((p = strtok_r(nodes_str, " ", &last)); 00922 p; 00923 (p = strtok_r(NULL, " ", &last))) { 00924 nodes.push_back(atoi(p)); 00925 } 00926 00927 int restarted = 0; 00928 int result= m_mgmsrv.restartNodes(nodes, 00929 &restarted, 00930 nostart != 0, 00931 initialstart != 0, 00932 abort != 0, 00933 &m_stopSelf); 00934 00935 m_output->println("restart reply"); 00936 if(result != 0){ 00937 m_output->println("result: %d-%s", result, get_error_text(result)); 00938 } else 00939 m_output->println("result: Ok"); 00940 m_output->println("restarted: %d", restarted); 00941 if(version>1) 00942 m_output->println("disconnect: %d", (m_stopSelf)?1:0); 00943 m_output->println(""); 00944 } 00945 00946 void 00947 MgmApiSession::restartAll(Parser<MgmApiSession>::Context &, 00948 Properties const &args) 00949 { 00950 Uint32 nostart = 0; 00951 Uint32 initialstart = 0; 00952 Uint32 abort = 0; 00953 00954 args.get("initialstart", &initialstart); 00955 args.get("abort", &abort); 00956 args.get("nostart", &nostart); 00957 00958 int count = 0; 00959 int result = m_mgmsrv.restartDB(nostart, initialstart, abort, &count); 00960 00961 m_output->println("restart reply"); 00962 if(result != 0) 00963 m_output->println("result: %s", get_error_text(result)); 00964 else 00965 m_output->println("result: Ok"); 00966 m_output->println("restarted: %d", count); 00967 m_output->println(""); 00968 } 00969 00970 static void 00971 printNodeStatus(OutputStream *output, 00972 MgmtSrvr &mgmsrv, 00973 enum ndb_mgm_node_type type) { 00974 NodeId nodeId = 0; 00975 while(mgmsrv.getNextNodeId(&nodeId, type)) { 00976 enum ndb_mgm_node_status status; 00977 Uint32 startPhase = 0, 00978 version = 0, 00979 dynamicId = 0, 00980 nodeGroup = 0, 00981 connectCount = 0; 00982 bool system; 00983 const char *address= NULL; 00984 mgmsrv.status(nodeId, &status, &version, &startPhase, 00985 &system, &dynamicId, &nodeGroup, &connectCount, 00986 &address); 00987 output->println("node.%d.type: %s", 00988 nodeId, 00989 ndb_mgm_get_node_type_string(type)); 00990 output->println("node.%d.status: %s", 00991 nodeId, 00992 ndb_mgm_get_node_status_string(status)); 00993 output->println("node.%d.version: %d", nodeId, version); 00994 output->println("node.%d.startphase: %d", nodeId, startPhase); 00995 output->println("node.%d.dynamic_id: %d", nodeId, dynamicId); 00996 output->println("node.%d.node_group: %d", nodeId, nodeGroup); 00997 output->println("node.%d.connect_count: %d", nodeId, connectCount); 00998 output->println("node.%d.address: %s", nodeId, address ? address : ""); 00999 } 01000 01001 } 01002 01003 void 01004 MgmApiSession::getStatus(Parser<MgmApiSession>::Context &, 01005 Properties const &) { 01006 int noOfNodes = 0; 01007 01008 NodeId nodeId = 0; 01009 while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){ 01010 noOfNodes++; 01011 } 01012 nodeId = 0; 01013 while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_API)){ 01014 noOfNodes++; 01015 } 01016 nodeId = 0; 01017 while(m_mgmsrv.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM)){ 01018 noOfNodes++; 01019 } 01020 01021 m_output->println("node status"); 01022 m_output->println("nodes: %d", noOfNodes); 01023 printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_NDB); 01024 printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_MGM); 01025 printNodeStatus(m_output, m_mgmsrv, NDB_MGM_NODE_TYPE_API); 01026 01027 nodeId = 0; 01028 01029 m_output->println(""); 01030 } 01031 01032 void 01033 MgmApiSession::getInfoClusterLog(Parser<MgmApiSession>::Context &, 01034 Properties const &) { 01035 const char* names[] = { "enabled", 01036 "debug", 01037 "info", 01038 "warning", 01039 "error", 01040 "critical", 01041 "alert" }; 01042 01043 m_output->println("clusterlog"); 01044 for(int i = 0; i < 7; i++) { 01045 m_output->println("%s: %d", 01046 names[i], m_mgmsrv.isEventLogFilterEnabled(i)); 01047 } 01048 m_output->println(""); 01049 } 01050 01051 void 01052 MgmApiSession::stop_v1(Parser<MgmApiSession>::Context &, 01053 Properties const &args) { 01054 stop(args,1); 01055 } 01056 01057 void 01058 MgmApiSession::stop_v2(Parser<MgmApiSession>::Context &, 01059 Properties const &args) { 01060 stop(args,2); 01061 } 01062 01063 void 01064 MgmApiSession::stop(Properties const &args, int version) { 01065 Uint32 abort; 01066 char *nodes_str; 01067 Vector<NodeId> nodes; 01068 01069 args.get("node", (const char **)&nodes_str); 01070 if(nodes_str == NULL) 01071 { 01072 m_output->println("stop reply"); 01073 m_output->println("result: empty node list"); 01074 m_output->println(""); 01075 return; 01076 } 01077 args.get("abort", &abort); 01078 01079 char *p, *last; 01080 for((p = strtok_r(nodes_str, " ", &last)); 01081 p; 01082 (p = strtok_r(NULL, " ", &last))) { 01083 nodes.push_back(atoi(p)); 01084 } 01085 01086 int stopped= 0; 01087 int result= 0; 01088 if (nodes.size()) 01089 result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0, &m_stopSelf); 01090 01091 m_output->println("stop reply"); 01092 if(result != 0) 01093 m_output->println("result: %s", get_error_text(result)); 01094 else 01095 m_output->println("result: Ok"); 01096 m_output->println("stopped: %d", stopped); 01097 if(version>1) 01098 m_output->println("disconnect: %d", (m_stopSelf)?1:0); 01099 m_output->println(""); 01100 } 01101 01102 void 01103 MgmApiSession::stopAll(Parser<MgmApiSession>::Context &, 01104 Properties const &args) { 01105 int stopped[2] = {0,0}; 01106 Uint32 abort; 01107 args.get("abort", &abort); 01108 01109 BaseString stop; 01110 const char* tostop= "db"; 01111 int ver=1; 01112 if (args.get("stop", stop)) 01113 { 01114 tostop= stop.c_str(); 01115 ver= 2; 01116 } 01117 01118 int result= 0; 01119 if(strstr(tostop,"db")) 01120 result= m_mgmsrv.shutdownDB(&stopped[0], abort != 0); 01121 if(!result && strstr(tostop,"mgm")) 01122 result= m_mgmsrv.shutdownMGM(&stopped[1], abort!=0, &m_stopSelf); 01123 01124 m_output->println("stop reply"); 01125 if(result != 0) 01126 m_output->println("result: %s", get_error_text(result)); 01127 else 01128 m_output->println("result: Ok"); 01129 m_output->println("stopped: %d", stopped[0]+stopped[1]); 01130 if(ver >1) 01131 m_output->println("disconnect: %d", (m_stopSelf)?1:0); 01132 m_output->println(""); 01133 } 01134 01135 void 01136 MgmApiSession::enterSingleUser(Parser<MgmApiSession>::Context &, 01137 Properties const &args) { 01138 int stopped = 0; 01139 Uint32 nodeId = 0; 01140 args.get("nodeId", &nodeId); 01141 int result = m_mgmsrv.enterSingleUser(&stopped, nodeId); 01142 m_output->println("enter single user reply"); 01143 if(result != 0) { 01144 m_output->println("result: %s", get_error_text(result)); 01145 } 01146 else { 01147 m_output->println("result: Ok"); 01148 } 01149 m_output->println(""); 01150 } 01151 01152 void 01153 MgmApiSession::exitSingleUser(Parser<MgmApiSession>::Context &, 01154 Properties const &args) { 01155 int stopped = 0; 01156 int result = m_mgmsrv.exitSingleUser(&stopped, false); 01157 m_output->println("exit single user reply"); 01158 if(result != 0) 01159 m_output->println("result: %s", get_error_text(result)); 01160 else 01161 m_output->println("result: Ok"); 01162 m_output->println(""); 01163 } 01164 01165 01166 void 01167 MgmApiSession::startSignalLog(Parser<MgmApiSession>::Context &, 01168 Properties const &args) { 01169 Uint32 node; 01170 01171 args.get("node", &node); 01172 01173 int result = m_mgmsrv.startSignalTracing(node); 01174 01175 m_output->println("start signallog reply"); 01176 if(result != 0) 01177 m_output->println("result: %s", get_error_text(result)); 01178 else 01179 m_output->println("result: Ok"); 01180 m_output->println(""); 01181 } 01182 01183 void 01184 MgmApiSession::logSignals(Parser<MgmApiSession>::Context &, 01185 Properties const &args) { 01186 Uint32 node = 0, in = 0, out = 0; 01187 // BaseString blocks; 01188 BaseString blockList; 01189 char * blockName; 01190 args.get("node", &node); 01191 args.get("in", &in); 01192 args.get("out", &out); 01193 args.get("blocks", blockList); 01194 // fast fix - pekka 01195 char buf[200]; 01196 BaseString::snprintf(buf, 200, "%s", blockList.c_str()); 01197 Vector<BaseString> blocks; 01198 01199 blockName=strtok(buf,"|"); 01200 while( blockName != NULL) 01201 { 01202 blocks.push_back(blockName); 01203 blockName=strtok(NULL,"|"); 01204 } 01205 01206 01207 if(in > 1 || out > 1) 01208 return; /* Invalid arguments */ 01209 01210 const MgmtSrvr::LogMode modes[] = { 01211 MgmtSrvr::Off, 01212 MgmtSrvr::Out, 01213 MgmtSrvr::In, 01214 MgmtSrvr::InOut, 01215 }; 01216 MgmtSrvr::LogMode mode = modes[in<<1 | out]; 01217 01218 int result = m_mgmsrv.setSignalLoggingMode(node, mode, blocks); 01219 01220 m_output->println("log signals reply"); 01221 if(result != 0) 01222 m_output->println("result: %s", get_error_text(result)); 01223 else 01224 m_output->println("result: Ok"); 01225 m_output->println(""); 01226 } 01227 01228 void 01229 MgmApiSession::start(Parser<MgmApiSession>::Context &, 01230 Properties const &args) { 01231 Uint32 node; 01232 01233 args.get("node", &node); 01234 01235 int result = m_mgmsrv.start(node); 01236 01237 m_output->println("start reply"); 01238 if(result != 0) 01239 m_output->println("result: %s", get_error_text(result)); 01240 else 01241 m_output->println("result: Ok"); 01242 m_output->println(""); 01243 } 01244 01245 void 01246 MgmApiSession::startAll(Parser<MgmApiSession>::Context &, 01247 Properties const &) { 01248 NodeId node = 0; 01249 int started = 0; 01250 01251 while(m_mgmsrv.getNextNodeId(&node, NDB_MGM_NODE_TYPE_NDB)) 01252 if(m_mgmsrv.start(node) == 0) 01253 started++; 01254 01255 m_output->println("start reply"); 01256 m_output->println("result: Ok"); 01257 m_output->println("started: %d", started); 01258 m_output->println(""); 01259 } 01260 01261 void 01262 MgmApiSession::setLogFilter(Parser_t::Context &ctx, 01263 const class Properties &args) { 01264 Uint32 severity; 01265 Uint32 enable; 01266 01267 args.get("level", &severity); 01268 args.get("enable", &enable); 01269 01270 int result = m_mgmsrv.setEventLogFilter(severity, enable); 01271 01272 m_output->println("set logfilter reply"); 01273 m_output->println("result: %d", result); 01274 m_output->println(""); 01275 } 01276 01277 static NdbOut& 01278 operator<<(NdbOut& out, const LogLevel & ll) 01279 { 01280 out << "[LogLevel: "; 01281 for(size_t i = 0; i<LogLevel::LOGLEVEL_CATEGORIES; i++) 01282 out << ll.getLogLevel((LogLevel::EventCategory)i) << " "; 01283 out << "]"; 01284 return out; 01285 } 01286 01287 void 01288 Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId){ 01289 01290 Uint32 threshold; 01291 LogLevel::EventCategory cat; 01292 Logger::LoggerLevel severity; 01293 EventLoggerBase::EventTextFunction textF; 01294 int i, n; 01295 DBUG_ENTER("Ndb_mgmd_event_service::log"); 01296 DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId)); 01297 01298 if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF)) 01299 DBUG_VOID_RETURN; 01300 01301 char m_text[256]; 01302 EventLogger::getText(m_text, sizeof(m_text), 01303 textF, theData, nodeId); 01304 01305 BaseString str("log event reply\n"); 01306 str.appfmt("type=%d\n", eventType); 01307 str.appfmt("time=%d\n", 0); 01308 str.appfmt("source_nodeid=%d\n", nodeId); 01309 for (i= 0; ndb_logevent_body[i].token; i++) 01310 { 01311 if ( ndb_logevent_body[i].type != eventType) 01312 continue; 01313 int val= theData[ndb_logevent_body[i].index]; 01314 if (ndb_logevent_body[i].index_fn) 01315 val= (*(ndb_logevent_body[i].index_fn))(val); 01316 str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val); 01317 } 01318 01319 Vector<NDB_SOCKET_TYPE> copy; 01320 m_clients.lock(); 01321 for(i = m_clients.size() - 1; i >= 0; i--) 01322 { 01323 if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)) 01324 { 01325 NDB_SOCKET_TYPE fd= m_clients[i].m_socket; 01326 if(fd != NDB_INVALID_SOCKET) 01327 { 01328 int r; 01329 if (m_clients[i].m_parsable) 01330 r= println_socket(fd, 01331 MAX_WRITE_TIMEOUT, str.c_str()); 01332 else 01333 r= println_socket(fd, 01334 MAX_WRITE_TIMEOUT, m_text); 01335 if (r == -1) { 01336 copy.push_back(fd); 01337 m_clients.erase(i, false); 01338 } 01339 } 01340 } 01341 } 01342 m_clients.unlock(); 01343 01344 if ((n= (int)copy.size())) 01345 { 01346 for(i= 0; i < n; i++) 01347 NDB_CLOSE_SOCKET(copy[i]); 01348 01349 LogLevel tmp; tmp.clear(); 01350 m_clients.lock(); 01351 for(i= m_clients.size() - 1; i >= 0; i--) 01352 tmp.set_max(m_clients[i].m_logLevel); 01353 m_clients.unlock(); 01354 update_log_level(tmp); 01355 } 01356 DBUG_VOID_RETURN; 01357 } 01358 01359 void 01360 Ndb_mgmd_event_service::update_max_log_level(const LogLevel &log_level) 01361 { 01362 LogLevel tmp = log_level; 01363 m_clients.lock(); 01364 for(int i = m_clients.size() - 1; i >= 0; i--) 01365 tmp.set_max(m_clients[i].m_logLevel); 01366 m_clients.unlock(); 01367 update_log_level(tmp); 01368 } 01369 01370 void 01371 Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp) 01372 { 01373 m_logLevel = tmp; 01374 EventSubscribeReq req; 01375 req = tmp; 01376 // send update to all nodes 01377 req.blockRef = 0; 01378 m_mgmsrv->m_log_level_requests.push_back(req); 01379 } 01380 01381 void 01382 Ndb_mgmd_event_service::check_listeners() 01383 { 01384 int i, n= 0; 01385 DBUG_ENTER("Ndb_mgmd_event_service::check_listeners"); 01386 m_clients.lock(); 01387 for(i= m_clients.size() - 1; i >= 0; i--) 01388 { 01389 int fd= m_clients[i].m_socket; 01390 DBUG_PRINT("info",("%d %d",i,fd)); 01391 char buf[1]; 01392 buf[0]=0; 01393 if (fd != NDB_INVALID_SOCKET && 01394 println_socket(fd,MAX_WRITE_TIMEOUT,"<PING>") == -1) 01395 { 01396 NDB_CLOSE_SOCKET(fd); 01397 m_clients.erase(i, false); 01398 n=1; 01399 } 01400 } 01401 if (n) 01402 { 01403 LogLevel tmp; tmp.clear(); 01404 for(i= m_clients.size() - 1; i >= 0; i--) 01405 tmp.set_max(m_clients[i].m_logLevel); 01406 update_log_level(tmp); 01407 } 01408 m_clients.unlock(); 01409 DBUG_VOID_RETURN; 01410 } 01411 01412 void 01413 Ndb_mgmd_event_service::add_listener(const Event_listener& client) 01414 { 01415 DBUG_ENTER("Ndb_mgmd_event_service::add_listener"); 01416 DBUG_PRINT("enter",("client.m_socket: %d", client.m_socket)); 01417 01418 check_listeners(); 01419 01420 m_clients.push_back(client); 01421 update_max_log_level(client.m_logLevel); 01422 01423 DBUG_VOID_RETURN; 01424 } 01425 01426 void 01427 Ndb_mgmd_event_service::stop_sessions(){ 01428 m_clients.lock(); 01429 for(int i = m_clients.size() - 1; i >= 0; i--){ 01430 if(m_clients[i].m_socket != NDB_INVALID_SOCKET){ 01431 NDB_CLOSE_SOCKET(m_clients[i].m_socket); 01432 m_clients.erase(i); 01433 } 01434 } 01435 m_clients.unlock(); 01436 } 01437 01438 void 01439 MgmApiSession::setParameter(Parser_t::Context &, 01440 Properties const &args) { 01441 BaseString node, param, value; 01442 args.get("node", node); 01443 args.get("parameter", param); 01444 args.get("value", value); 01445 01446 BaseString result; 01447 int ret = m_mgmsrv.setDbParameter(atoi(node.c_str()), 01448 atoi(param.c_str()), 01449 value.c_str(), 01450 result); 01451 01452 m_output->println("set parameter reply"); 01453 m_output->println("message: %s", result.c_str()); 01454 m_output->println("result: %d", ret); 01455 m_output->println(""); 01456 } 01457 01458 void 01459 MgmApiSession::setConnectionParameter(Parser_t::Context &ctx, 01460 Properties const &args) { 01461 BaseString node1, node2, param, value; 01462 args.get("node1", node1); 01463 args.get("node2", node2); 01464 args.get("param", param); 01465 args.get("value", value); 01466 01467 BaseString result; 01468 int ret = m_mgmsrv.setConnectionDbParameter(atoi(node1.c_str()), 01469 atoi(node2.c_str()), 01470 atoi(param.c_str()), 01471 atoi(value.c_str()), 01472 result); 01473 01474 m_output->println("set connection parameter reply"); 01475 m_output->println("message: %s", result.c_str()); 01476 m_output->println("result: %s", (ret>0)?"Ok":"Failed"); 01477 m_output->println(""); 01478 } 01479 01480 void 01481 MgmApiSession::getConnectionParameter(Parser_t::Context &ctx, 01482 Properties const &args) { 01483 BaseString node1, node2, param; 01484 int value = 0; 01485 01486 args.get("node1", node1); 01487 args.get("node2", node2); 01488 args.get("param", param); 01489 01490 BaseString result; 01491 int ret = m_mgmsrv.getConnectionDbParameter(atoi(node1.c_str()), 01492 atoi(node2.c_str()), 01493 atoi(param.c_str()), 01494 &value, 01495 result); 01496 01497 m_output->println("get connection parameter reply"); 01498 m_output->println("value: %d", value); 01499 m_output->println("result: %s", (ret>0)?"Ok":result.c_str()); 01500 m_output->println(""); 01501 } 01502 01503 void 01504 MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx, 01505 Properties const & args) { 01506 Uint32 parsable= 0; 01507 BaseString node, param, value; 01508 args.get("node", node); 01509 args.get("filter", param); 01510 args.get("parsable", &parsable); 01511 01512 int result = 0; 01513 BaseString msg; 01514 01515 Ndb_mgmd_event_service::Event_listener le; 01516 le.m_parsable = parsable; 01517 le.m_socket = m_socket; 01518 01519 Vector<BaseString> list; 01520 param.trim(); 01521 param.split(list, " ,"); 01522 for(size_t i = 0; i<list.size(); i++){ 01523 Vector<BaseString> spec; 01524 list[i].trim(); 01525 list[i].split(spec, "=:"); 01526 if(spec.size() != 2){ 01527 msg.appfmt("Invalid filter specification: >%s< >%s< %d", 01528 param.c_str(), list[i].c_str(), spec.size()); 01529 result = -1; 01530 goto done; 01531 } 01532 01533 spec[0].trim().ndb_toupper(); 01534 int category = ndb_mgm_match_event_category(spec[0].c_str()); 01535 if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){ 01536 category = atoi(spec[0].c_str()); 01537 if(category < NDB_MGM_MIN_EVENT_CATEGORY || 01538 category > NDB_MGM_MAX_EVENT_CATEGORY){ 01539 msg.appfmt("Unknown category: >%s<", spec[0].c_str()); 01540 result = -1; 01541 goto done; 01542 } 01543 } 01544 01545 int level = atoi(spec[1].c_str()); 01546 if(level < 0 || level > 15){ 01547 msg.appfmt("Invalid level: >%s<", spec[1].c_str()); 01548 result = -1; 01549 goto done; 01550 } 01551 category -= CFG_MIN_LOGLEVEL; 01552 le.m_logLevel.setLogLevel((LogLevel::EventCategory)category, level); 01553 } 01554 01555 if(list.size() == 0){ 01556 msg.appfmt("Empty filter specification"); 01557 result = -1; 01558 goto done; 01559 } 01560 01561 m_mgmsrv.m_event_listner.add_listener(le); 01562 01563 m_stop = true; 01564 m_socket = NDB_INVALID_SOCKET; 01565 01566 done: 01567 m_output->println("listen event"); 01568 m_output->println("result: %d", result); 01569 if(result != 0) 01570 m_output->println("msg: %s", msg.c_str()); 01571 m_output->println(""); 01572 } 01573 01574 void 01575 MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data) 01576 { 01577 MgmApiSession *s= (MgmApiSession *)_s; 01578 struct PurgeStruct &ps= *(struct PurgeStruct *)data; 01579 if (s->m_allocated_resources->is_reserved(ps.free_nodes)) 01580 { 01581 if (ps.str) 01582 ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid()); 01583 s->stopSession(); 01584 } 01585 } 01586 01587 void 01588 MgmApiSession::stop_session_if_timed_out(SocketServer::Session *_s, void *data) 01589 { 01590 MgmApiSession *s= (MgmApiSession *)_s; 01591 struct PurgeStruct &ps= *(struct PurgeStruct *)data; 01592 if (s->m_allocated_resources->is_reserved(ps.free_nodes) && 01593 s->m_allocated_resources->is_timed_out(ps.tick)) 01594 { 01595 s->stopSession(); 01596 } 01597 } 01598 01599 void 01600 MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx, 01601 const class Properties &args) 01602 { 01603 struct PurgeStruct ps; 01604 BaseString str; 01605 ps.str = &str; 01606 01607 m_mgmsrv.get_connected_nodes(ps.free_nodes); 01608 ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes 01609 01610 m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps); 01611 m_mgmsrv.get_socket_server()->checkSessions(); 01612 01613 m_output->println("purge stale sessions reply"); 01614 if (str.length() > 0) 01615 m_output->println("purged:%s",str.c_str()); 01616 m_output->println("result: Ok"); 01617 m_output->println(""); 01618 } 01619 01620 void 01621 MgmApiSession::check_connection(Parser_t::Context &ctx, 01622 const class Properties &args) 01623 { 01624 m_output->println("check connection reply"); 01625 m_output->println("result: Ok"); 01626 m_output->println(""); 01627 } 01628 01629 void 01630 MgmApiSession::transporter_connect(Parser_t::Context &ctx, 01631 Properties const &args) 01632 { 01633 m_mgmsrv.transporter_connect(m_socket); 01634 01635 m_stop= true; 01636 m_stopped= true; // force a stop (no closing socket) 01637 m_socket= NDB_INVALID_SOCKET; // so nobody closes it 01638 } 01639 01640 void 01641 MgmApiSession::get_mgmd_nodeid(Parser_t::Context &ctx, 01642 Properties const &args) 01643 { 01644 m_output->println("get mgmd nodeid reply"); 01645 m_output->println("nodeid:%u",m_mgmsrv.getOwnNodeId()); 01646 m_output->println(""); 01647 } 01648 01649 void 01650 MgmApiSession::report_event(Parser_t::Context &ctx, 01651 Properties const &args) 01652 { 01653 Uint32 length; 01654 const char *data_string; 01655 Uint32 data[25]; 01656 01657 args.get("length", &length); 01658 args.get("data", &data_string); 01659 01660 BaseString tmp(data_string); 01661 Vector<BaseString> item; 01662 tmp.split(item, " "); 01663 for (int i = 0; i < length ; i++) 01664 { 01665 sscanf(item[i].c_str(), "%u", data+i); 01666 } 01667 01668 m_mgmsrv.eventReport(data); 01669 m_output->println("report event reply"); 01670 m_output->println("result: ok"); 01671 m_output->println(""); 01672 } 01673 01674 template class MutexVector<int>; 01675 template class Vector<ParserRow<MgmApiSession> const*>;
1.4.7

