1 // Copyright (C) 2019-2023 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony GEAY (EDF R&D)
21 #include "SALOME_ExternalServerLauncher.hxx"
22 #include "SALOME_ExternalServerHandler.hxx"
23 #include "SALOME_NamingService.hxx"
24 #include "SALOME_LauncherException.hxx"
25 #include "SALOME_ContainerManager.hxx"
26 #include "SALOME_CPythonHelper.hxx"
28 #include CORBA_CLIENT_HEADER(SALOME_ExternalServerLauncher)
34 #include <Basics_Utils.hxx>
43 const char SALOME_ExternalServerLauncher::NAME_IN_NS[]="/ExternalServers";
45 unsigned SALOME_ExternalServerLauncher::CNT = 0;
47 SALOME_ExternalServerLauncher::SALOME_ExternalServerLauncher(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, PortableServer::POA_var poa,SALOME_NamingService_Abstract *ns):_pyHelper(pyHelper),_poa(poa)
49 _NS = ns == nullptr ? new SALOME_NamingService(orb) : ns;
50 PortableServer::ObjectId_var id(_poa->activate_object(this));
51 CORBA::Object_var obj(_poa->id_to_reference(id));
52 SALOME::ExternalServerLauncher_var refPtr(SALOME::ExternalServerLauncher::_narrow(obj));
53 _NS->Register(refPtr,NAME_IN_NS);
56 SALOME_ExternalServerLauncher::~SALOME_ExternalServerLauncher()
65 ChdirRAII(const std::string& wd):_wd(wd) { if(_wd.empty()) return ; char *pwd(get_current_dir_name()); _od = pwd; free(pwd); chdir(_wd.c_str()); }
66 ~ChdirRAII() { if(_od.empty()) return ; chdir(_od.c_str()); }
68 ChdirRAII(const std::string& wd) : _wd(wd) {
72 GetCurrentDirectory(sizeof(pwd), pwd);
73 _od = Kernel_Utils::utf8_encode_s(pwd);
74 SetCurrentDirectory(Kernel_Utils::utf8_decode_s(_wd).c_str());
77 if (_od.empty()) return;
78 SetCurrentDirectory(Kernel_Utils::utf8_decode_s(_od).c_str());
86 SALOME::ExternalServerHandler_ptr SALOME_ExternalServerLauncher::launchServer(const char *server_name, const char *working_dir, const SALOME::CmdList& command_list )
88 std::vector<std::string> servers(ListOfExternalServersCpp(_NS));
89 if(std::find(servers.begin(),servers.end(),server_name)!=servers.end())
91 std::ostringstream oss2; oss2 << "SALOME_ExternalServerLauncher::launchServer : Server \""<< server_name << "\" already exists !";
92 throw SALOME_LauncherException(oss2.str());
94 std::vector<std::string> cmd(command_list.length());
95 for(size_t i=0;i<command_list.length();i++)
96 cmd[i] = command_list[i];
100 ChdirRAII cr(working_dir);
101 pid = SALOME_ContainerManager::SystemWithPIDThreadSafe(cmd) ;
103 catch(SALOME_Exception& e)
105 std::ostringstream oss2; oss2 << "SALOME_ExternalServerLauncher::launchServer : Fail to launch subprocess ! Reason is : " << e.what() << " !";
106 throw SALOME_LauncherException(oss2.str());
108 SALOME_ExternalServerHandler *retServ(new SALOME_ExternalServerHandler(this,server_name,_NS,pid));
109 retServ->registerToKill(_pyHelper);
110 PortableServer::ObjectId_var id(_poa->activate_object(retServ));
111 CORBA::Object_var obj(_poa->id_to_reference(id));
112 std::string fullServerName(CreateAbsNameInNSFromServerName(server_name));
113 SALOME::ExternalServerHandler_ptr ret(SALOME::ExternalServerHandler::_narrow(obj));
114 _NS->Register(ret,fullServerName.c_str());
118 void SALOME_ExternalServerLauncher::registerToKill(const char *server_name, CORBA::Long PID)
120 std::ostringstream oss;
121 oss << "Custom_"<< server_name << "_" << CNT++;
122 _pyHelper->registerToSalomePiDict(oss.str(),PID);
123 _list_of_pids_to_kill.push_back(PID);
126 void SALOME_ExternalServerLauncher::cleanServersInNS()
128 std::vector<std::string> servers(ListOfExternalServersCpp(_NS));
129 for(std::vector<std::string>::const_iterator it=servers.begin();it!=servers.end();it++)
131 if(!IsAliveAndKicking(_NS,(*it).c_str()))
133 std::string fullServerName(CreateAbsNameInNSFromServerName(*it));
134 _NS->Destroy_Name(fullServerName.c_str());
139 void SALOME_ExternalServerLauncher::shutdownServers()
141 for(auto pid : this->_list_of_pids_to_kill)
143 SALOME_ExternalServerHandler::KillPID(pid);
146 std::vector<std::string> lioes(ListOfExternalServersCpp(_NS));
147 for(auto servName : lioes)
149 SALOME::ExternalServerHandler_var proc(GetServerHandlerGivenName(_NS,servName));
150 PortableServer::ServantBase *procServ(_poa->reference_to_servant(proc));
151 SALOME_ExternalServerHandler *procServC(dynamic_cast<SALOME_ExternalServerHandler *>(procServ));
162 SALOME::StringVec *SALOME_ExternalServerLauncher::listServersInNS()
164 SALOME::StringVec *ret(new SALOME::StringVec);
165 std::vector<std::string> loes(ListOfExternalServersCpp(_NS));
166 std::size_t sz(loes.size());
168 for(size_t i=0; i<sz; i++)
170 (*ret)[i]=CORBA::string_dup(loes[i].c_str());
175 SALOME::ExternalServerHandler_ptr SALOME_ExternalServerLauncher::retrieveServerRefGivenNSEntry( const char *ns_entry )
177 SALOME::ExternalServerHandler_var ret(GetServerHandlerGivenName(_NS,ns_entry));
181 char *SALOME_ExternalServerLauncher::gethostname()
183 std::string ret(_pyHelper->evalS("socket.gethostname()"));
184 return CORBA::string_dup(ret.c_str());
187 SALOME::ByteVec *SALOME_ExternalServerLauncher::fetchContentOfFileAndRm(const char *file_name)
189 std::ifstream t(file_name);
192 std::ostringstream oss; oss << "SALOME_ExternalServerLauncher::fetchContentOfFileAndRm : Error when trying to open \"" << file_name << "\" file !";
193 throw SALOME_LauncherException(oss.str());
195 t.seekg(0, std::ios::end);
196 size_t size(t.tellg());
197 std::unique_ptr<char,std::function<void(char *)> > buffer(new char[size],[](char *pt) { delete [] pt; });
199 t.read(buffer.get(),size);
201 std::unique_ptr<SALOME::ByteVec> ret(new SALOME::ByteVec);
203 for(size_t i=0;i<size;++i)
204 (*ret)[i] = buffer.get()[i];
206 if( unlink(file_name)!=0 )
208 std::cerr << "Error when trying to remove \"" << file_name << "\" !";
211 return ret.release();
214 std::vector<std::string> SALOME_ExternalServerLauncher::ListOfExternalServersCpp(SALOME_NamingService_Abstract *ns)
216 ns->Change_Directory(NAME_IN_NS);
217 std::vector<std::string> ret(ns->list_directory());
221 std::string SALOME_ExternalServerLauncher::CreateAbsNameInNSFromServerName(const std::string& scopeName)
223 std::ostringstream oss; oss << NAME_IN_NS << "/" << scopeName;
227 bool SALOME_ExternalServerLauncher::IsAliveAndKicking(SALOME::ExternalServerHandler_ptr server)
239 bool SALOME_ExternalServerLauncher::IsAliveAndKicking(SALOME_NamingService_Abstract *ns, const std::string& serverName)
241 SALOME::ExternalServerHandler_var pt(GetServerHandlerGivenName(ns, serverName));
242 if( CORBA::is_nil(pt) )
244 return IsAliveAndKicking(pt);
247 SALOME::ExternalServerHandler_var SALOME_ExternalServerLauncher::GetServerHandlerGivenName(SALOME_NamingService_Abstract *ns, const std::string& serverName)
249 std::vector<std::string> serverNames(ListOfExternalServersCpp(ns));
250 if(std::find(serverNames.begin(),serverNames.end(),serverName)==serverNames.end())
252 std::ostringstream oss; oss << "SALOME_ExternalServerLauncher::GetServerHandlerGivenName : scope name \"" << serverName << "\" does not exist !";
253 throw SALOME_LauncherException(oss.str());
255 std::string fullServerName(CreateAbsNameInNSFromServerName(serverName));
256 CORBA::Object_var obj(ns->Resolve(fullServerName.c_str()));
257 SALOME::ExternalServerHandler_var ret(SALOME::ExternalServerHandler::_narrow(obj));