CpcClient.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:14k
源码类别:

MySQL数据库

开发平台:

Visual C++

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