Salome HOME
new method returning calculation progress
[modules/yacs.git] / src / engine / Proc.cxx
index 9ccc9415d27747392a3ecdcf763a74e2dd43820a..4cb7429557d682721059287de61881aa0e0fe619 100644 (file)
@@ -1,12 +1,34 @@
+// Copyright (C) 2006-2015  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
 #include "Proc.hxx"
 #include "ElementaryNode.hxx"
 #include "Runtime.hxx"
 #include "Container.hxx"
+#include "ComponentInstance.hxx"
 #include "InputPort.hxx"
 #include "OutputPort.hxx"
 #include "TypeCode.hxx"
 #include "Logger.hxx"
 #include "Visitor.hxx"
+#include "VisitorSaveSchema.hxx"
+#include "VisitorSaveState.hxx"
 #include <sstream>
 #include <set>
 
 using namespace std;
 using namespace YACS::ENGINE;
 
-Proc::Proc(const std::string& name):Bloc(name),_edition(false)
+/*! \class YACS::ENGINE::Proc
+ *  \brief Base class for all schema objects.
+ *
+ * This is an abstract class that must be specialized in runtime.
+ * \ingroup Nodes
+ */
+
+Proc::Proc(const std::string& name):Bloc(name),_edition(false),_compoinstctr(0)
 {
   Runtime *theRuntime=getRuntime();
   DEBTRACE("theRuntime->_tc_double->ref: " << theRuntime->_tc_double->getRefCnt());
@@ -46,10 +75,7 @@ Proc::~Proc()
   for(pt=typeMap.begin();pt!=typeMap.end();pt++)
     ((*pt).second)->decrRef();
 
-  //get rid of containers in container map
-  std::map<std::string, Container*>::const_iterator it;
-  for(it=containerMap.begin();it!=containerMap.end();it++)
-    ((*it).second)->decrRef();
+  removeContainers();
 
   //get rid of loggers in logger map
   std::map<std::string, Logger*>::const_iterator lt;
@@ -62,6 +88,8 @@ void Proc::writeDot(std::ostream &os) const
   os << "digraph " << getQualifiedName() << " {\n" ;
   os << "node [ style=\"filled\" ];\n" ;
   os << "compound=true;";
+  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";
+
   Bloc::writeDot(os);
   os << "}\n" ;
 }
@@ -86,37 +114,77 @@ TypeCode *Proc::createType(const std::string& name, const std::string& kind)
   else
     throw Exception("Unknown kind");
 
+  if(typeMap.count(name)!=0)
+    typeMap[name]->decrRef();
+  t->incrRef();
+  typeMap[name]=t;
   t->incrRef();
   return t;
 }
 
+//! Create an object reference TypeCode 
+/*!
+ * \param id: the TypeCode repository id
+ * \param name: the TypeCode name
+ * \param ltc: a liste of object reference TypeCode to use as base types for this type
+ * \return the created TypeCode
+ */
 TypeCode *Proc::createInterfaceTc(const std::string& id, const std::string& name,
                                   std::list<TypeCodeObjref *> ltc)
 {
-  return TypeCode::interfaceTc(id.c_str(),name.c_str(),ltc);
+  TypeCode* t = TypeCode::interfaceTc(id.c_str(),name.c_str(),ltc);
+  if(typeMap.count(name)!=0)
+    typeMap[name]->decrRef();
+  typeMap[name]=t;
+  t->incrRef();
+  return t;
 }
 
+//! Create a sequence TypeCode 
+/*!
+ * \param id: the TypeCode repository id ("" for normal use)
+ * \param name: the TypeCode name
+ * \param content: the element TypeCode 
+ * \return the created TypeCode
+ */
 TypeCode * Proc::createSequenceTc (const std::string& id, const std::string& name,
                                    TypeCode *content)
 {
-  return TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
+  TypeCode* t = TypeCode::sequenceTc(id.c_str(),name.c_str(),content);
+  if(typeMap.count(name)!=0)
+    typeMap[name]->decrRef();
+  typeMap[name]=t;
+  t->incrRef();
+  return t;
 }
 
 TypeCode * Proc::createStructTc (const std::string& id, const std::string& name)
 {
-  return TypeCode::structTc(id.c_str(),name.c_str());
+  TypeCode* t = TypeCode::structTc(id.c_str(),name.c_str());
+  if(typeMap.count(name)!=0)
+    typeMap[name]->decrRef();
+  typeMap[name]=t;
+  t->incrRef();
+  return t;
 }
 
 TypeCode * Proc::getTypeCode (const std::string& name)
 {
+  TypeCode* aTC=0;
   if(typeMap.count(name)==0)
+    aTC=getRuntime()->getTypeCode(name);
+  else
+    aTC=typeMap[name];
+
+  if(!aTC)
     {
       std::stringstream msg;
       msg << "Type " << name << " does not exist" ;
       msg << " (" <<__FILE__ << ":" << __LINE__ << ")";
       throw Exception(msg.str());
     }
-  return typeMap[name];
+
+  return aTC;
 }
 
 void Proc::setTypeCode (const std::string& name,TypeCode *t)
@@ -124,6 +192,7 @@ void Proc::setTypeCode (const std::string& name,TypeCode *t)
   if(typeMap.count(name)!=0)
     typeMap[name]->decrRef();
   typeMap[name]=t;
+  t->incrRef();
 }
 
 
@@ -149,6 +218,34 @@ YACS::StatesForNode Proc::getNodeState(int numId)
   return state;
 }
 
+std::string Proc::getNodeProgress(int numId)
+{
+  std::string progress = "0";
+  if(YACS::ENGINE::Node::idMap.count(numId) == 0)
+    {
+      cerr << "Unknown node id " << numId << endl;
+    }
+  else if (YACS::ENGINE::ComposedNode* node = dynamic_cast<YACS::ENGINE::ComposedNode*>(YACS::ENGINE::Node::idMap[numId]))
+    progress = node->getProgress();
+  return progress;
+}
+
+int Proc::getGlobalProgressPercent()
+{
+       list<pair <int,int> > weightList = getProgressWeight();
+       int weightDone = 0;
+       int weightTotal = 0;
+       int progressPercent = 0;
+       for(list<pair <int,int> >::const_iterator iter=weightList.begin();iter!=weightList.end();iter++)
+         {
+                 weightDone += (*iter).first;
+                       weightTotal += (*iter).second;
+         }
+  if (weightTotal > 0)
+       progressPercent = int(float(weightDone) / float(weightTotal) * 100);
+  return progressPercent;
+}
+
 std::string Proc::getXMLState(int numId)
 {
   if(YACS::ENGINE::Node::idMap.count(numId) == 0)
@@ -177,7 +274,7 @@ std::string Proc::getInPortValue(int nodeNumId, std::string portName)
     {
       YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
       InputPort * inputPort = node->getInputPort(portName);
-      return inputPort->dump();
+      return inputPort->getAsString();
     }
   catch(YACS::Exception& ex)
     {
@@ -187,6 +284,48 @@ std::string Proc::getInPortValue(int nodeNumId, std::string portName)
     }
 }
 
+std::string Proc::setInPortValue(std::string nodeName, std::string portName, std::string value)
+{
+  DEBTRACE("Proc::setInPortValue " << nodeName << " " << portName << " " << value);
+
+  try
+    {
+      YACS::ENGINE::Node* node = YACS::ENGINE::Proc::nodeMap[nodeName];
+      YACS::ENGINE::InputPort* inputPort = node->getInputPort(portName);
+
+      switch (inputPort->edGetType()->kind())
+        {
+          case Double:
+            {
+              double val = atof(value.c_str());
+              inputPort->edInit(val);
+            }
+          case Int:
+            {
+              int val = atoi(value.c_str());
+              inputPort->edInit(val);
+            }
+          case String:
+            inputPort->edInit(value.c_str());
+          case Bool:
+            {
+              bool val = (! value.compare("False") ) && (! value.compare("0") );
+              inputPort->edInit(val);
+            }
+          default:
+            DEBTRACE("Proc::setInPortValue: filtered type: " << inputPort->edGetType()->kind());
+        }
+      return value;
+    }
+  catch(YACS::Exception& ex)
+    {
+      DEBTRACE("Proc::setInPortValue " << ex.what());
+      stringstream msg;
+      msg << "<value><error>" << ex.what() << "</error></value>";
+      return msg.str();
+    }
+}
+
 std::string Proc::getOutPortValue(int nodeNumId, std::string portName)
 {
   DEBTRACE("Proc::getOutPortValue " << nodeNumId << " " << portName);
@@ -200,7 +339,7 @@ std::string Proc::getOutPortValue(int nodeNumId, std::string portName)
     {
       YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId];
       OutputPort * outputPort = node->getOutputPort(portName);
-      return outputPort->dump();
+      return outputPort->getAsString();
     }
   catch(YACS::Exception& ex)
     {
@@ -313,3 +452,197 @@ void Proc::modified()
     edUpdateState();
 }
 
+//! Save Proc in XML schema file
+/*!
+ * \param xmlSchemaFile: the file name
+ */
+void Proc::saveSchema(const std::string& xmlSchemaFile)
+{
+  VisitorSaveSchema vss(this);
+  vss.openFileSchema(xmlSchemaFile);
+  accept(&vss);
+  vss.closeFileSchema();
+}
+
+//! Save Proc state in XML state file
+/*!
+ * \param xmlStateFile: the file name
+ */
+void Proc::saveState(const std::string& xmlStateFile)
+{
+  VisitorSaveState vst(this);
+  vst.openFileDump(xmlStateFile);
+  accept(&vst);
+  vst.closeFileDump();
+}
+
+void Proc::removeContainers()
+{
+  //get rid of containers in container map
+  std::map<std::string, Container*>::const_iterator it;
+  for(it=containerMap.begin();it!=containerMap.end();it++)
+    ((*it).second)->decrRef();
+  containerMap.clear();
+}
+
+//! Create a new Container and store it in containerMap
+/*!
+ * \param name: the container name and key in containerMap
+ * \param kind: the container kind (depends on runtime)
+ * \return the created Container
+ */
+Container *Proc::createContainer(const std::string& name, const std::string& kind)
+{
+  Container *co(getRuntime()->createContainer(kind));
+  co->setName(name);
+  if(containerMap.count(name)!=0)
+    containerMap[name]->decrRef();
+  containerMap[name]=co;
+  co->incrRef();
+  co->setProc(this);
+  return co;
+}
+
+//! Add a ComponentInstance into componentInstanceMap
+/*!
+ * If the name == "", the component instance is automatically named with a unique (in the Proc) name
+ *
+ * \param inst: the component instance
+ * \param name: the component instance name
+ * \param resetCtr: try to reuse instance number previously released, false by default
+ */
+void Proc::addComponentInstance(ComponentInstance* inst, const std::string& name, bool resetCtr)
+{
+  if(name != "")
+    {
+      inst->setName(name);
+      inst->setAnonymous(false);
+      if(componentInstanceMap.count(name)!=0)
+        componentInstanceMap[name]->decrRef();
+      componentInstanceMap[name]=inst;
+      inst->incrRef();
+    }
+  else
+    {
+      //automatic naming : componame_<_compoinstctr>
+      std::string instname;
+      std::string componame=inst->getCompoName();
+      if (resetCtr)
+        _compoinstctr = 0;        
+      while(1)
+        {
+          std::ostringstream buffer;
+          buffer << ++_compoinstctr;
+          instname=componame+"_"+buffer.str();
+          if(componentInstanceMap.count(instname)==0)
+            {
+              inst->setName(instname);
+              componentInstanceMap[instname]=inst;
+              inst->incrRef();
+              break;
+            }
+        }
+    }
+}
+
+//! Remove a componentInstance from the componentInstanceMap
+/*!
+ * To be used for a componentInstance with no service nodes referenced.
+ *
+ * \param inst: the component instance
+ */
+void Proc::removeComponentInstance(ComponentInstance* inst)
+{
+  if (componentInstanceMap.count(inst->getInstanceName()))
+    {
+      componentInstanceMap.erase(inst->getInstanceName());
+      inst->decrRef();
+    }
+}
+
+//! Remove a container from the containerMap
+/*!
+ * To be used for a container with no componentInstance referenced.
+ *
+ * \param cont: the container
+ */
+void Proc::removeContainer(Container* cont)
+{
+  if (containerMap.count(cont->getName()))
+    {
+      containerMap.erase(cont->getName());
+      cont->decrRef();
+    }
+}
+
+//! Create a new ComponentInstance and add it into componentInstanceMap
+/*!
+ * If the name == "", the component instance is automatically named with a unique (in the Proc) name
+ *
+ * \param componame: the component name
+ * \param name: the component instance name
+ * \param kind: the component instance kind (depends on runtime)
+ * \return the created ComponentInstance
+ */
+ComponentInstance* Proc::createComponentInstance(const std::string& componame, const std::string& name,const std::string& kind)
+{
+  ComponentInstance* inst=  getRuntime()->createComponentInstance(componame,kind);
+  addComponentInstance(inst,name);
+  return inst;
+}
+
+//! Return the proc (this)
+Proc* Proc::getProc()
+{
+  return this;
+}
+
+//! Return the proc (this)
+const Proc * Proc::getProc() const
+{
+  return this;
+}
+
+/*!
+ * This method is useful if this has been modified recursively and an update is needed between all the
+ * containers and components refered by children and little children and maps.
+ */
+void Proc::updateContainersAndComponents()
+{
+  std::map<std::string, Container*> myContainerMap;
+  std::map<std::string, ComponentInstance*> myComponentInstanceMap;
+  DeploymentTree treeToDup(getDeploymentTree());
+  vector<Container *> conts(treeToDup.getAllContainers());
+  for(vector<Container *>::const_iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
+    {
+      Container *tmp(*iterCt);
+      if(tmp)
+        {
+          if(myContainerMap.find(tmp->getName())!=myContainerMap.end())
+            {
+              std::ostringstream oss; oss << "Proc::updateContainersAndComponents : more than one container instance with name \"" << tmp->getName() << "\" !";
+              throw YACS::Exception(oss.str());
+            }
+          myContainerMap[tmp->getName()]=tmp;
+          tmp->incrRef();
+        }
+      vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
+      for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
+        {
+          ComponentInstance *tmp2(*iterCp);
+          if(tmp2)
+            {
+              if(myComponentInstanceMap.find(tmp2->getCompoName())!=myComponentInstanceMap.end())
+                {
+                  std::ostringstream oss; oss << "Proc::updateContainersAndComponents : more than one component instance with name \"" << tmp2->getCompoName() << "\" !";
+                  throw YACS::Exception(oss.str());
+                }
+            }
+          myComponentInstanceMap[tmp2->getCompoName()]=tmp2;
+          tmp2->incrRef();
+        }
+    }
+  removeContainers();
+  containerMap=myContainerMap;
+  componentInstanceMap=myComponentInstanceMap;
+}