]> SALOME platform Git repositories - modules/yacs.git/blob - src/runtime/SalomeContainer.cxx
Salome HOME
some factorizations before introducing new type of yacs container.
[modules/yacs.git] / src / runtime / SalomeContainer.cxx
1 // Copyright (C) 2006-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //#define REFCNT
21 //
22 #ifdef REFCNT
23 #define private public
24 #define protected public
25 #include <omniORB4/CORBA.h>
26 #include <omniORB4/internal/typecode.h>
27 #endif
28
29 #include "RuntimeSALOME.hxx"
30 #include "SalomeContainer.hxx"
31 #include "SalomeComponent.hxx"
32 #include "Proc.hxx"
33
34 #include "SALOME_NamingService.hxx"
35 #include "SALOME_LifeCycleCORBA.hxx"
36 #include "SALOME_ContainerManager.hxx"
37 #include "Basics_Utils.hxx"
38 #include "OpUtil.hxx"
39
40 #include <sstream>
41 #include <iostream>
42
43 #ifdef WIN32
44 #include <process.h>
45 #define getpid _getpid
46 #endif
47
48 //#define _DEVDEBUG_
49 #include "YacsTrace.hxx"
50
51 using namespace YACS::ENGINE;
52 using namespace std;
53
54 SalomeContainer::SalomeContainer():_launchMode("start"),_launchModeType(new SalomeContainerMonoHelper),_shutdownLevel(999)
55 {
56 }
57
58 SalomeContainer::SalomeContainer(const SalomeContainer& other)
59 : Container(other),
60   _launchMode(other._launchMode),
61   _launchModeType(other._launchModeType->deepCpyOnlyStaticInfo()),
62   _shutdownLevel(other._shutdownLevel),
63   _sct(other._sct)
64 {
65 }
66
67 SalomeContainer::~SalomeContainer()
68 {
69   delete _launchModeType;
70 }
71
72 void SalomeContainer::lock()
73 {
74   _mutex.lock();
75 }
76
77 void SalomeContainer::unLock()
78 {
79   _mutex.unlock();
80 }
81
82 Container *SalomeContainer::clone() const
83 {
84   if(_isAttachedOnCloning)
85     {
86       incrRef();
87       return (Container*) (this);
88     }
89   else
90     return new SalomeContainer(*this);
91 }
92
93 Container *SalomeContainer::cloneAlways() const
94 {
95   return new SalomeContainer(*this);
96 }
97
98 void SalomeContainer::checkCapabilityToDealWith(const ComponentInstance *inst) const throw(YACS::Exception)
99 {
100   if(inst->getKind()!=SalomeComponent::KIND)
101     throw Exception("SalomeContainer::checkCapabilityToDealWith : SalomeContainer is not able to deal with this type of ComponentInstance.");
102 }
103
104 void SalomeContainer::setProperty(const std::string& name, const std::string& value)
105 {
106   if (name == "type")
107     {
108       if (value == SalomeContainerMonoHelper::TYPE_NAME)
109         {
110           delete _launchModeType;
111           _launchModeType=new SalomeContainerMonoHelper;
112         }
113       else if (value == SalomeContainerMultiHelper::TYPE_NAME)
114         {
115           delete _launchModeType;
116           _launchModeType=new SalomeContainerMultiHelper;
117         }
118       else
119         throw Exception("SalomeContainer::setProperty : type value is not correct (mono or multi): " + value);
120       return ;
121     }
122   _sct.setProperty(name,value);
123 }
124
125 std::string SalomeContainer::getProperty(const std::string& name) const
126 {
127   return _sct.getProperty(name);
128 }
129
130 void SalomeContainer::clearProperties()
131 {
132   _sct.clearProperties();
133 }
134
135 void SalomeContainer::addComponentName(std::string name)
136 {
137   _componentNames.push_back(name);
138 }
139
140 void SalomeContainer::addToResourceList(const std::string& name)
141 {
142   _sct.addToResourceList(name);
143 }
144
145 //! Load a component instance in this container
146 /*!
147  * \param inst the component instance to load
148  */
149 CORBA::Object_ptr SalomeContainer::loadComponent(ComponentInstance *inst)
150 {
151   DEBTRACE("SalomeContainer::loadComponent ");
152   lock();//To be sure
153   if(!isAlreadyStarted(inst))
154     {
155       try
156         {
157           start(inst);
158         }
159       catch(Exception& e)
160         {
161           unLock();
162           throw e;
163         }
164     }
165   unLock();
166   lock();//To be sure
167   CORBA::Object_ptr objComponent=CORBA::Object::_nil();
168   std::string compoName=inst->getCompoName();
169   const char* componentName=compoName.c_str();
170   Engines::Container_var container(_launchModeType->getContainer(inst));
171
172   char* reason;
173
174   bool isLoadable = container->load_component_Library(componentName, reason);
175   if (isLoadable)
176     {
177       CORBA::string_free(reason);
178       int studyid=1;
179       Proc* p=getProc();
180       if(p)
181         {
182           std::string value=p->getProperty("DefaultStudyID");
183           if(!value.empty())
184             studyid= atoi(value.c_str());
185         }
186       // prepare component instance properties
187       Engines::FieldsDict_var env = new Engines::FieldsDict;
188       std::map<std::string, std::string> properties = inst->getProperties();
189       if(p)
190         {
191           std::map<std::string,std::string> procMap=p->getProperties();
192           properties.insert(procMap.begin(),procMap.end());
193         }
194
195       std::map<std::string, std::string>::const_iterator itm;
196       env->length(properties.size());
197       int item=0;
198       for(itm = properties.begin(); itm != properties.end(); ++itm, item++)
199         {
200           DEBTRACE("envname="<<itm->first<<" envvalue="<< itm->second);
201           env[item].key= CORBA::string_dup(itm->first.c_str());
202           env[item].value <<= itm->second.c_str();
203         }
204
205       objComponent=container->create_component_instance_env(componentName, studyid, env, reason);
206     }
207
208   if(CORBA::is_nil(objComponent))
209     {
210       unLock();
211       std::string text="Error while trying to create a new component: component '"+ compoName;
212       text=text+"' is not installed or it's a wrong name";
213       text += '\n';
214       text += reason;
215       CORBA::string_free(reason);
216       throw Exception(text);
217     }
218   unLock();
219   return objComponent;
220 }
221
222 //! Get the container placement id for a component instance
223 /*!
224  * \param inst the component instance
225  * \return the placement id
226  */
227 std::string SalomeContainer::getPlacementId(const ComponentInstance *inst) const
228 {
229
230   if(isAlreadyStarted(inst))
231     {
232       Engines::Container_var container(_launchModeType->getContainer(inst));
233       const char *what="/";
234       CORBA::String_var corbaStr=container->name();
235       string ret(corbaStr);
236
237       //Salome FOREVER ...
238       std::string::size_type i=ret.find_first_of(what,0);
239       i=ret.find_first_of(what, i==std::string::npos ? i:i+1);
240       if(i!=std::string::npos)
241         return ret.substr(i+1);
242       return ret;
243     }
244   else
245     return "Not placed yet !!!";
246 }
247
248 //! Get the container full path for a component instance
249 /*!
250  * \param inst the component instance
251  * \return the full placement id
252  */
253 std::string SalomeContainer::getFullPlacementId(const ComponentInstance *inst) const
254 {
255
256   if(isAlreadyStarted(inst))
257     {
258       Engines::Container_var container(_launchModeType->getContainer(inst));
259       try
260         {
261           CORBA::String_var corbaStr=container->name();
262           string ret(corbaStr);
263           return ret;
264         }
265       catch(...)
266         {
267           return "Unknown_placement";
268         }
269     }
270   else
271     return "Not_placed_yet";
272 }
273
274 //! Check if the component instance container is already started
275 /*!
276  * \param inst the component instance
277  * \return true, if the container is already started, else false
278  */
279 bool SalomeContainer::isAlreadyStarted(const ComponentInstance *inst) const
280 {
281   return _launchModeType->isAlreadyStarted(inst);
282 }
283
284 Engines::Container_ptr SalomeContainer::getContainerPtr(const ComponentInstance *inst) const
285 {
286   return Engines::Container::_duplicate(_launchModeType->getContainer(inst));
287 }
288
289 //! Start a salome container (true salome container not yacs one) with given ContainerParameters (_params)
290 /*!
291  * \param inst the component instance
292  */
293 void SalomeContainer::start(const ComponentInstance *inst) throw(YACS::Exception)
294 {
295   CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
296   SALOME_NamingService ns;
297   try
298     {
299       ns.init_orb(orb);
300     }
301   catch(SALOME_Exception& e)
302     {
303       throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service");
304     }
305   CORBA::Object_var obj(ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS));
306   Engines::ContainerManager_var contManager(Engines::ContainerManager::_narrow(obj));
307
308   std::string str(_sct.getContainerName());
309   DEBTRACE("SalomeContainer::start " << str <<";"<< _sct.getHostName() <<";"<<_type);
310
311   // Finalize parameters with components found in the container
312   std::vector<std::string>::iterator iter;
313   for(CORBA::ULong i=0; i < _componentNames.size();i++)
314     _sct.addToComponentList(_componentNames[i]);
315   Engines::ContainerParameters myparams(_sct.getParameters());
316
317   bool namedContainer=false;
318   if(str != "")
319     namedContainer=true;
320
321   //If a container_name is given try to find an already existing container in naming service
322   //If not found start a new container with the given parameters
323   if (dynamic_cast<SalomeContainerMonoHelper *>(_launchModeType) && str != "")
324     {
325       myparams.mode="getorstart";
326     }
327
328   if (str == "")
329   {
330     //give a almost unique name to the container : Pid_Name_Addr
331     std::ostringstream stream;
332     stream << getpid();
333     stream << "_";
334     stream << _name;
335     stream << "_";
336     stream << (void *)(this);
337     DEBTRACE("container_name="<<stream.str());
338     myparams.container_name=CORBA::string_dup(stream.str().c_str());
339     _shutdownLevel=1;
340   }
341
342   Engines::Container_var trueCont(Engines::Container::_nil());
343   if(namedContainer && _shutdownLevel==999)
344     {
345       //Make this only the first time start is called (_shutdownLevel==999)
346       //If the container is named, first try to get an existing container
347       //If there is an existing container use it and set the shutdown level to 3
348       //If there is no existing container, try to launch a new one and set the shutdown level to 2
349       myparams.mode="get";
350       try
351         { 
352           trueCont=contManager->GiveContainer(myparams);
353         }
354       catch( const SALOME::SALOME_Exception& ex )
355         {
356           std::string msg="SalomeContainer::start : no existing container : ";
357           msg += '\n';
358           msg += ex.details.text.in();
359           DEBTRACE( msg );
360         }
361       catch(...)
362         {
363         }
364
365       if(!CORBA::is_nil(trueCont))
366         {
367           _shutdownLevel=3;
368           DEBTRACE( "container found: " << str << " " << _shutdownLevel );
369         }
370       else
371         {
372           _shutdownLevel=2;
373           myparams.mode="start";
374           DEBTRACE( "container not found: " << str << " " << _shutdownLevel);
375         }
376     }
377
378   if(CORBA::is_nil(trueCont))
379     try
380       { 
381         // --- GiveContainer is used in batch mode to retreive launched containers,
382         //     and is equivalent to StartContainer when not in batch.
383         trueCont=contManager->GiveContainer(myparams);
384       }
385     catch( const SALOME::SALOME_Exception& ex )
386       {
387         std::string msg="SalomeContainer::start : Unable to launch container in Salome : ";
388         msg += '\n';
389         msg += ex.details.text.in();
390         throw Exception(msg);
391       }
392     catch(CORBA::COMM_FAILURE&)
393       {
394         throw Exception("SalomeContainer::start : Unable to launch container in Salome : CORBA Comm failure detected");
395       }
396     catch(CORBA::Exception&)
397       {
398         throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected");
399       }
400
401   if(CORBA::is_nil(trueCont))
402     throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file");
403
404   _launchModeType->setContainer(inst,trueCont);
405
406   CORBA::String_var containerName(trueCont->name()),hostName(trueCont->getHostName());
407   std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << trueCont->getPID() << std::endl;
408 }
409
410 void SalomeContainer::shutdown(int level)
411 {
412   DEBTRACE("SalomeContainer::shutdown: " << _name << "," << level << "," << _shutdownLevel);
413   if(level < _shutdownLevel)
414     return;
415
416   _shutdownLevel=999;
417   //shutdown the SALOME containers
418   _launchModeType->shutdown();
419 }
420
421 std::map<std::string,std::string> SalomeContainer::getResourceProperties(const std::string& name) const
422 {
423   return _sct.getResourceProperties(name);
424 }
425
426 std::map<std::string,std::string> SalomeContainer::getProperties() const
427 {
428   return _sct.getProperties();
429 }