]> SALOME platform Git repositories - modules/yacs.git/blob - src/engine/Proc.cxx
Salome HOME
Merge branch 'V7_dev'
[modules/yacs.git] / src / engine / Proc.cxx
1 // Copyright (C) 2006-2016  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 #include "Proc.hxx"
21 #include "ElementaryNode.hxx"
22 #include "Runtime.hxx"
23 #include "Container.hxx"
24 #include "ComponentInstance.hxx"
25 #include "InputPort.hxx"
26 #include "OutputPort.hxx"
27 #include "TypeCode.hxx"
28 #include "Logger.hxx"
29 #include "Visitor.hxx"
30 #include "VisitorSaveSchema.hxx"
31 #include "VisitorSaveState.hxx"
32 #include <sstream>
33 #include <set>
34
35 //#define _DEVDEBUG_
36 #include "YacsTrace.hxx"
37
38 using namespace std;
39 using namespace YACS::ENGINE;
40
41 /*! \class YACS::ENGINE::Proc
42  *  \brief Base class for all schema objects.
43  *
44  * This is an abstract class that must be specialized in runtime.
45  * \ingroup Nodes
46  */
47
48 Proc::Proc(const std::string& name):Bloc(name),_edition(false),_compoinstctr(0)
49 {
50   Runtime *theRuntime=getRuntime();
51   DEBTRACE("theRuntime->_tc_double->ref: " << theRuntime->_tc_double->getRefCnt());
52   DEBTRACE("theRuntime->_tc_int->ref: " << theRuntime->_tc_int->getRefCnt());
53   DEBTRACE("theRuntime->_tc_string->ref: " << theRuntime->_tc_string->getRefCnt());
54   DEBTRACE("theRuntime->_tc_bool->ref: " << theRuntime->_tc_bool->getRefCnt());
55   DEBTRACE("theRuntime->_tc_file->ref: " << theRuntime->_tc_file->getRefCnt());
56   theRuntime->_tc_double->incrRef();
57   theRuntime->_tc_string->incrRef();
58   theRuntime->_tc_int->incrRef();
59   theRuntime->_tc_bool->incrRef();
60   theRuntime->_tc_file->incrRef();
61   typeMap["double"]=theRuntime->_tc_double;
62   typeMap["string"]=theRuntime->_tc_string;
63   typeMap["int"]=theRuntime->_tc_int;
64   typeMap["bool"]=theRuntime->_tc_bool;
65   typeMap["file"]=theRuntime->_tc_file;
66 }
67
68 Proc::~Proc()
69 {
70   DEBTRACE("Proc::~Proc");
71   //for the moment all nodes are owned, so no need to manage their destruction
72   //nodeMap, inlineMap, serviceMap will be cleared automatically
73   //but we need to destroy TypeCodes
74   std::map<std::string, TypeCode *>::iterator pt;
75   for(pt=typeMap.begin();pt!=typeMap.end();pt++)
76     ((*pt).second)->decrRef();
77
78   removeContainers();
79
80   //get rid of loggers in logger map
81   std::map<std::string, Logger*>::const_iterator lt;
82   for(lt=_loggers.begin();lt!=_loggers.end();lt++)
83     delete (*lt).second;
84 }
85
86 void Proc::writeDot(std::ostream &os) const
87 {
88   os << "digraph " << getQualifiedName() << " {\n" ;
89   os << "node [ style=\"filled\" ];\n" ;
90   os << "compound=true;";
91   os << "states [label=< <TABLE> <TR> <TD BGCOLOR=\"pink\" > Ready</TD> <TD BGCOLOR=\"magenta\" > Toload</TD> </TR> <TR> <TD BGCOLOR=\"magenta\" > Loaded</TD> <TD BGCOLOR=\"purple\" > Toactivate</TD> </TR> <TR> <TD BGCOLOR=\"blue\" > Activated</TD> <TD BGCOLOR=\"green\" > Done</TD> </TR> <TR> <TD BGCOLOR=\"red\" > Error</TD> <TD BGCOLOR=\"orange\" > Failed</TD> </TR> <TR> <TD BGCOLOR=\"grey\" > Disabled</TD> <TD BGCOLOR=\"white\" > Pause</TD> </TR> </TABLE>> \n shape = plaintext \n style = invis \n ];\n";
92
93   Bloc::writeDot(os);
94   os << "}\n" ;
95 }
96
97 std::ostream& operator<< (std::ostream& os, const Proc& p)
98 {
99   os << "Proc" ;
100   return os;
101 }
102
103 TypeCode *Proc::createType(const std::string& name, const std::string& kind)
104 {
105   TypeCode* t;
106   if(kind=="double")
107     t=getRuntime()->_tc_double;
108   else if(kind=="string")
109     t=getRuntime()->_tc_string;
110   else if(kind=="int")
111     t=getRuntime()->_tc_int;
112   else if(kind=="bool")
113     t=getRuntime()->_tc_bool;
114   else
115     throw Exception("Unknown kind");
116
117   if(typeMap.count(name)!=0)
118     typeMap[name]->decrRef();
119   t->incrRef();
120   typeMap[name]=t;
121   t->incrRef();
122   return t;
123 }
124
125 //! Create an object reference TypeCode 
126 /*!
127  * \param id: the TypeCode repository id
128  * \param name: the TypeCode name
129  * \param ltc: a liste of object reference TypeCode to use as base types for this type
130  * \return the created TypeCode
131  */
132 TypeCode *Proc::createInterfaceTc(const std::string& id, const std::string& name,
133                                   std::list<TypeCodeObjref *> ltc)
134 {
135   TypeCode* t = TypeCode::interfaceTc(id.c_str(),name.c_str(),ltc);
136   if(typeMap.count(name)!=0)
137     typeMap[name]->decrRef();
138   typeMap[name]=t;
139   t->incrRef();
140   return t;
141 }
142
143 //! Create a sequence TypeCode 
144 /*!
145  * \param id: the TypeCode repository id ("" for normal use)
146  * \param name: the TypeCode name
147  * \param content: the element TypeCode 
148  * \return the created TypeCode
149  */
150 TypeCode * Proc::createSequenceTc (const std::string& id, const std::string& name,
151                                    TypeCode *content)
152 {
153   TypeCode* t = TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
154   if(typeMap.count(name)!=0)
155     typeMap[name]->decrRef();
156   typeMap[name]=t;
157   t->incrRef();
158   return t;
159 }
160
161 TypeCode * Proc::createStructTc (const std::string& id, const std::string& name)
162 {
163   TypeCode* t = TypeCode::structTc(id.c_str(),name.c_str());
164   if(typeMap.count(name)!=0)
165     typeMap[name]->decrRef();
166   typeMap[name]=t;
167   t->incrRef();
168   return t;
169 }
170
171 TypeCode * Proc::getTypeCode (const std::string& name)
172 {
173   TypeCode* aTC=0;
174   if(typeMap.count(name)==0)
175     aTC=getRuntime()->getTypeCode(name);
176   else
177     aTC=typeMap[name];
178
179   if(!aTC)
180     {
181       std::stringstream msg;
182       msg << "Type " << name << " does not exist" ;
183       msg << " (" <<__FILE__ << ":" << __LINE__ << ")";
184       throw Exception(msg.str());
185     }
186
187   return aTC;
188 }
189
190 void Proc::setTypeCode (const std::string& name,TypeCode *t)
191 {
192   if(typeMap.count(name)!=0)
193     typeMap[name]->decrRef();
194   typeMap[name]=t;
195   t->incrRef();
196 }
197
198
199 void Proc::accept(Visitor *visitor)
200 {
201   visitor->visitProc(this);
202 }
203
204 void Proc::setName(const std::string& name)
205 {
206   _name = name;
207 }
208
209 YACS::StatesForNode Proc::getNodeState(int numId)
210 {
211   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
212     {
213       cerr << "Unknown node id " << numId << endl;
214       return YACS::UNDEFINED;
215     }
216   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[numId];
217   YACS::StatesForNode state = node->getEffectiveState();
218   return state;
219 }
220
221 std::string Proc::getNodeProgress(int numId)
222 {
223   std::string progress = "0";
224   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
225     {
226       cerr << "Unknown node id " << numId << endl;
227     }
228   else if (YACS::ENGINE::ComposedNode* node = dynamic_cast<YACS::ENGINE::ComposedNode*>(YACS::ENGINE::Node::idMap[numId]))
229     progress = node->getProgress();
230   return progress;
231 }
232
233 int Proc::getGlobalProgressPercent()
234 {
235   list<ProgressWeight> weightList = getProgressWeight();
236   int weightDone = 0;
237   int weightTotal = 0;
238   int progressPercent = 0;
239   for(list<ProgressWeight>::const_iterator iter=weightList.begin();iter!=weightList.end();iter++)
240     {
241       weightDone += (*iter).weightDone;
242       weightTotal += (*iter).weightTotal;
243     }
244   if (weightTotal > 0)
245     progressPercent = int(float(weightDone) / float(weightTotal) * 100);
246   return progressPercent;
247 }
248
249 std::string Proc::getXMLState(int numId)
250 {
251   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
252     {
253       cerr << "Unknown node id " << numId << endl;
254       return "<state>unknown</state>";
255     }
256   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[numId];
257   stringstream msg;
258   msg << "<state>" << node->getEffectiveState() << "</state>";
259   msg << "<name>" << node->getQualifiedName() << "</name>";
260   msg << "<id>" << numId << "</id>";
261   return msg.str();
262 }
263
264 std::string Proc::getInPortValue(int nodeNumId, std::string portName)
265 {
266   DEBTRACE("Proc::getInPortValue " << nodeNumId << " " << portName);
267   stringstream msg;
268   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
269     {
270       msg << "<value><error>unknown node id: " << nodeNumId << "</error></value>";
271       return msg.str();
272     }
273   try
274     {
275       YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
276       InputPort * inputPort = node->getInputPort(portName);
277       return inputPort->getAsString();
278     }
279   catch(YACS::Exception& ex)
280     {
281       DEBTRACE("Proc::getInPortValue " << ex.what());
282       msg << "<value><error>" << ex.what() << "</error></value>";
283       return msg.str();
284     }
285 }
286
287 std::string Proc::setInPortValue(std::string nodeName, std::string portName, std::string value)
288 {
289   DEBTRACE("Proc::setInPortValue " << nodeName << " " << portName << " " << value);
290
291   try
292     {
293       YACS::ENGINE::Node* node = YACS::ENGINE::Proc::nodeMap[nodeName];
294       YACS::ENGINE::InputPort* inputPort = node->getInputPort(portName);
295
296       switch (inputPort->edGetType()->kind())
297         {
298           case Double:
299             {
300               double val = atof(value.c_str());
301               inputPort->edInit(val);
302             }
303             break;
304           case Int:
305             {
306               int val = atoi(value.c_str());
307               inputPort->edInit(val);
308             }
309             break;
310           case String:
311             inputPort->edInit(value.c_str());
312             break;
313           case Bool:
314             {
315               if((!value.compare("False")) || (!value.compare("false")))
316                 inputPort->edInit(false);
317               else if ((!value.compare("True")) || (!value.compare("true")))
318                 inputPort->edInit(true);
319               else
320               {
321                 int val = atoi(value.c_str());
322                 inputPort->edInit(val);
323               }
324             }
325             break;
326           default:
327             DEBTRACE("Proc::setInPortValue: filtered type: " << inputPort->edGetType()->kind());
328         }
329       return value;
330     }
331   catch(YACS::Exception& ex)
332     {
333       DEBTRACE("Proc::setInPortValue " << ex.what());
334       stringstream msg;
335       msg << "<value><error>" << ex.what() << "</error></value>";
336       return msg.str();
337     }
338 }
339
340 std::string Proc::getOutPortValue(int nodeNumId, std::string portName)
341 {
342   DEBTRACE("Proc::getOutPortValue " << nodeNumId << " " << portName);
343   stringstream msg;
344   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
345     {
346       msg << "<value><error>unknown node id: " << nodeNumId << "</error></value>";
347       return msg.str();
348     }
349   try
350     {
351       YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
352       OutputPort * outputPort = node->getOutputPort(portName);
353       return outputPort->getAsString();
354     }
355   catch(YACS::Exception& ex)
356     {
357       DEBTRACE("Proc::getOutPortValue " << ex.what());
358       msg << "<value><error>" << ex.what() << "</error></value>";
359       return msg.str();
360     }
361 }
362
363 std::string Proc::getNodeErrorDetails(int nodeNumId)
364 {
365   DEBTRACE("Proc::getNodeErrorDetails " << nodeNumId);
366   stringstream msg;
367   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
368     {
369       msg << "Unknown node id " << nodeNumId;
370       return msg.str();
371     }
372   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
373   return node->getErrorDetails();
374 }
375
376 std::string Proc::getNodeErrorReport(int nodeNumId)
377 {
378   DEBTRACE("Proc::getNodeErrorReport " << nodeNumId);
379   stringstream msg;
380   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
381     {
382       msg << "Unknown node id " << nodeNumId;
383       return msg.str();
384     }
385   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
386   return node->getErrorReport();
387 }
388
389 std::string Proc::getNodeContainerLog(int nodeNumId)
390 {
391   DEBTRACE("Proc::getNodeContainerLog " << nodeNumId);
392   stringstream msg;
393   if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0)
394     {
395       msg << "Unknown node id " << nodeNumId;
396       return msg.str();
397     }
398   YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
399   return node->getContainerLog();
400 }
401
402 std::list<int> Proc::getNumIds()
403 {
404   list<YACS::ENGINE::Node *> nodes = getAllRecursiveConstituents();
405   int len = nodes.size();
406   list<int> numids;
407   for( list<YACS::ENGINE::Node *>::const_iterator iter = nodes.begin();
408        iter != nodes.end(); iter++)
409     {
410       numids.push_back((*iter)->getNumId());
411     }
412   numids.push_back(this->getNumId());
413   return numids;
414 }
415
416 std::list<std::string> Proc::getIds()
417 {
418   list<YACS::ENGINE::Node *> nodes = getAllRecursiveConstituents();
419   int len = nodes.size();
420   list<string> ids;
421   for( list<YACS::ENGINE::Node *>::const_iterator iter = nodes.begin();
422        iter != nodes.end(); iter++)
423     {
424       ids.push_back(getChildName(*iter));
425     }
426   ids.push_back("_root_");
427   return ids;
428 }
429
430 Logger *Proc::getLogger(const std::string& name)
431 {
432   Logger* logger;
433   LoggerMap::const_iterator it = _loggers.find(name);
434
435   if (it != _loggers.end())
436   {
437     logger = it->second;
438   }
439   else
440   {
441     logger = new Logger(name);
442     _loggers[name]=logger;
443   }
444   return logger;
445 }
446
447 void Proc::setEdition(bool edition)
448 {
449   DEBTRACE("Proc::setEdition: " << edition);
450   _edition=edition;
451   if(_edition)
452     edUpdateState();
453 }
454 //! Sets Proc in modified state and update state if in edition mode
455 /*!
456  *
457  */
458 void Proc::modified()
459 {
460   DEBTRACE("Proc::modified() " << _edition);
461   _modified=1;
462   if(_edition)
463     edUpdateState();
464 }
465
466 //! Save Proc in XML schema file
467 /*!
468  * \param xmlSchemaFile: the file name
469  */
470 void Proc::saveSchema(const std::string& xmlSchemaFile)
471 {
472   VisitorSaveSchema vss(this);
473   vss.openFileSchema(xmlSchemaFile);
474   accept(&vss);
475   vss.closeFileSchema();
476 }
477
478 //! Save Proc state in XML state file
479 /*!
480  * \param xmlStateFile: the file name
481  */
482 void Proc::saveState(const std::string& xmlStateFile)
483 {
484   VisitorSaveState vst(this);
485   vst.openFileDump(xmlStateFile);
486   accept(&vst);
487   vst.closeFileDump();
488 }
489
490 void Proc::removeContainers()
491 {
492   //get rid of containers in container map
493   std::map<std::string, Container*>::const_iterator it;
494   for(it=containerMap.begin();it!=containerMap.end();it++)
495     ((*it).second)->decrRef();
496   containerMap.clear();
497 }
498
499 //! Create a new Container and store it in containerMap
500 /*!
501  * \param name: the container name and key in containerMap
502  * \param kind: the container kind (depends on runtime)
503  * \return the created Container
504  */
505 Container *Proc::createContainer(const std::string& name, const std::string& kind)
506 {
507   Container *co(getRuntime()->createContainer(kind));
508   co->setName(name);
509   if(containerMap.count(name)!=0)
510     containerMap[name]->decrRef();
511   containerMap[name]=co;
512   co->incrRef();
513   co->setProc(this);
514   return co;
515 }
516
517 //! Add a ComponentInstance into componentInstanceMap
518 /*!
519  * If the name == "", the component instance is automatically named with a unique (in the Proc) name
520  *
521  * \param inst: the component instance
522  * \param name: the component instance name
523  * \param resetCtr: try to reuse instance number previously released, false by default
524  */
525 void Proc::addComponentInstance(ComponentInstance* inst, const std::string& name, bool resetCtr)
526 {
527   if(name != "")
528     {
529       inst->setName(name);
530       inst->setAnonymous(false);
531       if(componentInstanceMap.count(name)!=0)
532         componentInstanceMap[name]->decrRef();
533       componentInstanceMap[name]=inst;
534       inst->incrRef();
535     }
536   else
537     {
538       //automatic naming : componame_<_compoinstctr>
539       std::string instname;
540       std::string componame=inst->getCompoName();
541       if (resetCtr)
542         _compoinstctr = 0;        
543       while(1)
544         {
545           std::ostringstream buffer;
546           buffer << ++_compoinstctr;
547           instname=componame+"_"+buffer.str();
548           if(componentInstanceMap.count(instname)==0)
549             {
550               inst->setName(instname);
551               componentInstanceMap[instname]=inst;
552               inst->incrRef();
553               break;
554             }
555         }
556     }
557 }
558
559 //! Remove a componentInstance from the componentInstanceMap
560 /*!
561  * To be used for a componentInstance with no service nodes referenced.
562  *
563  * \param inst: the component instance
564  */
565 void Proc::removeComponentInstance(ComponentInstance* inst)
566 {
567   if (componentInstanceMap.count(inst->getInstanceName()))
568     {
569       componentInstanceMap.erase(inst->getInstanceName());
570       inst->decrRef();
571     }
572 }
573
574 //! Remove a container from the containerMap
575 /*!
576  * To be used for a container with no componentInstance referenced.
577  *
578  * \param cont: the container
579  */
580 void Proc::removeContainer(Container* cont)
581 {
582   if (containerMap.count(cont->getName()))
583     {
584       containerMap.erase(cont->getName());
585       cont->decrRef();
586     }
587 }
588
589 //! Create a new ComponentInstance and add it into componentInstanceMap
590 /*!
591  * If the name == "", the component instance is automatically named with a unique (in the Proc) name
592  *
593  * \param componame: the component name
594  * \param name: the component instance name
595  * \param kind: the component instance kind (depends on runtime)
596  * \return the created ComponentInstance
597  */
598 ComponentInstance* Proc::createComponentInstance(const std::string& componame, const std::string& name,const std::string& kind)
599 {
600   ComponentInstance* inst=  getRuntime()->createComponentInstance(componame,kind);
601   addComponentInstance(inst,name);
602   return inst;
603 }
604
605 //! Return the proc (this)
606 Proc* Proc::getProc()
607 {
608   return this;
609 }
610
611 //! Return the proc (this)
612 const Proc * Proc::getProc() const
613 {
614   return this;
615 }
616
617 /*!
618  * This method is useful if this has been modified recursively and an update is needed between all the
619  * containers and components refered by children and little children and maps.
620  */
621 void Proc::updateContainersAndComponents()
622 {
623   std::map<std::string, Container*> myContainerMap;
624   std::map<std::string, ComponentInstance*> myComponentInstanceMap;
625   DeploymentTree treeToDup(getDeploymentTree());
626   vector<Container *> conts(treeToDup.getAllContainers());
627   for(vector<Container *>::const_iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
628     {
629       Container *tmp(*iterCt);
630       if(tmp)
631         {
632           if(myContainerMap.find(tmp->getName())!=myContainerMap.end())
633             {
634               std::ostringstream oss; oss << "Proc::updateContainersAndComponents : more than one container instance with name \"" << tmp->getName() << "\" !";
635               throw YACS::Exception(oss.str());
636             }
637           myContainerMap[tmp->getName()]=tmp;
638           tmp->incrRef();
639         }
640       vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
641       for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
642         {
643           ComponentInstance *tmp2(*iterCp);
644           if(tmp2)
645             {
646               if(myComponentInstanceMap.find(tmp2->getCompoName())!=myComponentInstanceMap.end())
647                 {
648                   std::ostringstream oss; oss << "Proc::updateContainersAndComponents : more than one component instance with name \"" << tmp2->getCompoName() << "\" !";
649                   throw YACS::Exception(oss.str());
650                 }
651             }
652           myComponentInstanceMap[tmp2->getCompoName()]=tmp2;
653           tmp2->incrRef();
654         }
655     }
656   removeContainers();
657   containerMap=myContainerMap;
658   componentInstanceMap=myComponentInstanceMap;
659 }