ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ZMQServer.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ZMQServer.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 //
29 #include <cstring>
30 #include <sstream>
31 #include <zmq.hpp>
32 #include "G4UItcsh.hh"
33 #include "G4UImanager.hh"
34 #include "G4UIcommandTree.hh"
35 #include "G4ZMQServer.hh"
36 
37 // --------------------------------------------------------------------------
38 namespace {
39 
40 G4UImanager* ui_manager = nullptr;
41 G4bool qexit = false;
42 std::stringstream cout_stream;
43 std::string black_str = "\033[30m";
44 std::string command_list = "";
45 
46 void ThrowException(const std::string& message)
47 {
48  std::stringstream ss;
49  ss << "[ERROR] " << message << std::endl;
50  throw std::runtime_error(ss.str());
51 }
52 
53 // --------------------------------------------------------------------------
54 void GetCommandTree(G4UIcommandTree* ctree)
55 {
56  command_list += (ctree-> GetPathName() + " ");
57 
58  auto n_cmd = ctree-> GetCommandEntry();
59  for ( auto icmd = 1; icmd <= n_cmd; icmd++ ) {
60  auto cmd_path = ctree-> GetCommand(icmd)-> GetCommandPath();
61  command_list += (cmd_path + " ");
62  }
63 
64  auto n_tree = ctree-> GetTreeEntry();
65  for ( auto itr = 1; itr <= n_tree ; itr++ ) {
66  G4UIcommandTree* atree = ctree-> GetTree(itr);
67  ::GetCommandTree(atree);
68  }
69 }
70 
71 } // end of namespace
72 
73 // --------------------------------------------------------------------------
75 {
76  endpoint_ = "tcp://127.0.0.1:5555";
77  qdebug_ = false;
78  shell_= new G4UItcsh();
79  shell_-> SetLsColor(BLUE, RED);
80 
81  ::ui_manager = G4UImanager::GetUIpointer();
82  ::ui_manager-> SetSession(this);
83  ::ui_manager-> SetCoutDestination(this);
84 
85  ::qexit = false;
86 }
87 
88 // --------------------------------------------------------------------------
90 {
91  delete shell_;
92 }
93 
94 // --------------------------------------------------------------------------
96 {
97  zmq::context_t context(1);
98  zmq::socket_t socket( context, ZMQ_REP );
99  socket.bind(endpoint_);
100 
101  enum { kBufferSize = 4096 };
102  char buffer[kBufferSize];
103 
104  while ( ! ::qexit ) {
105  if ( qdebug_ ) {
106  std::cout << "@@ Waiting..." << std::endl;
107  }
108 
109  // waiting command
110  zmq::message_t request;
111  G4bool qok = socket.recv(&request);
112  if ( qok == false ) ::ThrowException("G4ZMQSever: socket recv error");
113  auto end_pos = request.size();
114  if ( end_pos >= kBufferSize ) end_pos = kBufferSize - 1;
115  std::memcpy(buffer, request.data(), end_pos);
116  buffer[end_pos] = '\0';
117  std::string cmd_str = buffer;
118 
119  if ( qdebug_ ) {
120  std::cout << "@@ Recv=" << cmd_str << "<<" << std::endl;
121  }
122 
123  // store output & send back response
124  ::cout_stream.str("");
125 
126  if ( cmd_str == "@@ping" ) {
127  G4cout << "pong" << G4endl;
128 
129  } else if ( cmd_str == "@@debug") {
130  qdebug_ = true;
131  G4cout << "G4ZMQ debug activated" << G4endl;
132 
133  } else if ( cmd_str == "@@nodebug") {
134  qdebug_ = false;
135  G4cout << "G4ZMQ debug deactivated" << G4endl;
136 
137  } else if ( cmd_str == "@@get_command_tree" ) {
138  auto cwd_name = GetCurrentWorkingDirectory();
139  auto cwd_tree = FindDirectory(cwd_name.c_str());
140  ::command_list = "";
141  ::GetCommandTree(cwd_tree);
142  G4cout << ::command_list << std::flush;
143 
144  } else if ( cmd_str == "@@get_fullcommand_tree" ) {
145  auto root = ::ui_manager-> GetTree();
146  ::command_list = "";
147  ::GetCommandTree(root);
148  G4cout << ::command_list << std::flush;
149 
150  } else if ( cmd_str == "help" ) {
151  G4cout << "help <command>" << G4endl;
152 
153  } else {
154  G4String new_command = GetCommand(cmd_str);
155  if ( qdebug_ ) {
156  std::cout << ::black_str << "@@ Cmd="
157  << new_command << "<<" << std::endl;
158  }
159  ExecuteCommand(new_command);
160  }
161 
162  std::string reply = ::cout_stream.str();
163  size_t cout_size = reply.size();
164  zmq::message_t message(cout_size);
165  std::strncpy((char*)message.data(), reply.c_str(), cout_size);
166  qok = socket.send(message);
167  if ( qok == false ) ::ThrowException("G4ZMQServer: socket send error");
168  }
169 
170  return nullptr;
171 }
172 
173 // --------------------------------------------------------------------------
175 {
176 }
177 
178 // --------------------------------------------------------------------------
180 {
181  if ( qdebug_ ) {
182  std::cout << coutString << std::flush;
183  }
184 
185  ::cout_stream << coutString << std::flush;
186 
187  return 0;
188 }
189 
190 // --------------------------------------------------------------------------
192 {
193  if ( qdebug_ ) {
194  std::cerr << cerrString << std::flush;
195  }
196 
197  ::cout_stream << cerrString << std::flush;
198 
199  return 0;
200 }
201 
202 // --------------------------------------------------------------------------
204 {
205  const std::string nullstr = "";
206  G4String cmdstr = input;
207 
208  G4String cstr = cmdstr.strip(G4String::leading);
209  if ( cstr.length() == 0 ) {
210  cmdstr = nullstr;
211 
212  // define built-in shell commands...
213  } else if ( cstr(0) == '#' ) {
214  G4cout << cstr << G4endl;
215  cmdstr = nullstr;
216 
217  } else if ( cstr == "ls" || cstr.substr(0,3) == "ls " ) {
218  ListDirectory(cstr);
219  cmdstr = nullstr;
220 
221  } else if ( cstr == "lc" || cstr.substr(0,3) == "lc " ) {
222  shell_-> ListCommand(cstr.remove(0,2));
223  cmdstr = nullstr;
224 
225  } else if (cstr == "pwd" ) {
226  G4cout << "Current Command Directory : "
228  cmdstr = nullstr;
229 
230  } else if ( cstr == "cwd" ) {
231  shell_-> ShowCurrentDirectory();
232  cmdstr = nullstr;
233 
234  } else if (cstr == "cd" || cstr.substr(0,3) == "cd " ) {
236  shell_-> SetCurrentDirectory(GetCurrentWorkingDirectory());
237  cmdstr = nullstr;
238 
239  } else if ( cstr == "help" || cstr.substr(0,5) == "help " ) {
240  TerminalHelp(cstr);
241  cmdstr = nullstr;
242 
243  } else if ( cstr(0) == '?' ) {
244  ShowCurrent(cstr);
245  cmdstr = nullstr;
246 
247  } else if ( cstr == "history" ) {
248  auto nh= ::ui_manager-> GetNumberOfHistory();
249  for (auto i = 0; i < nh; i++) {
250  G4cout << i << ": " << ::ui_manager->GetPreviousCommand(i) << G4endl;
251  }
252  cmdstr = nullstr;
253 
254  } else if ( cstr == "exit" ) {
255  ::qexit = true;
256  cmdstr = nullstr;
257  }
258 
259  return ModifyToFullPathCommand(cmdstr);
260 }
261 
262 // --------------------------------------------------------------------------
264 {
265  auto rc = ::ui_manager-> ApplyCommand(command);
266  auto pcode = rc % 100;
267  auto status = rc - pcode;
268 
269  G4UIcommand* cmd = nullptr;
270  if( status != fCommandSucceeded ) cmd = FindCommand(command);
271 
272  switch ( status ) {
273  case fCommandSucceeded:
274  break;
275  case fCommandNotFound:
276  G4cerr << "command <" << ::ui_manager-> SolveAlias(command)
277  << "> not found" << G4endl;
278  break;
280  G4cerr << "illegal application state -- command refused" << G4endl;
281  break;
283  G4cerr << "Parameter is out of range" << G4endl;
284  break;
286  G4cerr << "Parameter is out of candidate list (index "
287  << pcode << ")" << G4endl;
288  G4cerr << "Candidates : "
289  << cmd-> GetParameter(pcode)-> GetParameterCandidates()
290  << G4endl;
291  break;
293  G4cerr << "Parameter is wrong type and/or is not omittable (index "
294  << pcode << ")" << G4endl;
295  break;
296  case fAliasNotFound:
297  break;
298  default:
299  G4cerr << "command refused (" << status << ")" << G4endl;
300  break;
301  }
302 }
303 
304 // --------------------------------------------------------------------------
306 {
307  return true;
308 }
309 
310 // --------------------------------------------------------------------------
312 {
313 }