LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
G4ZMQServer.cc
Go to the documentation of this file.
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 // --------------------------------------------------------------------------
179 G4int G4ZMQServer::ReceiveG4cout(const G4String& coutString)
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 // --------------------------------------------------------------------------
191 G4int G4ZMQServer::ReceiveG4cerr(const G4String& cerrString)
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 : "
227  << GetCurrentWorkingDirectory() << G4endl;
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 " ) {
235  ChangeDirectoryCommand(cstr);
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;
279  case fIllegalApplicationState:
280  G4cerr << "illegal application state -- command refused" << G4endl;
281  break;
282  case fParameterOutOfRange:
283  G4cerr << "Parameter is out of range" << G4endl;
284  break;
285  case fParameterOutOfCandidates:
286  G4cerr << "Parameter is out of candidate list (index "
287  << pcode << ")" << G4endl;
288  G4cerr << "Candidates : "
289  << cmd-> GetParameter(pcode)-> GetParameterCandidates()
290  << G4endl;
291  break;
292  case fParameterUnreadable:
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 }
virtual void ExecuteCommand(const G4String &command)
Definition: G4ZMQServer.cc:263
G4String endpoint_
Definition: G4ZMQServer.hh:54
G4String GetCommand(const G4String &input)
Definition: G4ZMQServer.cc:203
void message(RunManager *runmanager)
Definition: ts_scorers.cc:74
virtual G4bool GetHelpChoice(G4int &)
Definition: G4ZMQServer.cc:305
virtual void ExitHelp() const
Definition: G4ZMQServer.cc:311
virtual void PauseSessionStart(const G4String &message)
Definition: G4ZMQServer.cc:174
virtual G4UIsession * SessionStart()
Definition: G4ZMQServer.cc:95
G4bool qdebug_
Definition: G4ZMQServer.hh:53
virtual G4int ReceiveG4cerr(const G4String &cerrString)
Definition: G4ZMQServer.cc:191
G4UItcsh * shell_
Definition: G4ZMQServer.hh:55
virtual G4int ReceiveG4cout(const G4String &coutString)
Definition: G4ZMQServer.cc:179