]> SALOME platform Git repositories - modules/kernel.git/blob - src/Container/Container_i.cxx
Salome HOME
bos #26520 Remove dependency on boost::python
[modules/kernel.git] / src / Container / Container_i.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME Container : implementation of container and engine for Kernel
24 //  File   : Container_i.cxx
25 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA 
26 //  Module : SALOME
27 //  $Header$
28 //#define private public
29 //
30 #include <string.h>
31 #include <stdio.h>
32 #include <time.h>
33 #include <sys/types.h>
34 #ifndef WIN32
35 #include <sys/time.h>
36 #include <dlfcn.h>
37 #include <unistd.h>
38 #include <sys/wait.h>
39 #else
40 #include <signal.h>
41 #include <process.h>
42 #include <direct.h>
43 int SIGUSR1 = 1000;
44 #endif
45
46 #include "utilities.h"
47 #include <SALOMEconfig.h>
48 #include CORBA_SERVER_HEADER(SALOME_Component)
49 #include CORBA_SERVER_HEADER(SALOME_Exception)
50 #include <pthread.h>  // must be before Python.h !
51 #include "SALOME_Container_i.hxx"
52 #include "SALOME_Component_i.hxx"
53 #include "SALOME_FileRef_i.hxx"
54 #include "SALOME_FileTransfer_i.hxx"
55 #include "Salome_file_i.hxx"
56 #include "SALOME_NamingService.hxx"
57 #include "SALOME_Fake_NamingService.hxx"
58 #include "SALOME_Embedded_NamingService_Client.hxx"
59 #include "Basics_Utils.hxx"
60
61 #ifdef _XOPEN_SOURCE
62 #undef _XOPEN_SOURCE
63 #endif
64
65 #include <Python.h>
66 #include "Container_init_python.hxx"
67 #ifdef BOS26455_WITH_BOOST_PYTHON
68 #include <boost/python.hpp>
69 #endif
70
71 bool _Sleeping = false ;
72
73 // // Needed by multi-threaded Python --- Supervision
74 int _ArgC ;
75 char ** _ArgV ;
76
77 extern "C" {void ActSigIntHandler() ; }
78 #ifndef WIN32
79 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
80 #else
81 extern "C" {void SigIntHandler( int ) ; }
82 #endif
83
84 #ifndef WIN32
85 #define LIB "lib"
86 #ifdef __APPLE__
87 #define ENGINESO "Engine.dylib"
88 #else
89 #define ENGINESO "Engine.so"
90 #endif
91 #else
92 #define LIB ""
93 #define ENGINESO "Engine.dll"
94 #endif
95
96 #ifdef WIN32
97 #define SEP ';'
98 #define SLASH '\\'
99 #else
100 #define SEP ':'
101 #define SLASH '/'
102 #endif
103
104 std::map<std::string, int> Abstract_Engines_Container_i::_cntInstances_map;
105 std::map<std::string, void *> Abstract_Engines_Container_i::_library_map;
106 std::map<std::string, void *> Abstract_Engines_Container_i::_toRemove_map;
107 omni_mutex Abstract_Engines_Container_i::_numInstanceMutex ;
108
109 static PyObject* _pyCont;
110
111 int checkifexecutable(const std::string&);
112 int findpathof(const std::string& path, std::string&, const std::string&);
113
114 /*! \class Engines_Container_i
115  *  \brief C++ implementation of Engines::Container interface
116  *
117  */
118
119
120 //=============================================================================
121 /*! 
122 *  Default constructor, not for use
123 */
124 //=============================================================================
125
126 Abstract_Engines_Container_i::Abstract_Engines_Container_i () :
127   _NS(nullptr),_id(nullptr),_numInstance(0)
128 {
129 }
130
131 //=============================================================================
132 /*! 
133 *  Constructor to use
134 */
135 //=============================================================================
136
137 Abstract_Engines_Container_i::Abstract_Engines_Container_i (CORBA::ORB_ptr orb, 
138                                                             PortableServer::POA_ptr poa,
139                                                             char *containerName ,
140                                                             int argc , char* argv[],
141                                                             SALOME_NamingService_Container_Abstract *ns,
142                                                             bool isServantAloneInProcess
143                                                             ) :
144   _NS(nullptr),_id(0),_numInstance(0),_isServantAloneInProcess(isServantAloneInProcess)
145 {
146   _pid = (long)getpid();
147
148   if(ns)
149     ActSigIntHandler() ;
150
151   _argc = argc ;
152   _argv = argv ;
153
154   std::string hostname = Kernel_Utils::GetHostname();
155 #ifndef WIN32
156   MESSAGE(hostname << " " << getpid() << 
157     " Engines_Container_i starting argc " <<
158     _argc << " Thread " << pthread_self() ) ;
159 #else
160   MESSAGE(hostname << " " << _getpid() << 
161     " Engines_Container_i starting argc " << _argc<< " Thread " << pthread_self().p ) ;
162 #endif
163
164   int i = 0 ;
165   while ( _argv[ i ] )
166   {
167     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
168     i++ ;
169   }
170
171   if ( argc < 2 )
172   {
173     INFOS("SALOME_Container usage : SALOME_Container ServerName");
174     ASSERT(0) ;
175   }
176   SCRUTE(argv[1]);
177   _isSupervContainer = false;
178
179   _orb = CORBA::ORB::_duplicate(orb) ;
180   _poa = PortableServer::POA::_duplicate(poa) ;
181
182   // Pour les containers paralleles: il ne faut pas enregistrer et activer
183   // le container generique, mais le container specialise
184
185   {
186     _id = _poa->activate_object(this);
187     // key point : if ns is nullptr : this servant is alone in its process
188     //             if ns is not null : this servant embedded into single process.
189     _NS = ns==nullptr ? new SALOME_NamingService : ns->clone();
190     _NS->init_orb( _orb ) ;
191     CORBA::Object_var obj=_poa->id_to_reference(*_id);
192     Engines::Container_var pCont = Engines::Container::_narrow(obj);
193     _remove_ref();
194
195     _containerName =  SALOME_NamingService_Abstract::BuildContainerNameForNS(containerName, hostname.c_str());
196     SCRUTE(_containerName);
197     _NS->Register(pCont, _containerName.c_str());
198     MESSAGE("Engines_Container_i::Engines_Container_i : Container name " << _containerName);
199
200     // Python: 
201     // import SALOME_Container
202     // pycont = SALOME_Container.SALOME_Container_i(containerIORStr)
203
204     CORBA::String_var sior =  _orb->object_to_string(pCont);
205     std::string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
206     myCommand += _containerName + "','";
207     myCommand += sior;
208     myCommand += "')\n";
209     SCRUTE(myCommand);
210
211     //[RNV]: Comment the PyEval_AcquireLock() and PyEval_ReleaseLock() because this 
212     //approach leads to the deadlock of the main thread of the application on Windows platform
213     //in case if cppContainer runs in the standalone mode. The problem with the PyThreadState 
214     //described by ABN seems not reproduced, to be checked carefully later...
215     PyGILState_STATE gstate = PyGILState_Ensure();
216     
217     //// [ABN]: using the PyGILState* API here is unstable. omniORB logic is invoked
218     //// by the Python code executed below, and in some (random) cases, the Python code
219     //// execution ends with a PyThreadState which was not the one we have here.
220     //// (TODO: understand why ...)
221     //// To be on the safe side we get and load the thread state ourselves:    
222     //PyEval_AcquireLock();  // get GIL
223     //PyThreadState * mainThreadState = PyThreadState_Get();
224     //PyThreadState_Swap(mainThreadState);
225
226 #ifdef WIN32
227     // mpv: this is temporary solution: there is a unregular crash if not
228     //Sleep(2000);
229     //
230     // first element is the path to Registry.dll, but it's wrong
231     PyRun_SimpleString("import sys\n");
232     PyRun_SimpleString("sys.path = sys.path[1:]\n");
233 #endif
234     PyRun_SimpleString("import SALOME_Container\n");
235     PyRun_SimpleString((char*)myCommand.c_str());
236     PyObject *mainmod = PyImport_AddModule("__main__");
237     PyObject *globals = PyModule_GetDict(mainmod);
238     _pyCont = PyDict_GetItemString(globals, "pyCont");
239
240     //PyThreadState_Swap(NULL);
241     //PyEval_ReleaseLock();
242     PyGILState_Release(gstate);
243
244     fileTransfer_i* aFileTransfer = new fileTransfer_i();
245     CORBA::Object_var obref=aFileTransfer->_this();
246     _fileTransfer = Engines::fileTransfer::_narrow(obref);
247     aFileTransfer->_remove_ref();
248   }
249 }
250
251 //=============================================================================
252 /*! 
253 *  Destructor
254 */
255 //=============================================================================
256
257 Abstract_Engines_Container_i::~Abstract_Engines_Container_i()
258 {
259   MESSAGE("Abstract_Container_i::~Abstract_Container_i()");
260   if(_id)
261     delete _id;
262   if(_NS)
263     delete _NS;
264   cleanAllPyScripts();
265 }
266
267 //=============================================================================
268 //! Get container name
269 /*! 
270 *  CORBA attribute: Container name (see constructor)
271 */
272 //=============================================================================
273
274 char* Abstract_Engines_Container_i::name()
275 {
276   return CORBA::string_dup(_containerName.c_str()) ;
277 }
278
279 //=============================================================================
280 //! Get container working directory
281 /*! 
282 *  CORBA attribute: Container working directory 
283 */
284 //=============================================================================
285
286 char* Abstract_Engines_Container_i::workingdir()
287 {
288   char wd[256];
289   getcwd (wd,256);
290   return CORBA::string_dup(wd) ;
291 }
292
293 //=============================================================================
294 //! Get container log file name
295 /*! 
296 *  CORBA attribute: Container log file name
297 */
298 //=============================================================================
299
300 char* Abstract_Engines_Container_i::logfilename()
301 {
302   return CORBA::string_dup(_logfilename.c_str()) ;
303 }
304
305 //! Set container log file name
306 void Abstract_Engines_Container_i::logfilename(const char* name)
307 {
308   _logfilename=name;
309 }
310
311 //=============================================================================
312 //! Get container host name
313 /*! 
314 *  CORBA method: Get the hostName of the Container (without domain extensions)
315 */
316 //=============================================================================
317
318 char* Abstract_Engines_Container_i::getHostName()
319 {
320   std::string s = Kernel_Utils::GetHostname();
321   //  MESSAGE("Engines_Container_i::getHostName " << s);
322   return CORBA::string_dup(s.c_str()) ;
323 }
324
325 //=============================================================================
326 //! Get container PID
327 /*! 
328 *  CORBA method: Get the PID (process identification) of the Container
329 */
330 //=============================================================================
331
332 CORBA::Long Abstract_Engines_Container_i::getPID()
333 {
334   return (CORBA::Long)getpid();
335 }
336
337 //=============================================================================
338 //! Ping the servant to check it is still alive
339 /*! 
340 *  CORBA method: check if servant is still alive
341 */
342 //=============================================================================
343 void Abstract_Engines_Container_i::ping()
344 {
345   MESSAGE("Engines_Container_i::ping() pid "<< getpid());
346 }
347
348 //=============================================================================
349 //! Get number of CPU cores in the calculation node
350 /*!
351 *  CORBA method: get number of CPU cores
352 */
353 //=============================================================================
354
355 CORBA::Long Abstract_Engines_Container_i::getNumberOfCPUCores()
356 {
357   PyGILState_STATE gstate = PyGILState_Ensure();
358   PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
359   PyObject *result = PyObject_CallMethod(module,
360                                          (char*)"getNumberOfCPUCores", NULL);
361   int n = PyLong_AsLong(result);
362   Py_DECREF(result);
363   PyGILState_Release(gstate);
364
365   return (CORBA::Long)n;
366 }
367
368 //=============================================================================
369 //! Get a load of each CPU core in the calculation node
370 /*!
371 *  CORBA method: get a load of each CPU core
372 */
373 //=============================================================================
374 namespace {
375   std::string parseException()
376   {
377     std::string error;
378     if (PyErr_Occurred())
379     {
380 #ifdef BOS26455_WITH_BOOST_PYTHON
381       PyObject *ptype = nullptr;
382       PyObject *pvalue = nullptr;
383       PyObject *ptraceback = nullptr;
384       PyErr_Fetch(&ptype, &pvalue, &ptraceback);
385       if (ptype == nullptr)
386         return std::string("Null exception type");
387       PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
388       if (ptraceback != nullptr)
389         PyException_SetTraceback(pvalue, ptraceback);
390       boost::python::handle<> htype(ptype);
391       boost::python::handle<> hvalue(boost::python::allow_null(pvalue));
392       boost::python::handle<> htraceback(boost::python::allow_null(ptraceback));
393       boost::python::object traceback = boost::python::import("traceback");
394       boost::python::object format_exc = traceback.attr("format_exception");
395       boost::python::object formatted = format_exc(htype, hvalue, htraceback);
396       error = boost::python::extract<std::string>(boost::python::str("\n").join(formatted));
397 #else
398       error = "Python exception is caught";
399 #endif
400     }
401     return error;
402   }
403 }
404   
405 Engines::vectorOfDouble* Abstract_Engines_Container_i::loadOfCPUCores()
406 {
407   PyGILState_STATE gstate = PyGILState_Ensure();
408   PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
409   PyObject *result = PyObject_CallMethod(module,
410                                          (char*)"loadOfCPUCores", "s",
411                                          _load_script.c_str());
412   if (PyErr_Occurred())
413   {
414     std::string error = parseException();
415     PyErr_Print();
416     PyGILState_Release(gstate);
417     SALOME::ExceptionStruct es;
418     es.type = SALOME::INTERNAL_ERROR;
419     es.text = CORBA::string_dup(error.c_str());
420     throw SALOME::SALOME_Exception(es);
421   }
422
423   int n = this->getNumberOfCPUCores();
424   if (!PyList_Check(result) || PyList_Size(result) != n) {
425     // bad number of cores
426     PyGILState_Release(gstate);
427     Py_DECREF(result);
428     SALOME::ExceptionStruct es;
429     es.type = SALOME::INTERNAL_ERROR;
430     es.text = "wrong number of cores";
431     throw SALOME::SALOME_Exception(es);
432   }
433
434   Engines::vectorOfDouble_var loads = new Engines::vectorOfDouble;
435   loads->length(n);
436   for (Py_ssize_t i = 0; i < PyList_Size(result); ++i) {
437     PyObject* item = PyList_GetItem(result, i);
438     double foo = PyFloat_AsDouble(item);
439     if (foo < 0.0 || foo > 1.0)
440     {
441       // value not in [0, 1] range
442       PyGILState_Release(gstate);
443       Py_DECREF(result);
444       SALOME::ExceptionStruct es;
445       es.type = SALOME::INTERNAL_ERROR;
446       es.text = "load not in [0, 1] range";
447       throw SALOME::SALOME_Exception(es);
448     }
449     loads[i] = foo;
450   }
451
452   Py_DECREF(result);
453   PyGILState_Release(gstate);
454
455   return loads._retn();
456 }
457
458 //=============================================================================
459 //! Set custom script to calculate a load of each CPU core
460 /*!
461 *  CORBA method: Set custom script to calculate CPU load
462 *  \param script Python script to execute
463 */
464 //=============================================================================
465
466 void Abstract_Engines_Container_i::setPyScriptForCPULoad(const char *script)
467 {
468   _load_script = script;
469 }
470
471 //=============================================================================
472 //! Nullify custom script to calculate each CPU core's load
473 /*!
474 *  CORBA method: reset script for load calculation to default implementation
475 */
476 //=============================================================================
477
478 void Abstract_Engines_Container_i::resetScriptForCPULoad()
479 {
480   _load_script = "";
481 }
482
483 //=============================================================================
484 //! Get total physical memory of calculation node, in megabytes
485 /*!
486 *  CORBA method: get total physical memory of calculation node
487 */
488 //=============================================================================
489
490 CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemory()
491 {
492   PyGILState_STATE gstate = PyGILState_Ensure();
493   PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
494   PyObject *result = PyObject_CallMethod(module,
495                                          (char*)"getTotalPhysicalMemory", NULL);
496   int n = PyLong_AsLong(result);
497   Py_DECREF(result);
498   PyGILState_Release(gstate);
499
500   return (CORBA::Long)n;
501 }
502
503 //=============================================================================
504 //! Get used physical memory of calculation node, in megabytes
505 /*!
506 *  CORBA method: get used physical memory of calculation node
507 */
508 //=============================================================================
509
510 CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemoryInUse()
511 {
512   PyGILState_STATE gstate = PyGILState_Ensure();
513   PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
514   PyObject *result = PyObject_CallMethod(module,
515                                          (char*)"getTotalPhysicalMemoryInUse", NULL);
516   int n = PyLong_AsLong(result);
517   Py_DECREF(result);
518   PyGILState_Release(gstate);
519
520   return (CORBA::Long)n;
521 }
522
523 //=============================================================================
524 //! Obtain physical memory, used by the current process, in megabytes.
525 /*!
526 *  CORBA method: get physical memory, used by the current process
527 */
528 //=============================================================================
529
530 CORBA::Long Abstract_Engines_Container_i::getTotalPhysicalMemoryInUseByMe()
531 {
532   PyGILState_STATE gstate = PyGILState_Ensure();
533   PyObject *module = PyImport_ImportModuleNoBlock((char*)"salome_psutil");
534   PyObject *result = PyObject_CallMethod(module,
535                                          (char*)"getTotalPhysicalMemoryInUseByMe", NULL);
536   int n = PyLong_AsLong(result);
537   Py_DECREF(result);
538   PyGILState_Release(gstate);
539
540   return (CORBA::Long)n;
541 }
542
543 //=============================================================================
544 //! Shutdown the container
545 /*! 
546 *  CORBA method, oneway: Server shutdown. 
547 *  - Container name removed from naming service,
548 *  - servant deactivation,
549 *  - orb shutdown if no other servants in the process 
550 */
551 //=============================================================================
552 void Abstract_Engines_Container_i::Shutdown()
553 {
554   MESSAGE("Engines_Container_i::Shutdown()");
555
556   // Clear registered temporary files
557   clearTemporaryFiles();
558
559   /* For each component contained in this container
560   * tell it to self-destroy
561   */
562   std::map<std::string, Engines::EngineComponent_var>::iterator itm;
563   for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
564   {
565     try
566     {
567       itm->second->destroy();
568     }
569     catch(const CORBA::Exception&)
570     {
571       // ignore this entry and continue
572     }
573     catch(...)
574     {
575       // ignore this entry and continue
576     }
577   }
578   _listInstances_map.clear();
579
580   // NS unregistering may throw in SSL mode if master process hosting SALOME_Embedded_NamingService servant has vanished
581   // In this case it's skip it and still continue.
582   try
583   {
584     _NS->Destroy_FullDirectory(_containerName.c_str());
585     _NS->Destroy_Name(_containerName.c_str());
586   }
587   catch(...)
588   {
589   }
590   //
591   this->cleanAllPyScripts();
592   //
593   if(_isServantAloneInProcess)
594   {
595     MESSAGE("Effective Shutdown of container Begins...");
596     if(!CORBA::is_nil(_orb))
597       _orb->shutdown(0);
598   }
599 }
600
601 //=============================================================================
602 //! load a component implementation
603 /*! 
604 *  CORBA method
605 *  \param componentName         component name
606 *  \param reason                explains error when load fails
607 *  \return true if dlopen successful or already done, false otherwise
608 */
609 //=============================================================================
610 bool
611 Abstract_Engines_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
612 {
613
614   //=================================================================
615   // --- C++ implementation section 
616   //=================================================================
617   std::string retso;
618   if(load_component_CppImplementation(componentName,retso))
619   {
620     reason=CORBA::string_dup("");
621     return true;
622   }
623   else if(retso != "ImplementationNotFound")
624   {
625     reason=CORBA::string_dup(retso.c_str());
626     return false;
627   }
628
629   retso="Component ";
630   retso+=componentName;
631   retso+=": Can't find C++ implementation ";
632   retso+=std::string(LIB) + componentName + ENGINESO;
633
634   //=================================================================
635   // --- Python implementation section 
636   //=================================================================
637   std::string retpy;
638   if(load_component_PythonImplementation(componentName,retpy))
639   {
640     reason=CORBA::string_dup("");
641     return true;
642   }
643   else if(retpy != "ImplementationNotFound")
644   {
645     reason=CORBA::string_dup(retpy.c_str());
646     return false;
647   }
648   
649   retpy="Component ";
650   retpy+=componentName;
651   retpy+=": Can't find python implementation ";
652   retpy+=componentName;
653   retpy+="(.py)";
654
655   //=================================================================
656   // -- Executable implementation section
657   //=================================================================
658   std::string retex;
659   if(load_component_ExecutableImplementation(componentName,retex))
660   {
661     reason=CORBA::string_dup("");
662     return true;
663   }
664   else if(retex != "ImplementationNotFound")
665   {
666     reason=CORBA::string_dup(retex.c_str());
667     return false;
668   }
669
670   retex="Component ";
671   retex+=componentName;
672   retex+=": Can't find executable implementation ";
673   retex+=componentName;
674   retex+=".exe";
675
676   std::string ret="Component implementation not found: ";
677   ret += componentName ;
678   ret += '\n' ;
679   ret += retso+ '\n' ;
680   ret += retpy+ '\n' ;
681   ret += retex+ '\n' ;
682
683   std::cerr << ret << std::endl;
684   reason=CORBA::string_dup(ret.c_str());
685
686   return false;
687 }
688
689 //=============================================================================
690 //! try to load a C++ component implementation
691 /*! 
692 *  C++ method: 
693 *  \param componentName      the name of the component (COMPONENT, for example)
694 *  \param reason             explains error when load fails
695 *  \return true if loading is successful or already done, false otherwise
696 */
697 //=============================================================================
698 bool
699 Abstract_Engines_Container_i::load_component_CppImplementation(const char* componentName, std::string& reason)
700 {
701   std::string aCompName(componentName);
702   std::string impl_name = std::string(LIB) + aCompName + ENGINESO;
703   SCRUTE(impl_name);
704
705   _numInstanceMutex.lock(); // lock to be alone
706   // (see decInstanceCnt, finalize_removal))
707   if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name);
708   if (_library_map.count(impl_name) != 0)
709   {
710     MESSAGE("Library " << impl_name << " already loaded");
711     _numInstanceMutex.unlock();
712     reason="";
713     return true;
714   }
715   _numInstanceMutex.unlock();
716
717 #ifndef WIN32
718   void* handle;
719   handle = dlopen( impl_name.c_str() , RTLD_NOW | RTLD_GLOBAL ) ;
720   if ( !handle )
721   {
722     //not loadable. Try to find the lib file in LD_LIBRARY_PATH
723     std::string path;
724 #ifdef __APPLE__
725       char* p=getenv("DYLD_LIBRARY_PATH");
726 #else
727       char* p=getenv("LD_LIBRARY_PATH");
728 #endif
729       if(p)path=p;
730       path=path+SEP+"/usr/lib"+SEP+"/lib";
731
732       std::string pth;
733       if(findpathof(path, pth, impl_name))
734         {
735           //found but not loadable
736           reason="Component ";
737           reason+=aCompName;
738           reason+=": C++ implementation found ";
739           reason+=pth;
740           reason+=" but it is not loadable. Error:\n";
741           reason+=dlerror();
742           std::cerr << reason << std::endl;
743           return false;
744         }
745       else
746         {
747           //not found
748           //continue with other implementation
749           reason="ImplementationNotFound";
750           return false;
751     }
752   }
753 #else
754   HINSTANCE handle;
755 #ifdef UNICODE
756   std::wstring libToLoad = Kernel_Utils::utf8_decode_s( impl_name );
757 #else
758   std::string libToLoad = impl_name;
759 #endif
760   handle = LoadLibrary(libToLoad.c_str() );
761   if ( !handle )
762   {
763     reason="ImplementationNotFound";
764   }
765 #endif
766
767   if ( handle )
768   {
769     _numInstanceMutex.lock();
770     _library_map[impl_name] = handle;
771     _numInstanceMutex.unlock();
772     reason="";
773     return true;
774   }
775
776   return false;
777
778 }
779 //=============================================================================
780 //! try to load a Python component implementation
781 /*! 
782 *  C++ method: 
783 *  \param componentName         name of the component
784 *  \param reason                explains error when load fails
785 *  \return true if loading is successful or already done, false otherwise
786 */
787 //=============================================================================
788 bool
789 Abstract_Engines_Container_i::load_component_PythonImplementation(const char* componentName, std::string& reason)
790 {
791   std::string aCompName(componentName);
792
793   _numInstanceMutex.lock() ; // lock to be alone (stl container write)
794   if (_library_map.count(aCompName) != 0)
795   {
796     _numInstanceMutex.unlock() ;
797     reason="";
798     return true; // Python Component, already imported
799   }
800   _numInstanceMutex.unlock() ;
801
802   PyGILState_STATE gstate = PyGILState_Ensure();
803   PyObject *result = PyObject_CallMethod(_pyCont,
804                                          (char*)"import_component",
805                                          (char*)"s",componentName);
806
807   reason=PyUnicode_AsUTF8(result);
808   Py_XDECREF(result);
809   SCRUTE(reason);
810   PyGILState_Release(gstate);
811
812   if (reason=="")
813   {
814     //Python component has been loaded (import componentName)
815     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
816     _library_map[aCompName] = (void *)_pyCont; // any non O value OK
817     _numInstanceMutex.unlock() ;
818     MESSAGE("import Python: "<< aCompName <<" OK");
819     return true;
820   }
821   else if(reason=="ImplementationNotFound")
822   {
823     //Python implementation has not been found. Continue with other implementation
824     reason="ImplementationNotFound";
825   }
826   else
827   {
828     //Python implementation has been found but loading has failed
829     std::cerr << reason << std::endl;
830   }
831   return false;
832
833 }
834 //=============================================================================
835 //! try to load a Executable component implementation
836 /*! 
837 *  C++ method: 
838 *  \param componentName        name of the component
839 *  \param reason               explains error when load fails
840 *  \return true if loading is successful or already done, false otherwise
841 */
842 //=============================================================================
843 bool
844 Abstract_Engines_Container_i::load_component_ExecutableImplementation(const char* componentName, std::string& reason)
845 {
846   std::string aCompName(componentName);
847   std::string executable=aCompName+".exe";
848
849   std::string path;
850   std::string pth;
851
852   char* p=getenv("PATH");
853   if(p)path=p;
854
855   if (findpathof(path, pth, executable))
856   {
857     if(checkifexecutable(pth))
858     {
859       _numInstanceMutex.lock() ; // lock to be alone (stl container write)
860       _library_map[executable] = (void *)1; // any non O value OK
861       _numInstanceMutex.unlock() ;
862       MESSAGE("import executable: "<< pth <<" OK");
863       reason="";
864       return true;
865     }
866     reason="Component ";
867     reason+=aCompName;
868     reason+=": implementation found ";
869     reason+=pth;
870     reason+=" but it is not executable";
871     std::cerr << reason << std::endl;
872   }
873   else
874   {
875     reason="ImplementationNotFound";
876   }
877   return false;
878 }
879
880 //=============================================================================
881 //! Create a new component instance
882 /*! 
883 *  CORBA method: Creates a new servant instance of a component.
884 *  The servant registers itself to naming service and Registry.
885 *  \param genericRegisterName  Name of the component instance to register
886 *                         in Registry & Name Service (without _inst_n suffix)
887 *  \return a loaded component
888 */
889 //=============================================================================
890 Engines::EngineComponent_ptr
891 Abstract_Engines_Container_i::create_component_instance(const char*genericRegisterName)
892 {
893   Engines::FieldsDict_var env = new Engines::FieldsDict;
894   char* reason;
895   Engines::EngineComponent_ptr compo =
896     create_component_instance_env(genericRegisterName, env, reason);
897   CORBA::string_free(reason);
898   return compo;
899 }
900
901 //=============================================================================
902 //! Create a new component instance with environment variables specified
903 /*! 
904 *  CORBA method: Creates a new servant instance of a component.
905 *  The servant registers itself to naming service and Registry.
906 *  \param genericRegisterName  Name of the component instance to register
907 *                         in Registry & Name Service (without _inst_n suffix)
908 *  \param env             dict of env variables
909 *  \param reason          explains error when create_component_instance_env fails
910 *  \return a loaded component
911 */
912 //=============================================================================
913 Engines::EngineComponent_ptr
914 Abstract_Engines_Container_i::create_component_instance_env(const char*genericRegisterName,
915                                                    const Engines::FieldsDict& env,
916                                                    CORBA::String_out reason)
917 {
918   std::string error;
919   if (_library_map.count(genericRegisterName) != 0)
920   {
921     // It's a Python component
922     Engines::EngineComponent_ptr compo = createPythonInstance(genericRegisterName, error);
923     reason=CORBA::string_dup(error.c_str());
924     return compo;
925   }
926
927   std::string impl_name = std::string(LIB) + genericRegisterName + ENGINESO;
928   if (_library_map.count(impl_name) != 0)
929   {
930     // It's a C++ component
931     void* handle = _library_map[impl_name];
932     Engines::EngineComponent_ptr compo = createInstance(genericRegisterName, handle, error);
933     reason=CORBA::string_dup(error.c_str());
934     return compo;
935   }
936
937   impl_name = std::string(genericRegisterName) + ".exe";
938   if (_library_map.count(impl_name) != 0)
939   {
940     //It's an executable component
941     Engines::EngineComponent_ptr compo = createExecutableInstance(genericRegisterName, env, error);
942     reason=CORBA::string_dup(error.c_str());
943     return compo;
944   }
945
946   error="load_component_Library has probably not been called for component: ";
947   error += genericRegisterName;
948   INFOS(error);
949   reason=CORBA::string_dup(error.c_str());
950   return Engines::EngineComponent::_nil() ;
951 }
952
953 //=============================================================================
954 //! Create a new component instance (Executable implementation)
955 /*! 
956 *  \param CompName               Name of the component instance
957 *  \param env                    dict of env variables
958 *  \param reason                 explains error when creation fails
959 *  \return a loaded component
960 *
961 *   This component is implemented in an executable with name genericRegisterName.exe
962 *   It must register itself in Naming Service. The container waits some time (10 s max)
963 *   it's registration.
964 */
965 //=============================================================================
966 Engines::EngineComponent_ptr
967 Abstract_Engines_Container_i::createExecutableInstance(std::string CompName,
968                                                       const Engines::FieldsDict& env,
969                                                       std::string& reason)
970 {
971   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
972
973   _numInstanceMutex.lock() ; // lock on the instance number
974   _numInstance++ ;
975   int numInstance = _numInstance ;
976   _numInstanceMutex.unlock() ;
977
978   char aNumI[12];
979   sprintf( aNumI , "%d" , numInstance ) ;
980   std::string instanceName = CompName + "_inst_" + aNumI ;
981   std::string component_registerName = _containerName + "/" + instanceName;
982
983   //check if an entry exist in naming service
984   CORBA::Object_var nsobj = _NS->Resolve(component_registerName.c_str());
985   if ( !CORBA::is_nil(nsobj) )
986   {
987     // unregister the registered component
988     _NS->Destroy_Name(component_registerName.c_str());
989     //kill or shutdown it ???
990   }
991
992   // first arg container ior string
993   // second arg container name
994   // third arg instance name
995
996   Engines::Container_var pCont= _this();
997   CORBA::String_var sior =  _orb->object_to_string(pCont);
998
999   std::string command;
1000   command="mkdir -p ";
1001   command+=instanceName;
1002   command+=";cd ";
1003   command+=instanceName;
1004   command+=";";
1005   command+=CompName ;
1006   command+=".exe";
1007   command+=" ";
1008   command+= sior; // container ior string
1009   command+=" ";
1010   command+=_containerName; //container name
1011   command+=" ";
1012   command+=instanceName; //instance name
1013   command+=" &";
1014   MESSAGE("SALOME_Container::create_component_instance command=" << command);
1015
1016 #ifndef WIN32
1017   // use fork/execl instead of system to get finer control on env variables
1018   int status;
1019   pid_t pid = fork();
1020   if(pid == 0) // child
1021   {
1022     for (CORBA::ULong i=0; i < env.length(); i++)
1023     {
1024       if (env[i].value.type()->kind() == CORBA::tk_string)
1025       {
1026         const char* value;
1027         env[i].value >>= value;
1028         std::string s(env[i].key);
1029         s+='=';
1030         s+=value;
1031         putenv(strdup(s.c_str()));
1032       }
1033     }
1034
1035     execl("/bin/sh", "sh", "-c", command.c_str() , (char *)0);
1036     status=-1;
1037   }
1038   else if(pid < 0)       // failed to fork
1039   {
1040     status=-1;
1041   }
1042   else            //parent
1043   {
1044     pid_t tpid;
1045     do
1046     {
1047       tpid = wait(&status);
1048     } while (tpid != pid);
1049   }
1050 #else
1051   // launch component with a system call
1052   int status=system(command.c_str());
1053 #endif
1054
1055   if (status == -1)
1056   {
1057     reason="SALOME_Container::create_component_instance system failed (system command status -1)";
1058     MESSAGE(reason);
1059     return Engines::EngineComponent::_nil();
1060   }
1061 #ifndef WIN32
1062   else if (WEXITSTATUS(status) == 217)
1063   {
1064     reason="SALOME_Container::create_component_instance system failed (system command status 217)";
1065     MESSAGE(reason);
1066     return Engines::EngineComponent::_nil();
1067   }
1068 #endif
1069   else
1070   {
1071     int count=20;
1072     if (getenv("TIMEOUT_TO_WAIT_EXE_COMPONENT") != 0)
1073     {
1074       std::string new_count_str = getenv("TIMEOUT_TO_WAIT_EXE_COMPONENT");
1075       int new_count;
1076       std::istringstream ss(new_count_str);
1077       if (!(ss >> new_count))
1078       {
1079         INFOS("[Container] TIMEOUT_TO_WAIT_EXE_COMPONENT should be an int");
1080       }
1081       else
1082         count = new_count;
1083     }
1084     INFOS("[Container] waiting " << count << " second steps exe component ");
1085     CORBA::Object_var obj = CORBA::Object::_nil() ;
1086     while ( CORBA::is_nil(obj) && count )
1087     {
1088 #ifndef WIN32
1089       sleep( 1 ) ;
1090 #else
1091       Sleep(1000);
1092 #endif
1093       count-- ;
1094       MESSAGE( count << ". Waiting for component " << CompName);
1095       obj = _NS->Resolve(component_registerName.c_str());
1096     }
1097
1098     if(CORBA::is_nil(obj))
1099     {
1100       reason="SALOME_Container::create_component_instance failed";
1101       MESSAGE(reason);
1102       return Engines::EngineComponent::_nil();
1103     }
1104     else
1105     {
1106       MESSAGE("SALOME_Container::create_component_instance successful");
1107       iobject = Engines::EngineComponent::_narrow(obj);
1108       _listInstances_map[instanceName] = iobject;
1109       return iobject._retn();
1110     }
1111   }
1112 }
1113
1114
1115 //=============================================================================
1116 //! Create a new component instance (Python implementation)
1117 /*! 
1118 *  \param CompName               Name of the component instance
1119 *  \param reason                 explains error when creation fails
1120 *  \return a loaded component
1121 */
1122 //=============================================================================
1123 Engines::EngineComponent_ptr
1124 Abstract_Engines_Container_i::createPythonInstance(std::string CompName,
1125                                           std::string& reason)
1126 {
1127   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
1128
1129   _numInstanceMutex.lock() ; // lock on the instance number
1130   _numInstance++ ;
1131   int numInstance = _numInstance ;
1132   _numInstanceMutex.unlock() ;
1133
1134   char aNumI[12];
1135   sprintf( aNumI , "%d" , numInstance ) ;
1136   std::string instanceName = CompName + "_inst_" + aNumI ;
1137   std::string component_registerName = _containerName + "/" + instanceName;
1138
1139   PyGILState_STATE gstate = PyGILState_Ensure();
1140   PyObject *result = PyObject_CallMethod(_pyCont,
1141                                          (char*)"create_component_instance",
1142                                          (char*)"ss",
1143                                          CompName.c_str(),
1144                                          instanceName.c_str());
1145   const char *ior;
1146   const char *error;
1147   PyArg_ParseTuple(result,"ss", &ior, &error);
1148   std::string iors = ior;
1149   reason=error;
1150   Py_DECREF(result);
1151   PyGILState_Release(gstate);
1152
1153   if( iors!="" )
1154   {
1155     CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
1156     iobject = Engines::EngineComponent::_narrow( obj ) ;
1157     _listInstances_map[instanceName] = iobject;
1158   }
1159   return iobject._retn();
1160 }
1161
1162 char *
1163 Abstract_Engines_Container_i::create_python_service_instance(const char * CompName,
1164                                                     CORBA::String_out reason)
1165 {
1166   CORBA::Object_var object = CORBA::Object::_nil();
1167
1168   _numInstanceMutex.lock() ; // lock on the instance number
1169   _numInstance++ ;
1170   int numInstance = _numInstance ;
1171   _numInstanceMutex.unlock() ;
1172
1173   char aNumI[12];
1174   sprintf( aNumI , "%d" , numInstance ) ;
1175   std::string instanceName = std::string(CompName) + "_inst_" + aNumI ;
1176   std::string component_registerName = _containerName + "/" + instanceName;
1177
1178   PyGILState_STATE gstate = PyGILState_Ensure();
1179   PyObject *result = PyObject_CallMethod(_pyCont,
1180                                          (char*)"create_component_instance",
1181                                          (char*)"ss",
1182                                          CompName,
1183                                          instanceName.c_str());
1184   const char *ior;
1185   const char *error;
1186   PyArg_ParseTuple(result,"ss", &ior, &error);
1187   reason = CORBA::string_dup(error);
1188   char * _ior = CORBA::string_dup(ior);
1189   Py_DECREF(result);
1190   PyGILState_Release(gstate);
1191
1192   return _ior;
1193 }
1194
1195
1196 //=============================================================================
1197 //! Create a new component instance (C++ implementation)
1198 /*! 
1199 *  C++ method: create a servant instance of a component.
1200 *  \param genericRegisterName    Name of the component instance to register
1201 *                                in Registry & Name Service,
1202 *                                (without _inst_n suffix, like "COMPONENT")
1203 *  \param handle                 loaded library handle
1204 *  \param reason                 explains error when creation fails
1205 *  \return a loaded component
1206
1207 *  example with names:
1208 *    - aGenRegisterName = COMPONENT (= first argument)
1209 *    - _containerName = /Containers/cli76ce/FactoryServer
1210 *    - factoryName = COMPONENTEngine_factory
1211 *    - component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
1212 *    - instanceName = COMPONENT_inst_1
1213 *    - component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
1214 */
1215 //=============================================================================
1216 Engines::EngineComponent_ptr
1217 Abstract_Engines_Container_i::createInstance(std::string genericRegisterName,
1218                                     void *handle,
1219                                     std::string& reason)
1220 {
1221   // --- find the factory
1222
1223   std::string aGenRegisterName = genericRegisterName;
1224   std::string factory_name = aGenRegisterName + std::string("Engine_factory");
1225   SCRUTE(factory_name) ;
1226
1227   typedef PortableServer::ObjectId* (*FACTORY_FUNCTION) (CORBA::ORB_ptr,
1228                                                          PortableServer::POA_ptr, 
1229                                                          PortableServer::ObjectId *, 
1230                                                          const char *, 
1231                                                          const char *) ;
1232
1233 #ifndef WIN32
1234   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)dlsym( handle, factory_name.c_str() );
1235 #else
1236   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)GetProcAddress( (HINSTANCE)handle, factory_name.c_str() );
1237 #endif
1238
1239   if ( !Component_factory )
1240   {
1241     MESSAGE( "Can't resolve symbol: " + factory_name );
1242 #ifndef WIN32
1243     reason=dlerror();
1244     MESSAGE(reason);
1245 #endif
1246     return Engines::EngineComponent::_nil() ;
1247   }
1248
1249   // --- create instance
1250
1251   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
1252
1253   try
1254   {
1255     _numInstanceMutex.lock() ; // lock on the instance number
1256     _numInstance++ ;
1257     int numInstance = _numInstance ;
1258     _numInstanceMutex.unlock() ;
1259
1260     char aNumI[12];
1261     sprintf( aNumI , "%d" , numInstance ) ;
1262     std::string instanceName = aGenRegisterName + "_inst_" + aNumI ;
1263     std::string component_registerName =
1264       _containerName + "/" + instanceName;
1265
1266     // --- Instantiate required CORBA object
1267
1268     PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
1269     id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
1270                                                 aGenRegisterName.c_str() ) ;
1271     if (id == NULL)
1272     {
1273       reason="Can't get ObjectId from factory";
1274       INFOS(reason);
1275       return iobject._retn();
1276     }
1277
1278     // --- get reference from id
1279
1280     CORBA::Object_var obj = _poa->id_to_reference(*id);
1281     iobject = Engines::EngineComponent::_narrow( obj ) ;
1282
1283     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
1284     _listInstances_map[instanceName] = iobject;
1285     _cntInstances_map[aGenRegisterName] += 1;
1286     _numInstanceMutex.unlock() ;
1287     SCRUTE(aGenRegisterName);
1288     SCRUTE(_cntInstances_map[aGenRegisterName]);
1289
1290     // --- register the engine under the name
1291     //     containerName(.dir)/instanceName(.object)
1292
1293     _NS->Register( iobject , component_registerName.c_str() ) ;
1294     MESSAGE( component_registerName.c_str() << " bound" ) ;
1295   }
1296   catch (...)
1297   {
1298     reason="Container_i::createInstance exception caught";
1299     INFOS(reason) ;
1300   }
1301   return iobject._retn();
1302 }
1303
1304 //=============================================================================
1305 //! Find an existing (in the container) component instance
1306 /*!
1307 *  CORBA method: Finds a servant instance of a component
1308 *  \param registeredName  Name of the component in Registry or Name Service,
1309 *                         without instance suffix number
1310 *  \return the first found instance
1311 */
1312 //=============================================================================
1313 Engines::EngineComponent_ptr
1314 Abstract_Engines_Container_i::find_component_instance( const char* registeredName)
1315 {
1316   Engines::EngineComponent_var anEngine = Engines::EngineComponent::_nil();
1317   std::map<std::string,Engines::EngineComponent_var>::iterator itm =_listInstances_map.begin();
1318   while (itm != _listInstances_map.end())
1319   {
1320     std::string instance = (*itm).first;
1321     SCRUTE(instance);
1322     if (instance.find(registeredName) == 0)
1323     {
1324       anEngine = (*itm).second;
1325       return anEngine._retn();
1326     }
1327     itm++;
1328   }
1329   return anEngine._retn();
1330 }
1331
1332 //=============================================================================
1333 //! Remove the component instance from container
1334 /*!
1335 *  CORBA method: Stops the component servant, and deletes all related objects
1336 *  \param component_i     Component to be removed
1337 */
1338 //=============================================================================
1339
1340 void Abstract_Engines_Container_i::remove_impl(Engines::EngineComponent_ptr component_i)
1341 {
1342   ASSERT(! CORBA::is_nil(component_i));
1343   std::string instanceName = component_i->instanceName() ;
1344   MESSAGE("unload component " << instanceName);
1345   _numInstanceMutex.lock() ; // lock to be alone (stl container write)
1346   _listInstances_map.erase(instanceName);
1347   _numInstanceMutex.unlock() ;
1348   component_i->destroy() ;
1349   _NS->Destroy_Name(instanceName.c_str());
1350 }
1351
1352 //=============================================================================
1353 //! Unload component libraries from the container
1354 /*!
1355 *  CORBA method: Discharges unused libraries from the container.
1356 */
1357 //=============================================================================
1358 void Abstract_Engines_Container_i::finalize_removal()
1359 {
1360   MESSAGE("finalize unload : dlclose");
1361   _numInstanceMutex.lock(); // lock to be alone
1362   // (see decInstanceCnt, load_component_Library)
1363   std::map<std::string, void *>::iterator ith;
1364   for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
1365   {
1366     void *handle = (*ith).second;
1367     std::string impl_name= (*ith).first;
1368     if (handle)
1369     {
1370       SCRUTE(handle);
1371       SCRUTE(impl_name);
1372       //        dlclose(handle);                // SALOME unstable after ...
1373       //        _library_map.erase(impl_name);
1374     }
1375   }
1376   _toRemove_map.clear();
1377   _numInstanceMutex.unlock();
1378 }
1379
1380 //=============================================================================
1381 //! Decrement component instance reference count
1382 /*!
1383 *
1384 */
1385 //=============================================================================
1386 void Abstract_Engines_Container_i::decInstanceCnt(std::string genericRegisterName)
1387 {
1388   if(_cntInstances_map.count(genericRegisterName)==0)
1389     return;
1390   std::string aGenRegisterName =genericRegisterName;
1391   MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName);
1392   ASSERT(_cntInstances_map[aGenRegisterName] > 0);
1393   _numInstanceMutex.lock(); // lock to be alone
1394   // (see finalize_removal, load_component_Library)
1395   _cntInstances_map[aGenRegisterName] -= 1;
1396   SCRUTE(_cntInstances_map[aGenRegisterName]);
1397   if (_cntInstances_map[aGenRegisterName] == 0)
1398   {
1399     std::string impl_name =
1400       Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
1401     SCRUTE(impl_name);
1402     void* handle = _library_map[impl_name];
1403     ASSERT(handle);
1404     _toRemove_map[impl_name] = handle;
1405   }
1406   _numInstanceMutex.unlock();
1407 }
1408
1409 //=============================================================================
1410 //! Find or create a new component instance
1411 /*!
1412 *  CORBA method: find or create an instance of the component (servant),
1413 *  load a new component class (dynamic library) if required,
1414 *
1415 *  ---- FOR COMPATIBILITY WITH 2.2 ----
1416 *
1417 *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
1418 *
1419 *  The servant registers itself to naming service and Registry.
1420 *  \param genericRegisterName  Name of the component to register
1421 *                              in Registry & Name Service
1422 *  \param componentName       Name of the constructed library of the component
1423 *  \return a loaded component
1424 */
1425 //=============================================================================
1426
1427 Engines::EngineComponent_ptr
1428 Abstract_Engines_Container_i::load_impl( const char* genericRegisterName,
1429                                          const char* /*componentName*/ )
1430 {
1431   char* reason;
1432   std::string impl_name = std::string(LIB) + genericRegisterName + ENGINESO;
1433   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
1434   if (load_component_Library(genericRegisterName,reason))
1435     iobject = find_or_create_instance(genericRegisterName, impl_name);
1436   CORBA::string_free(reason);
1437   return iobject._retn();
1438 }
1439
1440 Engines::EmbeddedNamingService_ptr Abstract_Engines_Container_i::get_embedded_NS_if_ssl()
1441 {
1442   SALOME_Embedded_NamingService_Client *nsc(dynamic_cast<SALOME_Embedded_NamingService_Client *>(this->_NS));
1443   if(nsc)
1444   {
1445     Engines::EmbeddedNamingService_var obj = nsc->GetObject();
1446     return Engines::EmbeddedNamingService::_duplicate(obj);
1447   }
1448   else
1449   {
1450     return Engines::EmbeddedNamingService::_nil();
1451   } 
1452 }
1453
1454 //=============================================================================
1455 //! Finds an already existing component instance or create a new instance
1456 /*!
1457 *  C++ method: Finds an already existing servant instance of a component, or
1458 *              create an instance.
1459 *  ---- USE ONLY FOR MULTISTUDY INSTANCES ! --------
1460 *  \param genericRegisterName    Name of the component instance to register
1461 *                                in Registry & Name Service,
1462 *                                (without _inst_n suffix, like "COMPONENT")
1463 *  \param componentLibraryName   like "libCOMPONENTEngine.so"
1464 *  \return a loaded component
1465 *
1466 *  example with names:
1467 *    - aGenRegisterName = COMPONENT (= first argument)
1468 *    - impl_name = libCOMPONENTEngine.so (= second argument)
1469 *    - _containerName = /Containers/cli76ce/FactoryServer
1470 *    - factoryName = COMPONENTEngine_factory
1471 *    - component_registerBase = /Containers/cli76ce/FactoryServer/COMPONENT
1472 *    - instanceName = COMPONENT_inst_1
1473 *    - component_registerName = /Containers/cli76ce/FactoryServer/COMPONENT_inst_1
1474 */
1475 //=============================================================================
1476
1477 Engines::EngineComponent_ptr
1478 Abstract_Engines_Container_i::find_or_create_instance(std::string genericRegisterName,
1479                                                       std::string componentLibraryName)
1480 {
1481   std::string aGenRegisterName = genericRegisterName;
1482   std::string impl_name = componentLibraryName;
1483   if (_library_map.count(impl_name) == 0)
1484   {
1485     INFOS("shared library " << impl_name <<" must be loaded before creating instance");
1486     return Engines::EngineComponent::_nil() ;
1487   }
1488   else
1489   {
1490     // --- find a registered instance in naming service, or create
1491
1492     void* handle = _library_map[impl_name];
1493     std::string component_registerBase =
1494       _containerName + "/" + aGenRegisterName;
1495     Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
1496     std::string reason;
1497     try
1498     {
1499       CORBA::Object_var obj =
1500         _NS->ResolveFirst( component_registerBase.c_str());
1501       if ( CORBA::is_nil( obj ) )
1502       {
1503         iobject = createInstance(genericRegisterName,
1504                                  handle,
1505                                  reason);
1506       }
1507       else
1508       {
1509         iobject = Engines::EngineComponent::_narrow( obj ) ;
1510       }
1511     }
1512     catch (...)
1513     {
1514       INFOS( "Container_i::load_impl caught" ) ;
1515     }
1516     return iobject._retn();
1517   }
1518 }
1519
1520 //=============================================================================
1521 //! Indicate if container is a python one
1522 /*! 
1523 *  Retrieves only with container naming convention if it is a python container
1524 */
1525 //=============================================================================
1526 bool Abstract_Engines_Container_i::isPythonContainer(const char* ContainerName)
1527 {
1528   bool ret=false;
1529   size_t len=strlen(ContainerName);
1530   if(len>=2)
1531     if(strcmp(ContainerName+len-2,"Py")==0)
1532       ret=true;
1533   return ret;
1534 }
1535
1536 //=============================================================================
1537 //! Kill the container
1538 /*!
1539 *  CORBA method: Kill the container process with exit(0).
1540 *  To remove :  never returns !
1541 */
1542 //=============================================================================
1543 bool Abstract_Engines_Container_i::Kill_impl()
1544 {
1545   MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
1546     << _containerName.c_str() << " machineName "
1547     << Kernel_Utils::GetHostname().c_str());
1548   INFOS("===============================================================");
1549   INFOS("= REMOVE calls to Kill_impl in C++ container                  =");
1550   INFOS("===============================================================");
1551   //_exit( 0 ) ;
1552   ASSERT(0);
1553   return false;
1554 }
1555
1556 //=============================================================================
1557 /*! 
1558 *  
1559 */
1560 //=============================================================================
1561 void ActSigIntHandler()
1562 {
1563 #ifndef WIN32
1564   struct sigaction SigIntAct ;
1565   SigIntAct.sa_sigaction = &SigIntHandler ;
1566   sigemptyset(&SigIntAct.sa_mask);
1567   SigIntAct.sa_flags = SA_SIGINFO ;
1568 #endif
1569
1570   // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
1571   // (SIGINT | SIGUSR1) :
1572   // it must be only one signal ===> one call for SIGINT 
1573   // and an other one for SIGUSR1
1574
1575 #ifndef WIN32
1576   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) 
1577   {
1578     perror("SALOME_Container main ") ;
1579     exit(0) ;
1580   }
1581   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) )
1582   {
1583     perror("SALOME_Container main ") ;
1584     exit(0) ;
1585   }
1586   if ( sigaction( SIGUSR2 , &SigIntAct, NULL ) )
1587   {
1588     perror("SALOME_Container main ") ;
1589     exit(0) ;
1590   }
1591
1592   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
1593   //             use of streams (and so on) should never be used because :
1594   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
1595   //             A stream operation may be interrupted by a signal and if the Handler use stream we
1596   //             may have a "Dead-Lock" ===HangUp
1597   //==INFOS is commented
1598   //  INFOS(pthread_self() << "SigIntHandler activated") ;
1599
1600 #else  
1601   signal( SIGINT, SigIntHandler );
1602 // legacy code required to supervisor. Commented in order to avoid problems on Windows 
1603 //  signal( SIGUSR1, SigIntHandler );
1604 #endif
1605
1606 }
1607
1608 void SetCpuUsed() ;
1609 void CallCancelThread() ;
1610
1611 #ifndef WIN32
1612 void SigIntHandler(int /*what*/ ,
1613                    siginfo_t * siginfo ,
1614                    void * /*toto*/ ) 
1615 {
1616   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
1617   //             use of streams (and so on) should never be used because :
1618   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
1619   //             A stream operation may be interrupted by a signal and if the Handler use stream we
1620   //             may have a "Dead-Lock" ===HangUp
1621   //==MESSAGE is commented
1622   //  MESSAGE(pthread_self() << "SigIntHandler what     " << what << std::endl
1623   //          << "              si_signo " << siginfo->si_signo << std::endl
1624   //          << "              si_code  " << siginfo->si_code << std::endl
1625   //          << "              si_pid   " << siginfo->si_pid) ;
1626
1627   if ( _Sleeping )
1628   {
1629     _Sleeping = false ;
1630     //     MESSAGE("SigIntHandler END sleeping.") ;
1631     return ;
1632   }
1633   else
1634   {
1635     ActSigIntHandler() ;
1636     if ( siginfo->si_signo == SIGUSR1 )
1637     {
1638       SetCpuUsed() ;
1639     }
1640     else if ( siginfo->si_signo == SIGUSR2 )
1641     {
1642       CallCancelThread() ;
1643     }
1644     else 
1645     {
1646       _Sleeping = true ;
1647       //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
1648       int count = 0 ;
1649       while( _Sleeping )
1650       {
1651         sleep( 1 ) ;
1652         count += 1 ;
1653       }
1654       //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
1655     }
1656     return ;
1657   }
1658 }
1659 #else // Case WIN32
1660 void SigIntHandler( int what )
1661 {
1662 #ifndef WIN32
1663   MESSAGE( pthread_self() << "SigIntHandler what     " << what << std::endl );
1664 #else
1665   MESSAGE( "SigIntHandler what     " << what << std::endl );
1666 #endif
1667   if ( _Sleeping )
1668   {
1669     _Sleeping = false ;
1670     MESSAGE("SigIntHandler END sleeping.") ;
1671     return ;
1672   }
1673   else
1674   {
1675     ActSigIntHandler() ;
1676     if ( what == SIGUSR1 )
1677     {
1678       SetCpuUsed() ;
1679     }
1680     else
1681     {
1682       _Sleeping = true ;
1683       MESSAGE("SigIntHandler BEGIN sleeping.") ;
1684       int count = 0 ;
1685       while( _Sleeping ) 
1686       {
1687         Sleep( 1000 ) ;
1688         count += 1 ;
1689       }
1690       MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
1691     }
1692     return ;
1693   }
1694 }
1695 #endif
1696
1697 //=============================================================================
1698 //! Get or create a file reference object associated to a local file (to transfer it)
1699 /*!
1700 *  CORBA method: get or create a fileRef object associated to a local file
1701 *  (a file on the computer on which runs the container server), which stores
1702 *  a list of (machine, localFileName) corresponding to copies already done.
1703 *
1704 *  \param  origFileName absolute path for a local file to copy on other
1705 *          computers
1706 *  \return a fileRef object associated to the file.
1707 */
1708 //=============================================================================
1709 Engines::fileRef_ptr
1710 Abstract_Engines_Container_i::createFileRef(const char* origFileName)
1711 {
1712   std::string origName(origFileName);
1713   Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
1714
1715   if (origName[0] != '/')
1716   {
1717     INFOS("path of file to copy must be an absolute path beginning with '/'");
1718     return Engines::fileRef::_nil();
1719   }
1720
1721   if (CORBA::is_nil(_fileRef_map[origName]))
1722   {
1723     CORBA::Object_var obj=_poa->id_to_reference(*_id);
1724     Engines::Container_var pCont = Engines::Container::_narrow(obj);
1725     fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
1726     theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
1727     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
1728     _fileRef_map[origName] = theFileRef;
1729     _numInstanceMutex.unlock() ;
1730   }
1731
1732   theFileRef =  Engines::fileRef::_duplicate(_fileRef_map[origName]);
1733   ASSERT(! CORBA::is_nil(theFileRef));
1734   return theFileRef._retn();
1735 }
1736
1737 //=============================================================================
1738 //! Get a fileTransfer reference
1739 /*!
1740 *  CORBA method:
1741 *  \return a reference to the fileTransfer object
1742 */
1743 //=============================================================================
1744 Engines::fileTransfer_ptr
1745 Abstract_Engines_Container_i::getFileTransfer()
1746 {
1747   Engines::fileTransfer_var aFileTransfer
1748     = Engines::fileTransfer::_duplicate(_fileTransfer);
1749   return aFileTransfer._retn();
1750 }
1751
1752 //=============================================================================
1753 //! Create a Salome file
1754 //=============================================================================
1755 Engines::Salome_file_ptr
1756 Abstract_Engines_Container_i::createSalome_file(const char* origFileName)
1757 {
1758   std::string origName(origFileName);
1759   if (CORBA::is_nil(_Salome_file_map[origName]))
1760   {
1761     Salome_file_i* aSalome_file = new Salome_file_i();
1762     aSalome_file->setContainer(Engines::Container::_duplicate(this->_this()));
1763     try
1764     {
1765       aSalome_file->setLocalFile(origFileName);
1766       aSalome_file->recvFiles();
1767     }
1768     catch (const SALOME::SALOME_Exception& /*e*/) //!< TODO: unused variable
1769     {
1770       return Engines::Salome_file::_nil();
1771     }
1772
1773     Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
1774     theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
1775     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
1776     _Salome_file_map[origName] = theSalome_file;
1777     _numInstanceMutex.unlock() ;
1778   }
1779
1780   Engines::Salome_file_ptr theSalome_file =
1781     Engines::Salome_file::_duplicate(_Salome_file_map[origName]);
1782   ASSERT(!CORBA::is_nil(theSalome_file));
1783   return theSalome_file;
1784 }
1785
1786 //=============================================================================
1787 /*! \brief copy a file from a remote host (container) to the local host
1788  * \param container the remote container
1789  * \param remoteFile the file to copy locally from the remote host into localFile
1790  * \param localFile the local file
1791  */
1792 //=============================================================================
1793 void Abstract_Engines_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
1794 {
1795   Engines::fileTransfer_var fileTransfer = container->getFileTransfer();
1796
1797   FILE* fp;
1798   if ((fp = fopen(localFile,"wb")) == NULL)
1799   {
1800     INFOS("file " << localFile << " cannot be open for writing");
1801     return;
1802   }
1803
1804   CORBA::Long fileId = fileTransfer->open(remoteFile);
1805   if (fileId > 0)
1806   {
1807     Engines::fileBlock* aBlock;
1808     int toFollow = 1;
1809     int ctr=0;
1810     while (toFollow)
1811     {
1812       ctr++;
1813       //SCRUTE(ctr);
1814       aBlock = fileTransfer->getBlock(fileId);
1815       toFollow = aBlock->length();
1816       //SCRUTE(toFollow);
1817       CORBA::Octet *buf = aBlock->get_buffer();
1818       fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
1819       delete aBlock;
1820     }
1821     fclose(fp);
1822     MESSAGE("end of transfer");
1823     fileTransfer->close(fileId);
1824   }
1825   else
1826   {
1827     INFOS("open reference file for copy impossible");
1828   }
1829 }
1830
1831 //=============================================================================
1832 /*! \brief create a PyNode object to execute remote python code
1833  * \param nodeName the name of the node
1834  * \param code the python code to load
1835  * \return the PyNode
1836  */
1837 //=============================================================================
1838 Engines::PyNode_ptr Abstract_Engines_Container_i::createPyNode(const char* nodeName, const char* code)
1839 {
1840   Engines::PyNode_var node= Engines::PyNode::_nil();
1841
1842   PyGILState_STATE gstate = PyGILState_Ensure();
1843   PyObject *res = PyObject_CallMethod(_pyCont,
1844     (char*)"create_pynode",
1845     (char*)"ss",
1846     nodeName,
1847     code);
1848   if(res==NULL)
1849   {
1850     //internal error
1851     PyErr_Print();
1852     PyGILState_Release(gstate);
1853     SALOME::ExceptionStruct es;
1854     es.type = SALOME::INTERNAL_ERROR;
1855     es.text = "can not create a python node";
1856     throw SALOME::SALOME_Exception(es);
1857   }
1858   long ierr=PyLong_AsLong(PyTuple_GetItem(res,0));
1859   PyObject* result=PyTuple_GetItem(res,1);
1860   std::string astr=PyUnicode_AsUTF8(result);
1861   Py_DECREF(res);
1862   PyGILState_Release(gstate);
1863   if(ierr==0)
1864   {
1865     Utils_Locker lck(&_mutexForDftPy);
1866     CORBA::Object_var obj=_orb->string_to_object(astr.c_str());
1867     node=Engines::PyNode::_narrow(obj);
1868     std::map<std::string,Engines::PyNode_var>::iterator it(_dftPyNode.find(nodeName));
1869     if(it==_dftPyNode.end())
1870     {
1871       _dftPyNode[nodeName]=node;
1872     }
1873     else
1874     {
1875       Engines::PyNode_var oldNode((*it).second);
1876       if(!CORBA::is_nil(oldNode))
1877         oldNode->UnRegister();
1878       (*it).second=node;
1879     }
1880     if(!CORBA::is_nil(node))
1881       node->Register();
1882     return node._retn();
1883   }
1884   else
1885   {
1886     SALOME::ExceptionStruct es;
1887     es.type = SALOME::INTERNAL_ERROR;
1888     es.text = astr.c_str();
1889     throw SALOME::SALOME_Exception(es);
1890   }
1891 }
1892
1893 //=============================================================================
1894 /*! \brief Retrieves the last created PyNode instance with createPyNode.
1895  *
1896  */
1897 //=============================================================================
1898 Engines::PyNode_ptr Abstract_Engines_Container_i::getDefaultPyNode(const char *nodeName)
1899 {
1900   Utils_Locker lck(&_mutexForDftPy);
1901   std::map<std::string,Engines::PyNode_var>::iterator it(_dftPyNode.find(nodeName));
1902   if(it==_dftPyNode.end())
1903     return Engines::PyNode::_nil();
1904   else
1905   {
1906     Engines::PyNode_var tmpVar((*it).second);
1907     if(!CORBA::is_nil(tmpVar))
1908       return Engines::PyNode::_duplicate(tmpVar);
1909     else
1910       return Engines::PyNode::_nil();
1911   }
1912 }
1913
1914 //=============================================================================
1915 /*! \brief create a PyScriptNode object to execute remote python code
1916  * \param nodeName the name of the node
1917  * \param code the python code to load
1918  * \return the PyScriptNode
1919  */
1920 //=============================================================================
1921 Engines::PyScriptNode_ptr Abstract_Engines_Container_i::createPyScriptNode(const char* nodeName, const char* code)
1922 {
1923   Engines::PyScriptNode_var node= Engines::PyScriptNode::_nil();
1924
1925   PyGILState_STATE gstate = PyGILState_Ensure();
1926   PyObject *res = PyObject_CallMethod(_pyCont,
1927     (char*)"create_pyscriptnode",
1928     (char*)"ss",
1929     nodeName,
1930     code);
1931   if(res==NULL)
1932   {
1933     //internal error
1934     PyErr_Print();
1935     PyGILState_Release(gstate);
1936     SALOME::ExceptionStruct es;
1937     es.type = SALOME::INTERNAL_ERROR;
1938     es.text = "can not create a python node";
1939     throw SALOME::SALOME_Exception(es);
1940   }
1941   long ierr=PyLong_AsLong(PyTuple_GetItem(res,0));
1942   PyObject* result=PyTuple_GetItem(res,1);
1943   std::string astr=PyUnicode_AsUTF8(result);
1944   Py_DECREF(res);
1945   PyGILState_Release(gstate);
1946
1947   if(ierr==0)
1948   {
1949     Utils_Locker lck(&_mutexForDftPy);
1950     CORBA::Object_var obj=_orb->string_to_object(astr.c_str());
1951     node=Engines::PyScriptNode::_narrow(obj);
1952     std::map<std::string,Engines::PyScriptNode_var>::iterator it(_dftPyScriptNode.find(nodeName));
1953     if(it==_dftPyScriptNode.end())
1954     {
1955       _dftPyScriptNode[nodeName]=node;
1956     }
1957     else
1958     {
1959       Engines::PyScriptNode_var oldNode((*it).second);
1960       if(!CORBA::is_nil(oldNode))
1961         oldNode->UnRegister();
1962       (*it).second=node;
1963     }
1964     return node._retn();
1965   }
1966   else
1967   {
1968     SALOME::ExceptionStruct es;
1969     es.type = SALOME::INTERNAL_ERROR;
1970     es.text = astr.c_str();
1971     throw SALOME::SALOME_Exception(es);
1972   }
1973 }
1974
1975 void Abstract_Engines_Container_i::removePyScriptNode(const char *nodeName)
1976 {
1977   std::map<std::string,Engines::PyScriptNode_var>::iterator it(_dftPyScriptNode.find(nodeName));
1978   if(it==_dftPyScriptNode.end())
1979     {
1980       std::ostringstream oss; oss << "Engines_Container_i::removePyScriptNode : node \"" << nodeName << "\" is not map !";
1981       SALOME::ExceptionStruct es;
1982       es.type = SALOME::INTERNAL_ERROR;
1983       es.text = oss.str().c_str();
1984       throw SALOME::SALOME_Exception(es);
1985     }
1986   (*it).second->UnRegister();
1987   _dftPyScriptNode.erase(it);
1988 }
1989
1990 void Abstract_Engines_Container_i::cleanAllPyScripts()
1991 {
1992   for(std::map<std::string,Engines::PyNode_var>::iterator it=_dftPyNode.begin();it!=_dftPyNode.end();it++)
1993     {
1994       Engines::PyNode_var tmpVar((*it).second);
1995       if(!CORBA::is_nil(tmpVar))
1996         tmpVar->UnRegister();
1997     }
1998   _dftPyNode.clear();
1999   for(std::map<std::string,Engines::PyScriptNode_var>::iterator it=_dftPyScriptNode.begin();it!=_dftPyScriptNode.end();it++)
2000     {
2001       Engines::PyScriptNode_var tmpVar((*it).second);
2002       if(!CORBA::is_nil(tmpVar))
2003         tmpVar->UnRegister();
2004     }
2005   _dftPyScriptNode.clear();
2006 }
2007
2008 //=============================================================================
2009 /*! \brief Retrieves the last created PyScriptNode instance with createPyScriptNode.
2010  *
2011  */
2012 //=============================================================================
2013 Engines::PyScriptNode_ptr Abstract_Engines_Container_i::getDefaultPyScriptNode(const char *nodeName)
2014 {
2015   Utils_Locker lck(&_mutexForDftPy);
2016   std::map<std::string,Engines::PyScriptNode_var>::iterator it(_dftPyScriptNode.find(nodeName));
2017   if(it==_dftPyScriptNode.end())
2018     return Engines::PyScriptNode::_nil();
2019   else
2020   {
2021     Engines::PyScriptNode_var tmpVar((*it).second);
2022     if(!CORBA::is_nil(tmpVar))
2023       return Engines::PyScriptNode::_duplicate(tmpVar);
2024     else
2025       return Engines::PyScriptNode::_nil();
2026   }
2027 }
2028
2029 //=============================================================================
2030 /* int checkifexecutable(const char *filename)
2031 *
2032 * Return non-zero if the name is an executable file, and
2033 * zero if it is not executable, or if it does not exist.
2034 */
2035 //=============================================================================
2036 int checkifexecutable(const std::string& filename)
2037 {
2038   int result;
2039   struct stat statinfo;
2040
2041   result = stat(filename.c_str(), &statinfo);
2042   if (result < 0) return 0;
2043   if (!S_ISREG(statinfo.st_mode)) return 0;
2044
2045 #ifdef WIN32
2046   return 1;
2047 #else
2048   if (statinfo.st_uid == geteuid()) return statinfo.st_mode & S_IXUSR;
2049   if (statinfo.st_gid == getegid()) return statinfo.st_mode & S_IXGRP;
2050   return statinfo.st_mode & S_IXOTH;
2051 #endif
2052 }
2053
2054
2055 //=============================================================================
2056 /*! \brief Find a file by searching in a path
2057  *  \param filename file name to search
2058  *  \param path path to search in
2059  *  \param pth the complete file path if found
2060  *  \return 1 if found 0 if not 
2061 */
2062 //=============================================================================
2063 int findpathof(const std::string& path, std::string& pth, const std::string& filename)
2064 {
2065   if ( path.size() == 0 ) return 0;
2066
2067   std::string::size_type offset = 0;
2068   std::string::size_type pos = 0;
2069   int found = 0;
2070   struct stat statinfo;
2071
2072   while(!found)
2073   {
2074     pos = path.find( SEP, offset );
2075     pth = path.substr( offset, pos - offset );
2076     if ( pth.size() > 0 )
2077     {
2078       if( pth[pth.size()-1] != SLASH ) pth += SLASH;
2079       pth += filename;
2080       int result=stat(pth.c_str(), &statinfo);
2081       if(result == 0) found=1;
2082     }
2083     if (pos == std::string::npos) break;
2084     offset = pos+1;
2085   }
2086   return found;
2087 }
2088
2089 void Abstract_Engines_Container_i::registerTemporaryFile( const std::string& fileName )
2090 {
2091   _tmp_files.remove( fileName );
2092   _tmp_files.push_back( fileName );
2093 }
2094
2095 void Abstract_Engines_Container_i::unregisterTemporaryFile( const std::string& fileName )
2096 {
2097   _tmp_files.remove( fileName );
2098 }
2099
2100 void Abstract_Engines_Container_i::clearTemporaryFiles()
2101 {
2102   std::list<std::string>::const_iterator it;
2103   for ( it = _tmp_files.begin(); it != _tmp_files.end(); ++it ) {
2104 #if defined(WIN32) && defined(UNICODE)
2105         std::wstring aFile = Kernel_Utils::utf8_decode_s(*it);
2106         std::wstring command = (GetFileAttributes(aFile.c_str()) == FILE_ATTRIBUTE_DIRECTORY) ? L"rd /Q \"" : L"del /F /Q \"";
2107         command += aFile;
2108         command += L"\" 2>NUL";
2109         _wsystem(command.c_str());
2110 #else
2111 #if defined(WIN32)
2112         std::string aFile = *it;
2113         std::string command = (GetFileAttributes(aFile.c_str()) == FILE_ATTRIBUTE_DIRECTORY) ? "rd /Q \"" : "del /F /Q \"";
2114         command += aFile;
2115         command += "\" 2>NUL";
2116 #else
2117         std::string command = "rm -rf ";
2118         command += *it;
2119 #endif
2120         system(command.c_str());
2121 #endif
2122   }
2123   _tmp_files.clear();
2124 }
2125
2126 static Engines_Container_SSL_i *_container_singleton_ssl = nullptr;
2127
2128 static Engines::Container_var _container_ref_singleton_ssl;
2129
2130 Engines_Container_SSL_i *KERNEL::getContainerSA()
2131 {
2132   if(!_container_singleton_ssl)
2133   {
2134     int argc(0);
2135     CORBA::ORB_var orb = CORBA::ORB_init(argc,nullptr);
2136     CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
2137     PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
2138     PortableServer::POAManager_var pman = poa->the_POAManager();
2139     CORBA::PolicyList policies;
2140     policies.length(0);
2141     //
2142     char *argv[4] = {"Container","FactoryServer","toto",nullptr};
2143     SALOME_Fake_NamingService ns;
2144     _container_singleton_ssl = new Engines_Container_SSL_i(orb,poa,"FactoryServer",2,argv,&ns,false);
2145     PortableServer::ObjectId * cont_id = _container_singleton_ssl->getCORBAId();
2146     //
2147     CORBA::Object_var zeRef = poa->id_to_reference(*cont_id);
2148     _container_ref_singleton_ssl = Engines::Container::_narrow(zeRef);
2149   }
2150   return _container_singleton_ssl;
2151 }
2152
2153 Engines::Container_var KERNEL::getContainerRefSA()
2154 {
2155   getContainerSA();
2156   return _container_ref_singleton_ssl;
2157 }