Salome HOME
Retrieve state of ForEachLoop node even in case of failure.
authorAnthony Geay <anthony.geay@edf.fr>
Fri, 16 Jan 2015 17:10:25 +0000 (18:10 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Thu, 22 Jan 2015 09:11:03 +0000 (10:11 +0100)
src/engine/Any.cxx
src/engine/Any.hxx
src/engine/Executor.hxx
src/engine/ForEachLoop.cxx
src/engine/ForEachLoop.hxx
src/engine_swig/pilot.i

index 0ca4b843a4d2f1c2047761e45642dd3d527868e3..e062e0111149f60e74711634007b9937b1122334 100644 (file)
@@ -28,6 +28,9 @@
 using namespace YACS::ENGINE;
 using namespace std;
 
+// forbidden value int=-269488145 double=-1.54947e+231 bool=239
+const char SeqAlloc::DFT_CHAR_VAR=-17;//0xEF
+
 StringOnHeap::StringOnHeap(const char *val):_dealloc(0),_str(strdup(val))
 {
 }
@@ -382,7 +385,7 @@ void SeqAlloc::initCoarseMemory(char *mem, unsigned int size, Deallocator deallo
         memcpy(_start,mem,sizeInByte);
       else
         {
-          for(unsigned int i=0;i<sizeInByte;i++) _start[i]=0;
+          for(unsigned int i=0;i<sizeInByte;i++) _start[i]=DFT_CHAR_VAR;// see getSetItems
         }
     }
   _finish=_start+sizeInByte;
@@ -439,6 +442,20 @@ unsigned int SeqAlloc::size() const
   return (_finish-_start)/_sizeOf1Elm;
 }
 
+std::vector<unsigned int> SeqAlloc::getSetItems() const
+{
+  std::vector<unsigned int> ret;
+  unsigned int sz(size());
+  for(unsigned int i=0;i<sz;i++)
+    {
+      const char *pt(_start+i*_sizeOf1Elm);
+      for(unsigned j=0;j<_sizeOf1Elm && *pt==DFT_CHAR_VAR;j++,pt++); //see initCoarseMemory
+      if(pt!=_start+(i+1)*_sizeOf1Elm)
+        ret.push_back(i);
+    }
+  return ret;
+}
+
 void SequenceAny::clear()
 {
   for (char *cur=_alloc._start;cur!=_alloc._finish;cur+=_alloc._sizeOf1Elm)
@@ -539,6 +556,19 @@ Any *SequenceAny::clone() const
   return new SequenceAny(*this);
 }
 
+SequenceAny *SequenceAny::removeUnsetItemsFromThis() const
+{
+  std::vector<unsigned int> its(getSetItems());
+  std::size_t sz(its.size());
+  SequenceAny *ret(SequenceAny::New(getType()->contentType(),sz));
+  for(std::size_t i=0;i<sz;i++)
+    {
+      AnyPtr obj((*this)[its[i]]);
+      ret->setEltAtRank(i,obj);
+    }
+  return ret;
+}
+
 SequenceAny *SequenceAny::New(const TypeCode *typeOfContent)
 {
   if(typeOfContent->kind() == Objref)
index cc9a51c9df6f5994f3b8fdf9cb9ce9ec74cb35b7..3f4560f1b2cf04dcf0c7c253f3fe8d0cdeabab18 100644 (file)
@@ -162,6 +162,8 @@ namespace YACS
       void destroy(char *pt, const TypeCode *tc);
       void deallocate(char *pt);
       unsigned int size() const;
+      std::vector<unsigned int> getSetItems() const;
+      static const char DFT_CHAR_VAR;
     };
     
     class YACSLIBENGINE_EXPORT ComposedAny : public Any
@@ -201,6 +203,8 @@ namespace YACS
       static SequenceAny *New(const TypeCode *typeOfContent, unsigned lgth);
       template<class T>
       static SequenceAny *New(T *val, unsigned int lgth, Deallocator deAlloc);
+      std::vector<unsigned int> getSetItems() const { return _alloc.getSetItems(); }
+      SequenceAny *removeUnsetItemsFromThis() const;
     protected:
       void putMyReprAtPlace(char *data) const;
       static void putReprAtPlace(char *data, const char *src, const TypeCode *type, bool deepCpy);
index bf606ea6e41069b209461811e7cd52074d4d896b..fedd17196307f5b1f778fe0827bdb15af75e4674 100644 (file)
@@ -114,6 +114,7 @@ namespace YACS
       void waitPause();
       static int _maxThreads;
       static size_t _threadStackSize;
+      YACS::BASES::Mutex& getTheMutexForSchedulerUpdate() { return _mutexForSchedulerUpdate; }
     protected:
       bool checkBreakPoints();
       void waitResume();
index 1dc70d97e8421ef8467807a75868c9c7a62cf46c..325d05801544b40168e23fa026d23eef62b16c53 100644 (file)
@@ -21,6 +21,9 @@
 #include "TypeCode.hxx"
 #include "Visitor.hxx"
 #include "ComposedNode.hxx"
+#include "Executor.hxx"
+#include "AutoLocker.hxx"
+
 #include <iostream>
 #include <sstream>
 
@@ -852,3 +855,35 @@ std::string ForEachLoop::getProgress() const
     aProgress << "0";
   return aProgress.str();
 }
+
+/*!
+ * This method allows to retrieve the state of \a this during execution or after. This method works even if this is \b NOT complete, or during execution or after a failure in \a this.
+ * The typical usage of this method is to retrieve the results of items that passed successfully to avoid to lose all of them if only one fails.
+ * This method has one input \a execut and 3 outputs.
+ *
+ * \param [in] execut - The single input is for threadsafety reasons because this method can be called safely during the execution of \a this.
+ * \param [out] outputs - For each output ports in \a this linked with nodes sharing the same father than \a this the passed results are stored.
+ *                        All of the items in \a outputs have the same size.
+ * \param [out] nameOfOutputs - The array with same size than \a outputs, that tells for each item in outputs the output port it refers to.
+ * \return the list of ids among \c this->edGetSeqOfSamplesPort() that run successfully. The length of this returned array will be the length of all
+ *         SequenceAny objects contained in \a outputs.
+ *
+ * \sa edGetSeqOfSamplesPort
+ */
+std::vector<unsigned int> ForEachLoop::getPassedResults(Executor *execut, std::vector<SequenceAny *>& outputs, std::vector<std::string>& nameOfOutputs) const
+{
+  YACS::BASES::AutoLocker<YACS::BASES::Mutex> alck(&(execut->getTheMutexForSchedulerUpdate()));
+  if(_execVals.empty())
+    return std::vector<unsigned int>();
+  if(_execOutGoingPorts.empty())
+    return std::vector<unsigned int>();
+  std::size_t sz(_execVals.size()); outputs.resize(sz); nameOfOutputs.resize(sz);
+  const std::vector<AnyInputPort *>& ports(_execOutGoingPorts[0]);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      outputs[i]=_execVals[i]->removeUnsetItemsFromThis();
+      nameOfOutputs[i]=ports[i]->getName();
+    }
+  return _execVals[0]->getSetItems();
+}
+
index 8181cd8aa9a29daebfc1df1d29162da7c2f8e6b0..f390dcd363a312a2a76322e1a23b070bb7eab479 100644 (file)
@@ -123,6 +123,8 @@ namespace YACS
       static const char NAME[];
     };
 
+    class Executor;
+
     class YACSLIBENGINE_EXPORT ForEachLoop : public DynParaLoop
     {
       friend class SplitterNode;
@@ -169,6 +171,9 @@ namespace YACS
       virtual std::string typeName() {return "YACS__ENGINE__ForEachLoop";}
       virtual void resetState(int level);
       std::string getProgress() const;
+#ifndef SWIG
+      std::vector<unsigned int> getPassedResults(Executor *execut, std::vector<SequenceAny *>& outputs, std::vector<std::string>& nameOfOutputs) const;
+#endif
     protected:
       Node *simpleClone(ComposedNode *father, bool editionOnly=true) const;
       void checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
index 6262f477304eb9a88bfe601602d70b5252dc25f6..4b58f258e4ed61b8dab4ce33ef4ffa66c7123a05 100644 (file)
@@ -189,6 +189,8 @@ REFCOUNT_TEMPLATE(CompoInstmap,YACS::ENGINE::ComponentInstance)
 %newobject *::createStructTc;
 %newobject *::createType;
 
+%newobject YACS::ENGINE::SequenceAny::removeUnsetItemsFromThis;
+
 %newobject YACS::ENGINE::TypeCode::interfaceTc;
 %newobject YACS::ENGINE::TypeCode::sequenceTc;
 %newobject YACS::ENGINE::TypeCode::structTc;
@@ -371,6 +373,14 @@ EXCEPTION(YACS::ENGINE::ExecutorSwig::waitPause)
   }
 }
 
+%extend YACS::ENGINE::Any
+{
+  PyObject *getPyObj()
+  {
+    return (PyObject *)getRuntime()->convertNeutral(const_cast<YACS::ENGINE::TypeCode *>(self->getType()),self);
+  }
+}
+
 %newobject YACS::ENGINE::SequenceAny::__getitem__;
 %extend YACS::ENGINE::SequenceAny
 {
@@ -397,3 +407,30 @@ EXCEPTION(YACS::ENGINE::ExecutorSwig::waitPause)
     return a;
   }
 }
+
+%extend YACS::ENGINE::ForEachLoop
+{
+  PyObject *getPassedResults(Executor *execut) const
+  {
+    std::vector<SequenceAny *> ret1;
+    std::vector<std::string> ret2;
+    std::vector<unsigned int> ret0(self->getPassedResults(execut,ret1,ret2));
+    PyObject *ret(PyTuple_New(3));
+    // param 0
+    PyObject *ret0Py(PyList_New(ret0.size()));
+    for(std::size_t i=0;i<ret0.size();i++)
+      PyList_SetItem(ret0Py,i,PyInt_FromLong(ret0[i]));
+    PyTuple_SetItem(ret,0,ret0Py);
+    // param 1
+    PyObject *ret1Py(PyList_New(ret1.size()));
+    for(std::size_t i=0;i<ret1.size();i++)
+      PyList_SetItem(ret1Py,i,SWIG_NewPointerObj(SWIG_as_voidptr(ret1[i]),SWIGTYPE_p_YACS__ENGINE__SequenceAny, SWIG_POINTER_OWN | 0 ));
+    PyTuple_SetItem(ret,1,ret1Py);
+    // param 2
+    PyObject *ret2Py(PyList_New(ret2.size()));
+    for(std::size_t i=0;i<ret2.size();i++)
+      PyList_SetItem(ret2Py,i,PyString_FromString(ret2[i].c_str()));
+    PyTuple_SetItem(ret,2,ret2Py);
+    return ret;
+  }
+}