Back to index

salome-kernel  6.5.0
Container_i.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SALOME Container : implementation of container and engine for Kernel
00024 //  File   : Container_i.cxx
00025 //  Author : Paul RASCLE, EDF - MARC TAJCHMAN, CEA 
00026 //  Module : SALOME
00027 //  $Header: /home/server/cvs/KERNEL/KERNEL_SRC/src/Container/Container_i.cxx,v 1.22.2.7.14.8.2.1 2012-04-12 14:05:03 vsr Exp $
00028 //#define private public
00029 //
00030 #include <string.h>
00031 #include <stdio.h>
00032 #include <time.h>
00033 #include <sys/types.h>
00034 #ifndef WIN32
00035 #include <sys/time.h>
00036 #include <dlfcn.h>
00037 #include <unistd.h>
00038 #include <sys/wait.h>
00039 #else
00040 #include <signal.h>
00041 #include <process.h>
00042 #include <direct.h>
00043 int SIGUSR1 = 1000;
00044 #endif
00045 
00046 #include "utilities.h"
00047 #include <SALOMEconfig.h>
00048 #include CORBA_SERVER_HEADER(SALOME_Component)
00049 #include CORBA_SERVER_HEADER(SALOME_Exception)
00050 #include <pthread.h>  // must be before Python.h !
00051 #include "SALOME_Container_i.hxx"
00052 #include "SALOME_Component_i.hxx"
00053 #include "SALOME_FileRef_i.hxx"
00054 #include "SALOME_FileTransfer_i.hxx"
00055 #include "Salome_file_i.hxx"
00056 #include "SALOME_NamingService.hxx"
00057 #include "Basics_Utils.hxx"
00058 
00059 #ifdef _XOPEN_SOURCE
00060 #undef _XOPEN_SOURCE
00061 #endif
00062 
00063 #include <Python.h>
00064 #include "Container_init_python.hxx"
00065 
00066 bool _Sleeping = false ;
00067 
00068 // // Needed by multi-threaded Python --- Supervision
00069 int _ArgC ;
00070 char ** _ArgV ;
00071 
00072 extern "C" {void ActSigIntHandler() ; }
00073 #ifndef WIN32
00074 extern "C" {void SigIntHandler(int, siginfo_t *, void *) ; }
00075 #else
00076 extern "C" {void SigIntHandler( int ) ; }
00077 #endif
00078 
00079 #ifndef WIN32
00080 #define LIB "lib"
00081 #define ENGINESO "Engine.so"
00082 #else
00083 #define LIB ""
00084 #define ENGINESO "Engine.dll"
00085 #endif
00086 
00087 #ifdef WIN32
00088 #define SEP ';'
00089 #define SLASH '\\'
00090 #else
00091 #define SEP ':'
00092 #define SLASH '/'
00093 #endif
00094 
00095 std::map<std::string, int> Engines_Container_i::_cntInstances_map;
00096 std::map<std::string, void *> Engines_Container_i::_library_map;
00097 std::map<std::string, void *> Engines_Container_i::_toRemove_map;
00098 omni_mutex Engines_Container_i::_numInstanceMutex ;
00099 
00100 static PyObject* _pyCont;
00101 
00102 int checkifexecutable(const std::string&);
00103 int findpathof(const std::string& path, std::string&, const std::string&);
00104 
00111 //=============================================================================
00115 //=============================================================================
00116 
00117 Engines_Container_i::Engines_Container_i () :
00118 _numInstance(0),_id(0),_NS(0)
00119 {
00120 }
00121 
00122 //=============================================================================
00126 //=============================================================================
00127 
00128 Engines_Container_i::Engines_Container_i (CORBA::ORB_ptr orb, 
00129                                           PortableServer::POA_ptr poa,
00130                                           char *containerName ,
00131                                           int argc , char* argv[],
00132                                           bool activAndRegist,
00133                                           bool isServantAloneInProcess
00134                                           ) :
00135   _numInstance(0),_isServantAloneInProcess(isServantAloneInProcess),_id(0),_NS(0)
00136 {
00137   _pid = (long)getpid();
00138 
00139   if(activAndRegist)
00140     ActSigIntHandler() ;
00141 
00142   _argc = argc ;
00143   _argv = argv ;
00144 
00145   std::string hostname = Kernel_Utils::GetHostname();
00146 #ifndef WIN32
00147   MESSAGE(hostname << " " << getpid() << 
00148     " Engines_Container_i starting argc " <<
00149     _argc << " Thread " << pthread_self() ) ;
00150 #else
00151   MESSAGE(hostname << " " << _getpid() << 
00152     " Engines_Container_i starting argc " << _argc<< " Thread " << pthread_self().p ) ;
00153 #endif
00154 
00155   int i = 0 ;
00156   while ( _argv[ i ] )
00157   {
00158     MESSAGE("           argv" << i << " " << _argv[ i ]) ;
00159     i++ ;
00160   }
00161 
00162   if ( argc < 2 )
00163   {
00164     INFOS("SALOME_Container usage : SALOME_Container ServerName");
00165     ASSERT(0) ;
00166   }
00167   SCRUTE(argv[1]);
00168   _isSupervContainer = false;
00169 
00170   _orb = CORBA::ORB::_duplicate(orb) ;
00171   _poa = PortableServer::POA::_duplicate(poa) ;
00172 
00173   // Pour les containers paralleles: il ne faut pas enregistrer et activer
00174   // le container generique, mais le container specialise
00175 
00176   if(activAndRegist)
00177   {
00178     _id = _poa->activate_object(this);
00179     _NS = new SALOME_NamingService();
00180     _NS->init_orb( _orb ) ;
00181     CORBA::Object_var obj=_poa->id_to_reference(*_id);
00182     Engines::Container_var pCont 
00183       = Engines::Container::_narrow(obj);
00184     _remove_ref();
00185 
00186     _containerName = _NS->BuildContainerNameForNS(containerName,
00187       hostname.c_str());
00188     SCRUTE(_containerName);
00189     _NS->Register(pCont, _containerName.c_str());
00190     MESSAGE("Engines_Container_i::Engines_Container_i : Container name "
00191       << _containerName);
00192 
00193     // Python: 
00194     // import SALOME_Container
00195     // pycont = SALOME_Container.SALOME_Container_i(containerIORStr)
00196 
00197     CORBA::String_var sior =  _orb->object_to_string(pCont);
00198     std::string myCommand="pyCont = SALOME_Container.SALOME_Container_i('";
00199     myCommand += _containerName + "','";
00200     myCommand += sior;
00201     myCommand += "')\n";
00202     SCRUTE(myCommand);
00203 
00204     PyGILState_STATE gstate = PyGILState_Ensure();
00205 
00206 #ifdef WIN32
00207     // mpv: this is temporary solution: there is a unregular crash if not
00208     //Sleep(2000);
00209     //
00210     // first element is the path to Registry.dll, but it's wrong
00211     PyRun_SimpleString("import sys\n");
00212     PyRun_SimpleString("sys.path = sys.path[1:]\n");
00213 #endif
00214     PyRun_SimpleString("import SALOME_Container\n");
00215     PyRun_SimpleString((char*)myCommand.c_str());
00216     PyObject *mainmod = PyImport_AddModule("__main__");
00217     PyObject *globals = PyModule_GetDict(mainmod);
00218     _pyCont = PyDict_GetItemString(globals, "pyCont");
00219 
00220     PyGILState_Release(gstate);
00221 
00222     fileTransfer_i* aFileTransfer = new fileTransfer_i();
00223     CORBA::Object_var obref=aFileTransfer->_this();
00224     _fileTransfer = Engines::fileTransfer::_narrow(obref);
00225     aFileTransfer->_remove_ref();
00226   }
00227 }
00228 
00229 //=============================================================================
00233 //=============================================================================
00234 
00235 Engines_Container_i::~Engines_Container_i()
00236 {
00237   MESSAGE("Container_i::~Container_i()");
00238   if(_id)
00239     delete _id;
00240   if(_NS)
00241     delete _NS;
00242 }
00243 
00244 //=============================================================================
00246 
00249 //=============================================================================
00250 
00251 char* Engines_Container_i::name()
00252 {
00253   return CORBA::string_dup(_containerName.c_str()) ;
00254 }
00255 
00256 //=============================================================================
00258 
00261 //=============================================================================
00262 
00263 char* Engines_Container_i::workingdir()
00264 {
00265   char wd[256];
00266   getcwd (wd,256);
00267   return CORBA::string_dup(wd) ;
00268 }
00269 
00270 //=============================================================================
00272 
00275 //=============================================================================
00276 
00277 char* Engines_Container_i::logfilename()
00278 {
00279   return CORBA::string_dup(_logfilename.c_str()) ;
00280 }
00281 
00283 void Engines_Container_i::logfilename(const char* name)
00284 {
00285   _logfilename=name;
00286 }
00287 
00288 //=============================================================================
00290 
00293 //=============================================================================
00294 
00295 char* Engines_Container_i::getHostName()
00296 {
00297   std::string s = Kernel_Utils::GetHostname();
00298   //  MESSAGE("Engines_Container_i::getHostName " << s);
00299   return CORBA::string_dup(s.c_str()) ;
00300 }
00301 
00302 //=============================================================================
00304 
00307 //=============================================================================
00308 
00309 CORBA::Long Engines_Container_i::getPID()
00310 {
00311   return (CORBA::Long)getpid();
00312 }
00313 
00314 //=============================================================================
00316 
00319 //=============================================================================
00320 void Engines_Container_i::ping()
00321 {
00322   MESSAGE("Engines_Container_i::ping() pid "<< getpid());
00323 }
00324 
00325 //=============================================================================
00327 
00333 //=============================================================================
00334 void Engines_Container_i::Shutdown()
00335 {
00336   MESSAGE("Engines_Container_i::Shutdown()");
00337 
00338   // Clear registered temporary files
00339   clearTemporaryFiles();
00340 
00341   /* For each component contained in this container
00342   * tell it to self-destroy
00343   */
00344   std::map<std::string, Engines::EngineComponent_var>::iterator itm;
00345   for (itm = _listInstances_map.begin(); itm != _listInstances_map.end(); itm++)
00346     {
00347       try
00348         {
00349           itm->second->destroy();
00350         }
00351       catch(const CORBA::Exception& e)
00352         {
00353           // ignore this entry and continue
00354         }
00355       catch(...)
00356         {
00357           // ignore this entry and continue
00358         }
00359     }
00360   _listInstances_map.clear();
00361 
00362   _NS->Destroy_FullDirectory(_containerName.c_str());
00363   _NS->Destroy_Name(_containerName.c_str());
00364   if(_isServantAloneInProcess)
00365   {
00366     MESSAGE("Effective Shutdown of container Begins...");
00367     if(!CORBA::is_nil(_orb))
00368       _orb->shutdown(0);
00369   }
00370 }
00371 
00372 //=============================================================================
00374 
00380 //=============================================================================
00381 bool
00382 Engines_Container_i::load_component_Library(const char* componentName, CORBA::String_out reason)
00383 {
00384 
00385   //=================================================================
00386   // --- C++ implementation section 
00387   //=================================================================
00388   std::string retso;
00389   if(load_component_CppImplementation(componentName,retso))
00390     {
00391       reason=CORBA::string_dup("");
00392       return true;
00393     }
00394   else if(retso != "ImplementationNotFound")
00395     {
00396       reason=CORBA::string_dup(retso.c_str());
00397       return false;
00398     }
00399 
00400   retso="Component ";
00401   retso+=componentName;
00402   retso+=": Can't find C++ implementation ";
00403   retso+=std::string(LIB) + componentName + ENGINESO;
00404 
00405   //=================================================================
00406   // --- Python implementation section 
00407   //=================================================================
00408   std::string retpy;
00409   if(load_component_PythonImplementation(componentName,retpy))
00410     {
00411       reason=CORBA::string_dup("");
00412       return true;
00413     }
00414   else if(retpy != "ImplementationNotFound")
00415     {
00416       reason=CORBA::string_dup(retpy.c_str());
00417       return false;
00418     }
00419   
00420   retpy="Component ";
00421   retpy+=componentName;
00422   retpy+=": Can't find python implementation ";
00423   retpy+=componentName;
00424   retpy+="(.py)";
00425 
00426   //=================================================================
00427   // -- Executable implementation section
00428   //=================================================================
00429   std::string retex;
00430   if(load_component_ExecutableImplementation(componentName,retex))
00431     {
00432       reason=CORBA::string_dup("");
00433       return true;
00434     }
00435   else if(retex != "ImplementationNotFound")
00436     {
00437       reason=CORBA::string_dup(retex.c_str());
00438       return false;
00439     }
00440 
00441   retex="Component ";
00442   retex+=componentName;
00443   retex+=": Can't find executable implementation ";
00444   retex+=componentName;
00445   retex+=".exe";
00446 
00447   std::string ret="Component implementation not found: ";
00448   ret += componentName ;
00449   ret += '\n' ;
00450   ret += retso+ '\n' ;
00451   ret += retpy+ '\n' ;
00452   ret += retex+ '\n' ;
00453 
00454   std::cerr << ret << std::endl;
00455   reason=CORBA::string_dup(ret.c_str());
00456 
00457   return false;
00458 }
00459 
00460 //=============================================================================
00462 
00468 //=============================================================================
00469 bool
00470 Engines_Container_i::load_component_CppImplementation(const char* componentName, std::string& reason)
00471 {
00472   std::string aCompName(componentName);
00473   std::string impl_name = std::string(LIB) + aCompName + ENGINESO;
00474   SCRUTE(impl_name);
00475 
00476   _numInstanceMutex.lock(); // lock to be alone
00477   // (see decInstanceCnt, finalize_removal))
00478   if (_toRemove_map.count(impl_name) != 0) _toRemove_map.erase(impl_name);
00479   if (_library_map.count(impl_name) != 0)
00480     {
00481       MESSAGE("Library " << impl_name << " already loaded");
00482       _numInstanceMutex.unlock();
00483       reason="";
00484       return true;
00485     }
00486   _numInstanceMutex.unlock();
00487 
00488 #ifndef WIN32
00489   void* handle;
00490   handle = dlopen( impl_name.c_str() , RTLD_NOW ) ;
00491   if ( !handle )
00492     {
00493       //not loadable. Try to find the lib file in LD_LIBRARY_PATH
00494       std::string path;
00495       char* p=getenv("LD_LIBRARY_PATH");
00496       if(p)path=p;
00497       path=path+SEP+"/usr/lib"+SEP+"/lib";
00498 
00499       std::string pth;
00500       if(findpathof(path, pth, impl_name))
00501         {
00502           //found but not loadable
00503           reason="Component ";
00504           reason+=aCompName;
00505           reason+=": C++ implementation found ";
00506           reason+=pth;
00507           reason+=" but it is not loadable. Error:\n";
00508           reason+=dlerror();
00509           std::cerr << reason << std::endl;
00510           return false;
00511         }
00512       else
00513         {
00514           //not found
00515           //continue with other implementation
00516           reason="ImplementationNotFound";
00517           return false;
00518         }
00519     }
00520 #else
00521   HINSTANCE handle;
00522   handle = LoadLibrary( impl_name.c_str() );
00523   if ( !handle )
00524     {
00525       reason="ImplementationNotFound";
00526     }
00527 #endif
00528 
00529   if ( handle )
00530     {
00531       _numInstanceMutex.lock();
00532       _library_map[impl_name] = handle;
00533       _numInstanceMutex.unlock();
00534       reason="";
00535       return true;
00536     }
00537 
00538   return false;
00539 
00540 }
00541 //=============================================================================
00543 
00549 //=============================================================================
00550 bool
00551 Engines_Container_i::load_component_PythonImplementation(const char* componentName, std::string& reason)
00552 {
00553   std::string aCompName(componentName);
00554 
00555   _numInstanceMutex.lock() ; // lock to be alone (stl container write)
00556   if (_library_map.count(aCompName) != 0)
00557     {
00558       _numInstanceMutex.unlock() ;
00559       reason="";
00560       return true; // Python Component, already imported
00561     }
00562   _numInstanceMutex.unlock() ;
00563 
00564   PyGILState_STATE gstate = PyGILState_Ensure();
00565   PyObject *result = PyObject_CallMethod(_pyCont,
00566                                          (char*)"import_component",
00567                                          (char*)"s",componentName);
00568 
00569   reason=PyString_AsString(result);
00570   Py_XDECREF(result);
00571   SCRUTE(reason);
00572   PyGILState_Release(gstate);
00573 
00574   if (reason=="")
00575     {
00576       //Python component has been loaded (import componentName)
00577       _numInstanceMutex.lock() ; // lock to be alone (stl container write)
00578       _library_map[aCompName] = (void *)_pyCont; // any non O value OK
00579       _numInstanceMutex.unlock() ;
00580       MESSAGE("import Python: "<< aCompName <<" OK");
00581       return true;
00582     }
00583   else if(reason=="ImplementationNotFound")
00584     {
00585       //Python implementation has not been found. Continue with other implementation
00586       reason="ImplementationNotFound";
00587     }
00588   else
00589     {
00590       //Python implementation has been found but loading has failed
00591       std::cerr << reason << std::endl;
00592     }
00593   return false;
00594 
00595 }
00596 //=============================================================================
00598 
00604 //=============================================================================
00605 bool
00606 Engines_Container_i::load_component_ExecutableImplementation(const char* componentName, std::string& reason)
00607 {
00608   std::string aCompName(componentName);
00609   std::string executable=aCompName+".exe";
00610 
00611   std::string path;
00612   std::string pth;
00613 
00614   char* p=getenv("PATH");
00615   if(p)path=p;
00616 
00617   if (findpathof(path, pth, executable))
00618     {
00619       if(checkifexecutable(pth))
00620         {
00621           _numInstanceMutex.lock() ; // lock to be alone (stl container write)
00622           _library_map[executable] = (void *)1; // any non O value OK
00623           _numInstanceMutex.unlock() ;
00624           MESSAGE("import executable: "<< pth <<" OK");
00625           reason="";
00626           return true;
00627         }
00628       reason="Component ";
00629       reason+=aCompName;
00630       reason+=": implementation found ";
00631       reason+=pth;
00632       reason+=" but it is not executable";
00633       std::cerr << reason << std::endl;
00634     }
00635   else
00636     {
00637       reason="ImplementationNotFound";
00638     }
00639   return false;
00640 }
00641 
00642 //=============================================================================
00644 
00653 //=============================================================================
00654 Engines::EngineComponent_ptr
00655 Engines_Container_i::create_component_instance(const char*genericRegisterName,
00656                                                CORBA::Long studyId)
00657 {
00658   Engines::FieldsDict_var env = new Engines::FieldsDict;
00659   char* reason;
00660   Engines::EngineComponent_ptr compo =
00661     create_component_instance_env(genericRegisterName, studyId, env, reason);
00662   CORBA::string_free(reason);
00663   return compo;
00664 }
00665 
00666 //=============================================================================
00668 
00679 //=============================================================================
00680 Engines::EngineComponent_ptr
00681 Engines_Container_i::create_component_instance_env(const char*genericRegisterName,
00682                                                    CORBA::Long studyId,
00683                                                    const Engines::FieldsDict& env,
00684                                                    CORBA::String_out reason)
00685 {
00686   if (studyId < 0)
00687     {
00688       INFOS("studyId must be > 0 for mono study instance, =0 for multiStudy");
00689       reason=CORBA::string_dup("studyId must be > 0 for mono study instance, =0 for multiStudy");
00690       return Engines::EngineComponent::_nil() ;
00691     }
00692 
00693   std::string error;
00694   if (_library_map.count(genericRegisterName) != 0)
00695     {
00696       // It's a Python component
00697       Engines::EngineComponent_ptr compo = createPythonInstance(genericRegisterName, studyId, error);
00698       reason=CORBA::string_dup(error.c_str());
00699       return compo;
00700     }
00701 
00702   std::string impl_name = std::string(LIB) + genericRegisterName + ENGINESO;
00703   if (_library_map.count(impl_name) != 0)
00704     {
00705       // It's a C++ component
00706       void* handle = _library_map[impl_name];
00707       Engines::EngineComponent_ptr compo = createInstance(genericRegisterName, handle, studyId, error);
00708       reason=CORBA::string_dup(error.c_str());
00709       return compo;
00710     }
00711 
00712   impl_name = std::string(genericRegisterName) + ".exe";
00713   if (_library_map.count(impl_name) != 0)
00714     {
00715       //It's an executable component
00716       Engines::EngineComponent_ptr compo = createExecutableInstance(genericRegisterName, studyId, env, error);
00717       reason=CORBA::string_dup(error.c_str());
00718       return compo;
00719     }
00720 
00721   error="load_component_Library has probably not been called for component: ";
00722   error += genericRegisterName;
00723   INFOS(error);
00724   reason=CORBA::string_dup(error.c_str());
00725   return Engines::EngineComponent::_nil() ;
00726 }
00727 
00728 //=============================================================================
00730 
00742 //=============================================================================
00743 Engines::EngineComponent_ptr
00744 Engines_Container_i::createExecutableInstance(std::string CompName, int studyId,
00745                                               const Engines::FieldsDict& env,
00746                                               std::string& reason)
00747 {
00748   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
00749 
00750   _numInstanceMutex.lock() ; // lock on the instance number
00751   _numInstance++ ;
00752   int numInstance = _numInstance ;
00753   _numInstanceMutex.unlock() ;
00754 
00755   char aNumI[12];
00756   sprintf( aNumI , "%d" , numInstance ) ;
00757   std::string instanceName = CompName + "_inst_" + aNumI ;
00758   std::string component_registerName = _containerName + "/" + instanceName;
00759 
00760   //check if an entry exist in naming service
00761   CORBA::Object_var nsobj = _NS->Resolve(component_registerName.c_str());
00762   if ( !CORBA::is_nil(nsobj) )
00763   {
00764     // unregister the registered component
00765     _NS->Destroy_Name(component_registerName.c_str());
00766     //kill or shutdown it ???
00767   }
00768 
00769   // first arg container ior string
00770   // second arg container name
00771   // third arg instance name
00772 
00773   Engines::Container_var pCont= _this();
00774   CORBA::String_var sior =  _orb->object_to_string(pCont);
00775 
00776   std::string command;
00777   command="mkdir -p ";
00778   command+=instanceName;
00779   command+=";cd ";
00780   command+=instanceName;
00781   command+=";";
00782   command+=CompName ;
00783   command+=".exe";
00784   command+=" ";
00785   command+= sior; // container ior string
00786   command+=" ";
00787   command+=_containerName; //container name
00788   command+=" ";
00789   command+=instanceName; //instance name
00790   command+=" &";
00791   MESSAGE("SALOME_Container::create_component_instance command=" << command);
00792 
00793 #ifndef WIN32
00794   // use fork/execl instead of system to get finer control on env variables
00795   int status;
00796   pid_t pid = fork();
00797   if(pid == 0) // child
00798     {
00799       for (CORBA::ULong i=0; i < env.length(); i++)
00800         {
00801           if (env[i].value.type()->kind() == CORBA::tk_string)
00802             {
00803               const char* value;
00804               env[i].value >>= value;
00805               std::string s(env[i].key);
00806               s+='=';
00807               s+=value;
00808               putenv(strdup(s.c_str()));
00809             }
00810         }
00811 
00812       execl("/bin/sh", "sh", "-c", command.c_str() , (char *)0);
00813       status=-1;
00814     }
00815   else if(pid < 0)       // failed to fork
00816     {
00817       status=-1;
00818     }
00819   else            //parent
00820     {
00821       pid_t tpid;
00822       do
00823         {
00824           tpid = wait(&status);
00825         } while (tpid != pid);
00826     }
00827 #else
00828   // launch component with a system call
00829   int status=system(command.c_str());
00830 #endif
00831 
00832   if (status == -1)
00833   {
00834     reason="SALOME_Container::create_component_instance system failed (system command status -1)";
00835     MESSAGE(reason);
00836     return Engines::EngineComponent::_nil();
00837   }
00838 #ifndef WIN32
00839   else if (WEXITSTATUS(status) == 217)
00840   {
00841     reason="SALOME_Container::create_component_instance system failed (system command status 217)";
00842     MESSAGE(reason);
00843     return Engines::EngineComponent::_nil();
00844   }
00845 #endif
00846   else
00847   {
00848     int count=20;
00849     if (getenv("TIMEOUT_TO_WAIT_EXE_COMPONENT") != 0)
00850     {
00851       std::string new_count_str = getenv("TIMEOUT_TO_WAIT_EXE_COMPONENT");
00852       int new_count;
00853       std::istringstream ss(new_count_str);
00854       if (!(ss >> new_count))
00855       {
00856         INFOS("[Container] TIMEOUT_TO_WAIT_EXE_COMPONENT should be an int");
00857       }
00858       else
00859         count = new_count;
00860     }
00861     INFOS("[Container] waiting " << count << " second steps exe component ");
00862     CORBA::Object_var obj = CORBA::Object::_nil() ;
00863     while ( CORBA::is_nil(obj) && count )
00864     {
00865 #ifndef WIN32
00866       sleep( 1 ) ;
00867 #else
00868       Sleep(1000);
00869 #endif
00870       count-- ;
00871       MESSAGE( count << ". Waiting for component " << CompName);
00872       obj = _NS->Resolve(component_registerName.c_str());
00873     }
00874 
00875     if(CORBA::is_nil(obj))
00876     {
00877       reason="SALOME_Container::create_component_instance failed";
00878       MESSAGE(reason);
00879       return Engines::EngineComponent::_nil();
00880     }
00881     else
00882     {
00883       MESSAGE("SALOME_Container::create_component_instance successful");
00884       iobject = Engines::EngineComponent::_narrow(obj);
00885       _listInstances_map[instanceName] = iobject;
00886       return iobject._retn();
00887     }
00888   }
00889 }
00890 
00891 
00892 //=============================================================================
00894 
00901 //=============================================================================
00902 Engines::EngineComponent_ptr
00903 Engines_Container_i::createPythonInstance(std::string CompName, int studyId,
00904                                           std::string& reason)
00905 {
00906   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
00907 
00908   _numInstanceMutex.lock() ; // lock on the instance number
00909   _numInstance++ ;
00910   int numInstance = _numInstance ;
00911   _numInstanceMutex.unlock() ;
00912 
00913   char aNumI[12];
00914   sprintf( aNumI , "%d" , numInstance ) ;
00915   std::string instanceName = CompName + "_inst_" + aNumI ;
00916   std::string component_registerName = _containerName + "/" + instanceName;
00917 
00918   PyGILState_STATE gstate = PyGILState_Ensure();
00919   PyObject *result = PyObject_CallMethod(_pyCont,
00920                                          (char*)"create_component_instance",
00921                                          (char*)"ssl",
00922                                          CompName.c_str(),
00923                                          instanceName.c_str(),
00924                                          studyId);
00925   const char *ior;
00926   const char *error;
00927   PyArg_ParseTuple(result,"ss", &ior, &error);
00928   std::string iors = ior;
00929   reason=error;
00930   Py_DECREF(result);
00931   PyGILState_Release(gstate);
00932 
00933   if( iors!="" )
00934     {
00935       CORBA::Object_var obj = _orb->string_to_object(iors.c_str());
00936       iobject = Engines::EngineComponent::_narrow( obj ) ;
00937       _listInstances_map[instanceName] = iobject;
00938     }
00939   return iobject._retn();
00940 }
00941 
00942 //=============================================================================
00944 
00963 //=============================================================================
00964 Engines::EngineComponent_ptr
00965 Engines_Container_i::createInstance(std::string genericRegisterName,
00966                                     void *handle,
00967                                     int studyId,
00968                                     std::string& reason)
00969 {
00970   // --- find the factory
00971 
00972   std::string aGenRegisterName = genericRegisterName;
00973   std::string factory_name = aGenRegisterName + std::string("Engine_factory");
00974   SCRUTE(factory_name) ;
00975 
00976   typedef PortableServer::ObjectId* (*FACTORY_FUNCTION) (CORBA::ORB_ptr,
00977                                                          PortableServer::POA_ptr, 
00978                                                          PortableServer::ObjectId *, 
00979                                                          const char *, 
00980                                                          const char *) ;
00981 
00982 #ifndef WIN32
00983   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)dlsym( handle, factory_name.c_str() );
00984 #else
00985   FACTORY_FUNCTION Component_factory = (FACTORY_FUNCTION)GetProcAddress( (HINSTANCE)handle, factory_name.c_str() );
00986 #endif
00987 
00988   if ( !Component_factory )
00989   {
00990     INFOS( "Can't resolve symbol: " + factory_name );
00991 #ifndef WIN32
00992     reason=dlerror();
00993     INFOS(reason);
00994 #endif
00995     return Engines::EngineComponent::_nil() ;
00996   }
00997 
00998   // --- create instance
00999 
01000   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
01001 
01002   try
01003   {
01004     _numInstanceMutex.lock() ; // lock on the instance number
01005     _numInstance++ ;
01006     int numInstance = _numInstance ;
01007     _numInstanceMutex.unlock() ;
01008 
01009     char aNumI[12];
01010     sprintf( aNumI , "%d" , numInstance ) ;
01011     std::string instanceName = aGenRegisterName + "_inst_" + aNumI ;
01012     std::string component_registerName =
01013       _containerName + "/" + instanceName;
01014 
01015     // --- Instanciate required CORBA object
01016 
01017     PortableServer::ObjectId *id ; //not owner, do not delete (nore use var)
01018     id = (Component_factory) ( _orb, _poa, _id, instanceName.c_str(),
01019                                                 aGenRegisterName.c_str() ) ;
01020     if (id == NULL)
01021       {
01022         reason="Can't get ObjectId from factory";
01023         INFOS(reason);
01024         return iobject._retn();
01025       }
01026 
01027     // --- get reference & servant from id
01028 
01029     CORBA::Object_var obj = _poa->id_to_reference(*id);
01030     iobject = Engines::EngineComponent::_narrow( obj ) ;
01031 
01032     Engines_Component_i *servant =
01033       dynamic_cast<Engines_Component_i*>(_poa->reference_to_servant(iobject));
01034     ASSERT(servant);
01035     //SCRUTE(servant->_refcount_value());
01036     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
01037     _listInstances_map[instanceName] = iobject;
01038     _cntInstances_map[aGenRegisterName] += 1;
01039     _numInstanceMutex.unlock() ;
01040     SCRUTE(aGenRegisterName);
01041     SCRUTE(_cntInstances_map[aGenRegisterName]);
01042     servant->setStudyId(studyId);
01043     servant->_remove_ref(); // do not need servant any more (remove ref from reference_to_servant)
01044     //SCRUTE(servant->_refcount_value());
01045 
01046     // --- register the engine under the name
01047     //     containerName(.dir)/instanceName(.object)
01048 
01049     _NS->Register( iobject , component_registerName.c_str() ) ;
01050     MESSAGE( component_registerName.c_str() << " bound" ) ;
01051   }
01052   catch (...)
01053   {
01054     reason="Container_i::createInstance exception catched";
01055     INFOS(reason) ;
01056   }
01057   return iobject._retn();
01058 }
01059 
01060 //=============================================================================
01062 
01070 //=============================================================================
01071 Engines::EngineComponent_ptr
01072 Engines_Container_i::find_component_instance( const char* registeredName,
01073                                               CORBA::Long studyId)
01074 {
01075   Engines::EngineComponent_var anEngine = Engines::EngineComponent::_nil();
01076   std::map<std::string,Engines::EngineComponent_var>::iterator itm =_listInstances_map.begin();
01077   while (itm != _listInstances_map.end())
01078   {
01079     std::string instance = (*itm).first;
01080     SCRUTE(instance);
01081     if (instance.find(registeredName) == 0)
01082     {
01083       anEngine = (*itm).second;
01084       if (studyId == anEngine->getStudyId())
01085       {
01086         return anEngine._retn();
01087       }
01088     }
01089     itm++;
01090   }
01091   return anEngine._retn();
01092 }
01093 
01094 //=============================================================================
01096 
01100 //=============================================================================
01101 
01102 void Engines_Container_i::remove_impl(Engines::EngineComponent_ptr component_i)
01103 {
01104   ASSERT(! CORBA::is_nil(component_i));
01105   std::string instanceName = component_i->instanceName() ;
01106   MESSAGE("unload component " << instanceName);
01107   _numInstanceMutex.lock() ; // lock to be alone (stl container write)
01108   _listInstances_map.erase(instanceName);
01109   _numInstanceMutex.unlock() ;
01110   component_i->destroy() ;
01111   _NS->Destroy_Name(instanceName.c_str());
01112 }
01113 
01114 //=============================================================================
01116 
01119 //=============================================================================
01120 void Engines_Container_i::finalize_removal()
01121 {
01122   MESSAGE("finalize unload : dlclose");
01123   _numInstanceMutex.lock(); // lock to be alone
01124   // (see decInstanceCnt, load_component_Library)
01125   std::map<std::string, void *>::iterator ith;
01126   for (ith = _toRemove_map.begin(); ith != _toRemove_map.end(); ith++)
01127   {
01128     void *handle = (*ith).second;
01129     std::string impl_name= (*ith).first;
01130     if (handle)
01131     {
01132       SCRUTE(handle);
01133       SCRUTE(impl_name);
01134       //        dlclose(handle);                // SALOME unstable after ...
01135       //        _library_map.erase(impl_name);
01136     }
01137   }
01138   _toRemove_map.clear();
01139   _numInstanceMutex.unlock();
01140 }
01141 
01142 //=============================================================================
01144 
01147 //=============================================================================
01148 void Engines_Container_i::decInstanceCnt(std::string genericRegisterName)
01149 {
01150   if(_cntInstances_map.count(genericRegisterName)==0)
01151     return;
01152   std::string aGenRegisterName =genericRegisterName;
01153   MESSAGE("Engines_Container_i::decInstanceCnt " << aGenRegisterName);
01154   ASSERT(_cntInstances_map[aGenRegisterName] > 0);
01155   _numInstanceMutex.lock(); // lock to be alone
01156   // (see finalize_removal, load_component_Library)
01157   _cntInstances_map[aGenRegisterName] -= 1;
01158   SCRUTE(_cntInstances_map[aGenRegisterName]);
01159   if (_cntInstances_map[aGenRegisterName] == 0)
01160   {
01161     std::string impl_name =
01162       Engines_Component_i::GetDynLibraryName(aGenRegisterName.c_str());
01163     SCRUTE(impl_name);
01164     void* handle = _library_map[impl_name];
01165     ASSERT(handle);
01166     _toRemove_map[impl_name] = handle;
01167   }
01168   _numInstanceMutex.unlock();
01169 }
01170 
01171 //=============================================================================
01173 
01187 //=============================================================================
01188 
01189 Engines::EngineComponent_ptr
01190 Engines_Container_i::load_impl( const char* genericRegisterName,
01191                                 const char* componentName )
01192 {
01193   char* reason;
01194   std::string impl_name = std::string(LIB) + genericRegisterName + ENGINESO;
01195   Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
01196   if (load_component_Library(genericRegisterName,reason))
01197     iobject = find_or_create_instance(genericRegisterName, impl_name);
01198   CORBA::string_free(reason);
01199   return iobject._retn();
01200 }
01201 
01202 //=============================================================================
01204 
01223 //=============================================================================
01224 
01225 Engines::EngineComponent_ptr
01226 Engines_Container_i::find_or_create_instance(std::string genericRegisterName,
01227                                              std::string componentLibraryName)
01228 {
01229   std::string aGenRegisterName = genericRegisterName;
01230   std::string impl_name = componentLibraryName;
01231   if (_library_map.count(impl_name) == 0)
01232   {
01233     INFOS("shared library " << impl_name <<" must be loaded before creating instance");
01234     return Engines::EngineComponent::_nil() ;
01235   }
01236   else
01237   {
01238     // --- find a registered instance in naming service, or create
01239 
01240     void* handle = _library_map[impl_name];
01241     std::string component_registerBase =
01242       _containerName + "/" + aGenRegisterName;
01243     Engines::EngineComponent_var iobject = Engines::EngineComponent::_nil() ;
01244     std::string reason;
01245     try
01246     {
01247       CORBA::Object_var obj =
01248         _NS->ResolveFirst( component_registerBase.c_str());
01249       if ( CORBA::is_nil( obj ) )
01250       {
01251         iobject = createInstance(genericRegisterName,
01252                                  handle,
01253                                  0,
01254                                  reason); // force multiStudy instance here !
01255       }
01256       else
01257       {
01258         iobject = Engines::EngineComponent::_narrow( obj ) ;
01259         Engines_Component_i *servant =
01260           dynamic_cast<Engines_Component_i*>
01261           (_poa->reference_to_servant(iobject));
01262         ASSERT(servant)
01263           int studyId = servant->getStudyId();
01264         ASSERT (studyId >= 0);
01265         if (studyId == 0) // multiStudy instance, OK
01266         {
01267           // No ReBind !
01268           MESSAGE(component_registerBase.c_str()<<" already bound");
01269         }
01270         else // monoStudy instance: NOK
01271         {
01272           iobject = Engines::EngineComponent::_nil();
01273           INFOS("load_impl & find_component_instance methods "
01274             << "NOT SUITABLE for mono study components");
01275         }
01276       }
01277     }
01278     catch (...)
01279     {
01280       INFOS( "Container_i::load_impl catched" ) ;
01281     }
01282     return iobject._retn();
01283   }
01284 }
01285 
01286 //=============================================================================
01288 
01291 //=============================================================================
01292 bool Engines_Container_i::isPythonContainer(const char* ContainerName)
01293 {
01294   bool ret=false;
01295   int len=strlen(ContainerName);
01296   if(len>=2)
01297     if(strcmp(ContainerName+len-2,"Py")==0)
01298       ret=true;
01299   return ret;
01300 }
01301 
01302 //=============================================================================
01304 
01308 //=============================================================================
01309 bool Engines_Container_i::Kill_impl()
01310 {
01311   MESSAGE("Engines_Container_i::Kill() pid "<< getpid() << " containerName "
01312     << _containerName.c_str() << " machineName "
01313     << Kernel_Utils::GetHostname().c_str());
01314   INFOS("===============================================================");
01315   INFOS("= REMOVE calls to Kill_impl in C++ container                  =");
01316   INFOS("===============================================================");
01317   //_exit( 0 ) ;
01318   ASSERT(0);
01319   return false;
01320 }
01321 
01322 //=============================================================================
01326 //=============================================================================
01327 void ActSigIntHandler()
01328 {
01329 #ifndef WIN32
01330   struct sigaction SigIntAct ;
01331   SigIntAct.sa_sigaction = &SigIntHandler ;
01332   sigemptyset(&SigIntAct.sa_mask);
01333   SigIntAct.sa_flags = SA_SIGINFO ;
01334 #endif
01335 
01336   // DEBUG 03.02.2005 : the first parameter of sigaction is not a mask of signals
01337   // (SIGINT | SIGUSR1) :
01338   // it must be only one signal ===> one call for SIGINT 
01339   // and an other one for SIGUSR1
01340 
01341 #ifndef WIN32
01342   if ( sigaction( SIGINT , &SigIntAct, NULL ) ) 
01343   {
01344     perror("SALOME_Container main ") ;
01345     exit(0) ;
01346   }
01347   if ( sigaction( SIGUSR1 , &SigIntAct, NULL ) )
01348   {
01349     perror("SALOME_Container main ") ;
01350     exit(0) ;
01351   }
01352   if ( sigaction( SIGUSR2 , &SigIntAct, NULL ) )
01353   {
01354     perror("SALOME_Container main ") ;
01355     exit(0) ;
01356   }
01357 
01358   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
01359   //             use of streams (and so on) should never be used because :
01360   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
01361   //             A stream operation may be interrupted by a signal and if the Handler use stream we
01362   //             may have a "Dead-Lock" ===HangUp
01363   //==INFOS is commented
01364   //  INFOS(pthread_self() << "SigIntHandler activated") ;
01365 
01366 #else  
01367   signal( SIGINT, SigIntHandler );
01368   signal( SIGUSR1, SigIntHandler );
01369 #endif
01370 
01371 }
01372 
01373 void SetCpuUsed() ;
01374 void CallCancelThread() ;
01375 
01376 #ifndef WIN32
01377 void SigIntHandler(int what ,
01378                    siginfo_t * siginfo ,
01379                    void * toto ) 
01380 {
01381   //PAL9042 JR : during the execution of a Signal Handler (and of methods called through Signal Handlers)
01382   //             use of streams (and so on) should never be used because :
01383   //             streams of C++ are naturally thread-safe and use pthread_mutex_lock ===>
01384   //             A stream operation may be interrupted by a signal and if the Handler use stream we
01385   //             may have a "Dead-Lock" ===HangUp
01386   //==MESSAGE is commented
01387   //  MESSAGE(pthread_self() << "SigIntHandler what     " << what << std::endl
01388   //          << "              si_signo " << siginfo->si_signo << std::endl
01389   //          << "              si_code  " << siginfo->si_code << std::endl
01390   //          << "              si_pid   " << siginfo->si_pid) ;
01391 
01392   if ( _Sleeping )
01393   {
01394     _Sleeping = false ;
01395     //     MESSAGE("SigIntHandler END sleeping.") ;
01396     return ;
01397   }
01398   else
01399   {
01400     ActSigIntHandler() ;
01401     if ( siginfo->si_signo == SIGUSR1 )
01402     {
01403       SetCpuUsed() ;
01404     }
01405     else if ( siginfo->si_signo == SIGUSR2 )
01406     {
01407       CallCancelThread() ;
01408     }
01409     else 
01410     {
01411       _Sleeping = true ;
01412       //      MESSAGE("SigIntHandler BEGIN sleeping.") ;
01413       int count = 0 ;
01414       while( _Sleeping )
01415       {
01416         sleep( 1 ) ;
01417         count += 1 ;
01418       }
01419       //      MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
01420     }
01421     return ;
01422   }
01423 }
01424 #else // Case WIN32
01425 void SigIntHandler( int what )
01426 {
01427 #ifndef WIN32
01428   MESSAGE( pthread_self() << "SigIntHandler what     " << what << std::endl );
01429 #else
01430   MESSAGE( "SigIntHandler what     " << what << std::endl );
01431 #endif
01432   if ( _Sleeping )
01433   {
01434     _Sleeping = false ;
01435     MESSAGE("SigIntHandler END sleeping.") ;
01436     return ;
01437   }
01438   else
01439   {
01440     ActSigIntHandler() ;
01441     if ( what == SIGUSR1 )
01442     {
01443       SetCpuUsed() ;
01444     }
01445     else
01446     {
01447       _Sleeping = true ;
01448       MESSAGE("SigIntHandler BEGIN sleeping.") ;
01449       int count = 0 ;
01450       while( _Sleeping ) 
01451       {
01452         Sleep( 1000 ) ;
01453         count += 1 ;
01454       }
01455       MESSAGE("SigIntHandler LEAVE sleeping after " << count << " s.") ;
01456     }
01457     return ;
01458   }
01459 }
01460 #endif
01461 
01462 //=============================================================================
01464 
01473 //=============================================================================
01474 Engines::fileRef_ptr
01475 Engines_Container_i::createFileRef(const char* origFileName)
01476 {
01477   std::string origName(origFileName);
01478   Engines::fileRef_var theFileRef = Engines::fileRef::_nil();
01479 
01480   if (origName[0] != '/')
01481   {
01482     INFOS("path of file to copy must be an absolute path begining with '/'");
01483     return Engines::fileRef::_nil();
01484   }
01485 
01486   if (CORBA::is_nil(_fileRef_map[origName]))
01487   {
01488     CORBA::Object_var obj=_poa->id_to_reference(*_id);
01489     Engines::Container_var pCont = Engines::Container::_narrow(obj);
01490     fileRef_i* aFileRef = new fileRef_i(pCont, origFileName);
01491     theFileRef = Engines::fileRef::_narrow(aFileRef->_this());
01492     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
01493     _fileRef_map[origName] = theFileRef;
01494     _numInstanceMutex.unlock() ;
01495   }
01496 
01497   theFileRef =  Engines::fileRef::_duplicate(_fileRef_map[origName]);
01498   ASSERT(! CORBA::is_nil(theFileRef));
01499   return theFileRef._retn();
01500 }
01501 
01502 //=============================================================================
01504 
01508 //=============================================================================
01509 Engines::fileTransfer_ptr
01510 Engines_Container_i::getFileTransfer()
01511 {
01512   Engines::fileTransfer_var aFileTransfer
01513     = Engines::fileTransfer::_duplicate(_fileTransfer);
01514   return aFileTransfer._retn();
01515 }
01516 
01517 //=============================================================================
01519 //=============================================================================
01520 Engines::Salome_file_ptr
01521 Engines_Container_i::createSalome_file(const char* origFileName)
01522 {
01523   std::string origName(origFileName);
01524   if (CORBA::is_nil(_Salome_file_map[origName]))
01525   {
01526     Salome_file_i* aSalome_file = new Salome_file_i();
01527     aSalome_file->setContainer(Engines::Container::_duplicate(this->_this()));
01528     try
01529     {
01530       aSalome_file->setLocalFile(origFileName);
01531       aSalome_file->recvFiles();
01532     }
01533     catch (const SALOME::SALOME_Exception& e)
01534     {
01535       return Engines::Salome_file::_nil();
01536     }
01537 
01538     Engines::Salome_file_var theSalome_file = Engines::Salome_file::_nil();
01539     theSalome_file = Engines::Salome_file::_narrow(aSalome_file->_this());
01540     _numInstanceMutex.lock() ; // lock to be alone (stl container write)
01541     _Salome_file_map[origName] = theSalome_file;
01542     _numInstanceMutex.unlock() ;
01543   }
01544 
01545   Engines::Salome_file_ptr theSalome_file =
01546     Engines::Salome_file::_duplicate(_Salome_file_map[origName]);
01547   ASSERT(!CORBA::is_nil(theSalome_file));
01548   return theSalome_file;
01549 }
01550 
01551 //=============================================================================
01557 //=============================================================================
01558 void Engines_Container_i::copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile)
01559 {
01560   Engines::fileTransfer_var fileTransfer = container->getFileTransfer();
01561 
01562   FILE* fp;
01563   if ((fp = fopen(localFile,"wb")) == NULL)
01564     {
01565       INFOS("file " << localFile << " cannot be open for writing");
01566       return;
01567     }
01568 
01569   CORBA::Long fileId = fileTransfer->open(remoteFile);
01570   if (fileId > 0)
01571     {
01572       Engines::fileBlock* aBlock;
01573       int toFollow = 1;
01574       int ctr=0;
01575       while (toFollow)
01576         {
01577           ctr++;
01578           SCRUTE(ctr);
01579           aBlock = fileTransfer->getBlock(fileId);
01580           toFollow = aBlock->length();
01581           SCRUTE(toFollow);
01582           CORBA::Octet *buf = aBlock->get_buffer();
01583           fwrite(buf, sizeof(CORBA::Octet), toFollow, fp);
01584           delete aBlock;
01585         }
01586       fclose(fp);
01587       MESSAGE("end of transfer");
01588       fileTransfer->close(fileId);
01589     }
01590   else
01591     {
01592       INFOS("open reference file for copy impossible");
01593     }
01594 }
01595 
01596 //=============================================================================
01602 //=============================================================================
01603 Engines::PyNode_ptr Engines_Container_i::createPyNode(const char* nodeName, const char* code)
01604 {
01605     Engines::PyNode_var node= Engines::PyNode::_nil();
01606 
01607     PyGILState_STATE gstate = PyGILState_Ensure();
01608     PyObject *res = PyObject_CallMethod(_pyCont,
01609       (char*)"create_pynode",
01610       (char*)"ss",
01611       nodeName,
01612       code);
01613     if(res==NULL)
01614       {
01615         //internal error
01616         PyErr_Print();
01617         PyGILState_Release(gstate);
01618         SALOME::ExceptionStruct es;
01619         es.type = SALOME::INTERNAL_ERROR;
01620         es.text = "can not create a python node";
01621         throw SALOME::SALOME_Exception(es);
01622       }
01623     long ierr=PyInt_AsLong(PyTuple_GetItem(res,0));
01624     PyObject* result=PyTuple_GetItem(res,1);
01625     std::string astr=PyString_AsString(result);
01626     Py_DECREF(res);
01627     PyGILState_Release(gstate);
01628 
01629     if(ierr==0)
01630       {
01631         CORBA::Object_var obj = _orb->string_to_object(astr.c_str());
01632         node = Engines::PyNode::_narrow(obj);
01633         return node._retn();
01634       }
01635     else
01636       {
01637         SALOME::ExceptionStruct es;
01638         es.type = SALOME::INTERNAL_ERROR;
01639         es.text = astr.c_str();
01640         throw SALOME::SALOME_Exception(es);
01641       }
01642 
01643 }
01644 
01645 //=============================================================================
01651 //=============================================================================
01652 Engines::PyScriptNode_ptr Engines_Container_i::createPyScriptNode(const char* nodeName, const char* code)
01653 {
01654     Engines::PyScriptNode_var node= Engines::PyScriptNode::_nil();
01655 
01656     PyGILState_STATE gstate = PyGILState_Ensure();
01657     PyObject *res = PyObject_CallMethod(_pyCont,
01658       (char*)"create_pyscriptnode",
01659       (char*)"ss",
01660       nodeName,
01661       code);
01662     if(res==NULL)
01663       {
01664         //internal error
01665         PyErr_Print();
01666         PyGILState_Release(gstate);
01667         SALOME::ExceptionStruct es;
01668         es.type = SALOME::INTERNAL_ERROR;
01669         es.text = "can not create a python node";
01670         throw SALOME::SALOME_Exception(es);
01671       }
01672     long ierr=PyInt_AsLong(PyTuple_GetItem(res,0));
01673     PyObject* result=PyTuple_GetItem(res,1);
01674     std::string astr=PyString_AsString(result);
01675     Py_DECREF(res);
01676     PyGILState_Release(gstate);
01677 
01678     if(ierr==0)
01679       {
01680         CORBA::Object_var obj = _orb->string_to_object(astr.c_str());
01681         node = Engines::PyScriptNode::_narrow(obj);
01682         return node._retn();
01683       }
01684     else
01685       {
01686         SALOME::ExceptionStruct es;
01687         es.type = SALOME::INTERNAL_ERROR;
01688         es.text = astr.c_str();
01689         throw SALOME::SALOME_Exception(es);
01690       }
01691 }
01692 
01693 //=============================================================================
01694 /* int checkifexecutable(const char *filename)
01695 *
01696 * Return non-zero if the name is an executable file, and
01697 * zero if it is not executable, or if it does not exist.
01698 */
01699 //=============================================================================
01700 int checkifexecutable(const std::string& filename)
01701 {
01702   int result;
01703   struct stat statinfo;
01704 
01705   result = stat(filename.c_str(), &statinfo);
01706   if (result < 0) return 0;
01707   if (!S_ISREG(statinfo.st_mode)) return 0;
01708 
01709 #ifdef WIN32
01710   return 1;
01711 #else
01712   if (statinfo.st_uid == geteuid()) return statinfo.st_mode & S_IXUSR;
01713   if (statinfo.st_gid == getegid()) return statinfo.st_mode & S_IXGRP;
01714   return statinfo.st_mode & S_IXOTH;
01715 #endif
01716 }
01717 
01718 
01719 //=============================================================================
01726 //=============================================================================
01727 int findpathof(const std::string& path, std::string& pth, const std::string& filename)
01728 {
01729   if ( path.size() == 0 ) return 0;
01730 
01731   std::string::size_type offset = 0;
01732   std::string::size_type pos = 0;
01733   int found = 0;
01734   struct stat statinfo;
01735 
01736   while(!found)
01737   {
01738     pos = path.find( SEP, offset );
01739     pth = path.substr( offset, pos - offset );
01740     if ( pth.size() > 0 )
01741     {
01742       if( pth[pth.size()-1] != SLASH ) pth += SLASH;
01743       pth += filename;
01744       int result=stat(pth.c_str(), &statinfo);
01745       if(result == 0) found=1;
01746     }
01747     if (pos == std::string::npos) break;
01748     offset = pos+1;
01749   }
01750   return found;
01751 }
01752 
01753 void Engines_Container_i::registerTemporaryFile( const std::string& fileName )
01754 {
01755   _tmp_files.remove( fileName );
01756   _tmp_files.push_back( fileName );
01757 }
01758 
01759 void Engines_Container_i::unregisterTemporaryFile( const std::string& fileName )
01760 {
01761   _tmp_files.remove( fileName );
01762 }
01763 
01764 void Engines_Container_i::clearTemporaryFiles()
01765 {
01766   std::list<std::string>::const_iterator it;
01767   for ( it = _tmp_files.begin(); it != _tmp_files.end(); ++it ) {
01768 #ifdef WIN32
01769     std::string command = "del /F ";
01770 #else
01771     std::string command = "rm -rf ";
01772 #endif
01773     command += *it;
01774     system( command.c_str() );
01775   }
01776   _tmp_files.clear();
01777 }