Geant4-11
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// --------------------------------------------------------------------------
38namespace {
39
41G4bool qexit = false;
42std::stringstream cout_stream;
43std::string black_str = "\033[30m";
44std::string command_list = "";
45
46void 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// --------------------------------------------------------------------------
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
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
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.erase(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
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 ) {
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}
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
@ fParameterOutOfCandidates
@ fCommandNotFound
@ fAliasNotFound
@ fIllegalApplicationState
@ fParameterUnreadable
@ fCommandSucceeded
@ fParameterOutOfRange
@ BLUE
Definition: G4VUIshell.hh:54
@ RED
Definition: G4VUIshell.hh:53
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
G4String GetPreviousCommand(G4int i) const
Definition: G4UImanager.hh:202
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:77
G4UIcommand * FindCommand(const char *commandName) const
G4String ModifyToFullPathCommand(const char *aCommandLine) const
void ShowCurrent(const G4String &) const
void TerminalHelp(const G4String &)
void ListDirectory(const G4String &) const
G4String GetCurrentWorkingDirectory() const
void ChangeDirectoryCommand(const G4String &)
G4UIcommandTree * FindDirectory(const char *dirName) const
virtual G4int ReceiveG4cout(const G4String &coutString)
Definition: G4ZMQServer.cc:179
virtual void ExitHelp() const
Definition: G4ZMQServer.cc:311
G4String GetCommand(const G4String &input)
Definition: G4ZMQServer.cc:203
G4String endpoint_
Definition: G4ZMQServer.hh:54
G4UItcsh * shell_
Definition: G4ZMQServer.hh:55
virtual G4UIsession * SessionStart()
Definition: G4ZMQServer.cc:95
virtual G4int ReceiveG4cerr(const G4String &cerrString)
Definition: G4ZMQServer.cc:191
virtual void ExecuteCommand(const G4String &command)
Definition: G4ZMQServer.cc:263
virtual G4bool GetHelpChoice(G4int &)
Definition: G4ZMQServer.cc:305
G4bool qdebug_
Definition: G4ZMQServer.hh:53
virtual void PauseSessionStart(const G4String &message)
Definition: G4ZMQServer.cc:174
G4String lstrip_copy(G4String str, char c=' ')
Return copy of string with leading characters removed.
void GetCommandTree(G4UIcommandTree *ctree)
Definition: G4ZMQServer.cc:54
void ThrowException(const std::string &message)
Definition: G4ZMQServer.cc:46
socket
Definition: g4zmq.py:12
context
Definition: g4zmq.py:11
string cmdstr
Definition: test.py:122
#define buffer
Definition: xmlparse.cc:628