Salome HOME
Merge from V6_main 01/04/2013
[modules/yacs.git] / src / genericgui / GuiExecutor.cxx
1 // Copyright (C) 2006-2013  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.
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 <Python.h>
21 #include "SALOME_LifeCycleCORBA.hxx"
22 #include "SALOME_NamingService.hxx"
23
24 #include "GuiExecutor.hxx"
25 #include "GuiObserver_i.hxx"
26 #include "QtGuiContext.hxx"
27
28 #include "RuntimeSALOME.hxx"
29
30 #include "Proc.hxx"
31 #include "Node.hxx"
32 #include "InputPort.hxx"
33 #include "OutputPort.hxx"
34 #include "Executor.hxx"
35
36
37 //#define _DEVDEBUG_
38 #include "YacsTrace.hxx"
39
40 using namespace std;
41 using namespace YACS::HMI;
42 using namespace YACS::ENGINE;
43
44 GuiExecutor::GuiExecutor(YACS::ENGINE::Proc* proc)
45 {
46   DEBTRACE("GuiExecutor::GuiExecutor");
47
48   _proc = proc;
49   _context = QtGuiContext::getQtCurrent();
50
51   _engineRef = YACS_ORB::YACS_Gen::_nil();
52   _procRef = YACS_ORB::ProcExec::_nil();
53   _observerRef = YACS_ORB::Observer::_nil();
54
55   _execMode = YACS::CONTINUE;
56   _serv = 0;
57
58   _isRunning = false;
59   _isSuspended = false;
60   _isStopOnError = false;
61   _shutdownLevel=1;
62
63   _loadStateFile = "";
64   _breakpointList.clear();
65 }
66
67
68 GuiExecutor::~GuiExecutor()
69 {
70   DEBTRACE("GuiExecutor::~GuiExecutor");
71 }
72
73 void GuiExecutor::closeContext()
74 {
75   DEBTRACE("GuiExecutor::closeContext");
76   _context = 0;
77 }
78
79 void GuiExecutor::startResumeDataflow(bool initialize)
80 {
81   DEBTRACE("GuiExecutor::runDataflow " << initialize);
82   if (!_context)
83     {
84       DEBTRACE("context closed");
85       return;
86     }
87   if (CORBA::is_nil(_engineRef))
88     {
89       DEBTRACE("Create YACS ORB engine!");
90       YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
91       CORBA::ORB_ptr orb = runTime->getOrb();
92       SALOME_NamingService namingService(orb);
93       SALOME_LifeCycleCORBA lcc(&namingService);
94       ostringstream containerName;
95       containerName << "localhost/YACSContainer" << QtGuiContext::getQtCurrent()->getStudyId();
96       Engines::EngineComponent_var comp = lcc.FindOrLoad_Component(containerName.str().c_str(), "YACS" );
97       _engineRef =YACS_ORB::YACS_Gen::_narrow(comp);
98       YASSERT(!CORBA::is_nil(_engineRef));
99     }
100
101   checkEndOfDataflow(); // --- to allow change of the _isRunning state
102
103   if (_isRunning)
104     {
105       if (_isSuspended)
106         {
107           _procRef->setExecMode(getCurrentExecMode());
108           _procRef->resumeCurrentBreakPoint();
109           _isSuspended = false;
110         }
111       return;
112     }
113
114   _isRunning = true;
115
116   if (CORBA::is_nil(_procRef))
117     {
118       DEBTRACE("init _procRef");
119       _procRef = _engineRef->LoadProc(_context->getFileName().toAscii());
120       registerStatusObservers();
121       DEBTRACE("_procRef init");
122     }
123
124   YASSERT(!CORBA::is_nil(_procRef));
125
126   if (initialize)
127     _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
128   else
129     _procRef->setExecMode(getCurrentExecMode());
130   setBPList();
131
132   if (_loadStateFile.empty())
133     {
134       DEBTRACE("Run from scratch!");
135       _procRef->Run();
136     }
137   else
138     {
139       DEBTRACE("Run from STATE!");
140       try
141         {
142           _procRef->RunFromState(_loadStateFile.c_str());
143         }
144       catch (...)
145         {
146           DEBTRACE("Runtime error: execution from the loaded state failed")
147           return;
148         }
149     }
150 }
151
152 bool GuiExecutor::checkEndOfDataflow(bool display)
153 {
154   DEBTRACE("GuiExecutor::checkEndOfDataFlow");
155   if (_isRunning)
156     {
157       if (CORBA::is_nil(_procRef))
158         {
159           DEBTRACE("Runtime error: connection lost on a running scheme");
160           _isRunning = false;
161           return false;              
162         }
163       if (_procRef->isNotFinished())
164         {
165           DEBTRACE("Remote Execution Already running...");
166           return false;
167         }
168       else
169         {
170           _isRunning = false;
171           // --- TODO: cleaning on server ...
172         }
173     }
174   return true;
175 }
176
177 void GuiExecutor::killDataflow()
178 {
179   DEBTRACE("GuiExecutor::killDataflow");
180   if (_isRunning)
181     _procRef->stopExecution();
182 }
183
184 void GuiExecutor::suspendDataflow()
185 {
186   DEBTRACE("GuiExecutor::suspendDataflow");
187   if (_isRunning)
188     _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
189 }
190
191 void GuiExecutor::resumeDataflow()
192 {
193   DEBTRACE("GuiExecutor::resumeDataflow");
194   if (_isRunning)
195     {
196       _procRef->setExecMode(getCurrentExecMode());
197       _procRef->resumeCurrentBreakPoint();
198     }
199 }
200
201 void GuiExecutor::stopDataflow()
202 {
203   DEBTRACE("GuiExecutor::stopDataflow");
204   if (_isRunning)
205     _procRef->stopExecution();
206 }
207
208 void GuiExecutor::resetDataflow()
209 {
210   DEBTRACE("GuiExecutor::resetDataflow");
211   //update _isRunning
212   checkEndOfDataflow();
213   if (_isRunning)
214     _procRef->stopExecution();
215   checkEndOfDataflow();
216
217   if (!_isRunning)
218     {
219       _isRunning = true;
220       _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
221       //full reset: set all nodes in error to READY state and start execution
222       _procRef->RestartFromState("");
223     }
224 }
225
226   
227 void GuiExecutor::setStepByStepMode()
228 {
229   DEBTRACE("GuiExecutor::setStepByStepMode");
230   _execMode = YACS::STEPBYSTEP;
231   if (_isRunning)
232     _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
233 }
234
235 void GuiExecutor::setContinueMode()
236 {
237   DEBTRACE("GuiExecutor::setContinueMode");
238   _execMode = YACS::CONTINUE;
239   if (_isRunning)
240     _procRef->setExecMode(YACS_ORB::CONTINUE);
241 }
242
243 void GuiExecutor::setBreakpointMode()
244 {
245   DEBTRACE("GuiExecutor::setBreakpointMode");
246   _execMode = YACS::STOPBEFORENODES;
247   if (_isRunning)
248     _procRef->setExecMode(YACS_ORB::STOPBEFORENODES);
249 }
250
251 void GuiExecutor::setStopOnError(bool aMode)
252 {
253   DEBTRACE("GuiExecutor::setStopOnError " << aMode);
254   if (_isRunning)
255     {
256 #ifdef WNT
257       _procRef->setStopOnError(aMode, (getenv("TEMP") + string("\\dumpStateOnError_") + getenv("USER") + string(".xml")).c_str());
258 #else
259       _procRef->setStopOnError(aMode, (string("/tmp/dumpStateOnError_") + getenv("USER") + string(".xml")).c_str());
260 #endif
261       _isStopOnError = true;
262     }
263 }
264
265 void GuiExecutor::unsetStopOnError()
266 {
267   DEBTRACE("GuiExecutor::unsetStopOnError");
268   if (_isRunning)
269     {
270       _procRef->unsetStopOnError();
271       _isStopOnError = false;
272     }
273 }
274
275
276 void GuiExecutor::saveState(const std::string& xmlFile)
277 {
278   DEBTRACE("GuiExecutor::saveState " << xmlFile);
279   bool StartFinish = (getExecutorState() == YACS::NOTYETINITIALIZED ||
280                       getExecutorState() == YACS::FINISHED);
281   if ( _isRunning ||
282        !(CORBA::is_nil(_procRef)) && StartFinish )
283     _procRef->saveState(xmlFile.c_str());
284 }
285
286 void GuiExecutor::setLoadStateFile(std::string xmlFile)
287 {
288   DEBTRACE("GuiExecutor::setLoadStateFile " << xmlFile);
289   _loadStateFile = xmlFile;
290 }
291
292   
293 YACS_ORB::executionMode GuiExecutor::getCurrentExecMode()
294 {
295   DEBTRACE("GuiExecutor::getCurrentExecMode");
296   switch (_execMode)
297     {
298     case YACS::CONTINUE: return YACS_ORB::CONTINUE;
299     case YACS::STEPBYSTEP: return YACS_ORB::STEPBYSTEP;
300     case YACS::STOPBEFORENODES: return YACS_ORB::STOPBEFORENODES;
301     default: return YACS_ORB::CONTINUE;
302     }
303 }
304
305 int GuiExecutor::getExecutorState()
306 {
307   DEBTRACE("GuiExecutor::getExecutorState");
308   if (_isRunning || !CORBA::is_nil(_procRef))
309     return _procRef->getExecutorState();
310   else if (CORBA::is_nil(_procRef))
311     return YACS::NOTYETINITIALIZED;
312   else
313     return YACS::FINISHED;
314 }
315
316   
317 void GuiExecutor::setBreakpointList(std::list<std::string> breakpointList)
318 {
319   DEBTRACE("GuiExecutor::setBreakpointList");
320   if (!_context)
321     {
322       DEBTRACE("context closed");
323       return;
324     }
325   _breakpointList.clear();
326   _breakpointList = breakpointList;
327   setBPList();
328   if ((_execMode == YACS::CONTINUE) && ! _breakpointList.empty())
329     {
330       _context->getGMain()->_breakpointsModeAct->setChecked(true);
331       setBreakpointMode();
332     }
333 }
334
335 void GuiExecutor::addBreakpoint(std::string breakpoint)
336 {
337   DEBTRACE("addBreakpoint " << breakpoint);
338   if (!_context)
339     {
340       DEBTRACE("context closed");
341       return;
342     }
343   _breakpointList.push_back(breakpoint);
344   setBPList();
345   if ((_execMode == YACS::CONTINUE) && ! _breakpointList.empty())
346     {
347       _context->getGMain()->_breakpointsModeAct->setChecked(true);
348       setBreakpointMode();
349     }
350 }
351
352 void GuiExecutor::removeBreakpoint(std::string breakpoint)
353 {
354   DEBTRACE("removeBreakpoint " << breakpoint);
355   _breakpointList.remove(breakpoint);
356   setBPList();
357 }
358
359 void GuiExecutor::setNextStepList(std::list<std::string> nextStepList)
360 {
361   DEBTRACE("GuiExecutor::setNextStepList");
362   if (_isRunning)
363     {
364       YACS_ORB::stringArray listOfNextStep;
365       listOfNextStep.length(nextStepList.size());
366       int i=0;
367       for (list<string>::iterator it = nextStepList.begin(); it != nextStepList.end(); ++it)
368         listOfNextStep[i++] = (*it).c_str();
369       _procRef->setStepsToExecute(listOfNextStep);
370     }
371 }
372
373 void GuiExecutor::registerStatusObservers()
374 {
375   DEBTRACE("GuiExecutor::registerStatusObservers");
376   if (CORBA::is_nil(_procRef))
377     {
378       DEBTRACE("Runtime error (yacsgui): Lost connection on YACS executor");
379       return;
380     }
381   if (CORBA::is_nil(_observerRef))
382     {
383       _serv = new GuiObserver_i(_proc);
384       _serv->SetImpl(this);
385       _observerRef = _serv->_this();
386     }
387   DEBTRACE("---");
388   _serv->SetRemoteProc(_procRef);
389   _serv->setConversion();
390   DEBTRACE("---");
391   std::list<Node*> aNodeSet = _proc->getAllRecursiveConstituents();
392   for ( std::list<Node*>::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ )
393     {
394       _procRef->addObserver(_observerRef, _serv->getEngineId((*it)->getNumId()) , "status");
395     }
396   _procRef->addObserver(_observerRef, _serv->getEngineId(_proc->getNumId()) , "executor"); 
397 }
398
399
400
401 void GuiExecutor::setEngineRef(YACS_ORB::YACS_Gen_ptr ref)
402 {
403   DEBTRACE("GuiExecutor::setEngineRef");
404   _engineRef = ref;
405 }
406
407 std::string GuiExecutor::getErrorDetails(YACS::ENGINE::Node* node)
408 {
409   DEBTRACE("GuiExecutor::getErrorDetails");
410   if (_serv)
411   {
412     int engineId=_serv->getEngineId(node->getNumId());
413     return _procRef->getErrorDetails(engineId);
414   }
415   return "---";
416 }
417
418 std::string GuiExecutor::getErrorReport(YACS::ENGINE::Node* node)
419 {
420   DEBTRACE("GuiExecutor::getErrorReport");
421   if (_serv)
422   {
423     int engineId=_serv->getEngineId(node->getNumId());
424     return _procRef->getErrorReport(engineId);
425   }
426   return "---";
427 }
428
429 std::string GuiExecutor::getContainerLog()
430 {
431   DEBTRACE("GuiExecutor::getContainerLog");
432   std::string msg="";
433   if (!CORBA::is_nil(_engineRef))
434     {
435       Engines::Container_var cont= _engineRef->GetContainerRef();
436       CORBA::String_var logname = cont->logfilename();
437       DEBTRACE(logname);
438       msg=logname;
439       std::string::size_type pos = msg.find(":");
440       msg=msg.substr(pos+1);
441     }
442   return msg;
443 }
444
445 std::string GuiExecutor::getContainerLog(YACS::ENGINE::Node* node)
446 {
447   DEBTRACE("GuiExecutor::getContainerLog(YACS::ENGINE::Node* node)");
448   std::string msg;
449   if (_serv)
450     {
451       int engineId=_serv->getEngineId(node->getNumId());
452       CORBA::String_var logname = _procRef->getContainerLog(engineId);
453       msg=logname;
454       std::string::size_type pos = msg.find(":");
455       msg=msg.substr(pos+1);
456     }
457   return msg;
458 }
459
460 void GuiExecutor::shutdownProc()
461 {
462   DEBTRACE("GuiExecutor::shutdownProc " << _shutdownLevel << "," << _isRunning);
463   checkEndOfDataflow();
464   if (!_isRunning)
465     _procRef->shutdownProc(_shutdownLevel);
466 }
467
468 void GuiExecutor::setInPortValue(YACS::ENGINE::DataPort* port, std::string value)
469 {
470   DEBTRACE("GuiExecutor::setInPortValue");
471
472   YACS::ENGINE::Node* node = port->getNode();
473   YACS::ENGINE::ComposedNode* rootNode = node->getRootNode();
474
475   std::string nodeName;
476   if(rootNode == node)
477     nodeName = node->getName();
478   else
479     nodeName = rootNode->getChildName(node);
480
481   std::string msg = _procRef->setInPortValue(nodeName.c_str(), port->getName().c_str(), value.c_str());
482 }
483
484 bool GuiExecutor::event(QEvent *e)
485 {
486   DEBTRACE("GuiExecutor::event");
487   YACSEvent *yev = dynamic_cast<YACSEvent*>(e);
488   if (!yev) return false;
489   int numid = yev->getYACSEvent().first;
490   string event = yev->getYACSEvent().second;
491   DEBTRACE("<" << numid << "," << event << ">");
492   if (!_context)
493     {
494       DEBTRACE("context closed");
495       return true;
496     }
497   if (event == "executor") // --- Executor notification: state
498     {
499       int execState = _procRef->getExecutorState();
500       list<string> nextSteps;
501       if ((execState == YACS::WAITINGTASKS) || (execState == YACS::PAUSED))
502         {
503           YACS_ORB::stringArray_var nstp = _procRef->getTasksToLoad();
504           for (CORBA::ULong i=0; i<nstp->length(); i++)
505             nextSteps.push_back(nstp[i].in());
506           if (execState == YACS::PAUSED)
507             _isSuspended = true;
508         }
509       SubjectProc *sproc = _context->getSubjectProc();
510       sproc->update(YACS::HMI::UPDATEPROGRESS, execState, sproc);
511     }
512   else // --- Node notification
513     {
514       if (! _serv->_engineToGuiMap.count(numid))
515         return true;
516       int state = _procRef->getNodeState(numid);
517       int iGui = _serv->_engineToGuiMap[numid];
518       YASSERT(_context->_mapOfExecSubjectNode.count(iGui));
519       SubjectNode *snode = _context->_mapOfExecSubjectNode[iGui];
520       DEBTRACE("node " << snode->getName() << " state=" << state);
521
522       YACS::ENGINE::Node *node = snode->getNode();
523       list<InputPort*> inports = node->getLocalInputPorts();
524       list<InputPort*>::iterator iti = inports.begin();
525       for ( ; iti != inports.end(); ++iti)
526         {
527           string val = _procRef->getInPortValue(numid, (*iti)->getName().c_str());
528           DEBTRACE("node " << snode->getName() << " inport " << (*iti)->getName() 
529                    << " value " << val);
530           YASSERT(_context->_mapOfSubjectDataPort.count(*iti));
531           SubjectDataPort* port = _context->_mapOfSubjectDataPort[*iti];
532           port->setExecValue(val);
533           port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
534         }
535       list<OutputPort*> outports = node->getLocalOutputPorts();
536       list<OutputPort*>::iterator ito = outports.begin();
537       for ( ; ito != outports.end(); ++ito)
538         {
539           string val = _procRef->getOutPortValue(numid, (*ito)->getName().c_str());
540           DEBTRACE("node " << snode->getName() << " outport " << (*ito)->getName() 
541                    << " value " << val);
542           YASSERT(_context->_mapOfSubjectDataPort.count(*ito));
543           SubjectDataPort* port = _context->_mapOfSubjectDataPort[*ito];
544           port->setExecValue(val);
545           port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
546         }
547       snode->update(YACS::HMI::UPDATEPROGRESS, state, snode);
548    }
549
550   return true;
551 }
552
553 void GuiExecutor::setBPList()
554 {
555   DEBTRACE("GuiExecutor::setBPList");
556   if (_isRunning)
557   {
558     YACS_ORB::stringArray listOfBreakPoints;
559     listOfBreakPoints.length(_breakpointList.size());
560     int i=0;
561     for (list<string>::iterator it = _breakpointList.begin(); it != _breakpointList.end(); ++it)
562       listOfBreakPoints[i++] = (*it).c_str();
563     _procRef->setListOfBreakPoints(listOfBreakPoints);
564   }
565 }
566
567 YACS::ExecutorState GuiExecutor::updateSchema(string jobState)
568 {
569   YACS::ExecutorState execState = YACS::NOTYETINITIALIZED;
570
571   int numid;
572   int state;
573   std::list<Node*> aNodeSet = _proc->getAllRecursiveConstituents();
574   for ( std::list<Node*>::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ){
575
576     numid = (*it)->getNumId();
577
578     state = _proc->getNodeState(numid);
579     SubjectNode *snode = _context->_mapOfExecSubjectNode[numid];
580
581     YACS::ENGINE::Node *node = snode->getNode();
582     list<InputPort*> inports = node->getLocalInputPorts();
583     list<InputPort*>::iterator iti = inports.begin();
584     for ( ; iti != inports.end(); ++iti)
585       {
586         string val = _proc->getInPortValue(numid, (*iti)->getName().c_str());
587         YASSERT(_context->_mapOfSubjectDataPort.count(*iti));
588         SubjectDataPort* port = _context->_mapOfSubjectDataPort[*iti];
589         port->setExecValue(val);
590         port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
591       }
592     list<OutputPort*> outports = node->getLocalOutputPorts();
593     list<OutputPort*>::iterator ito = outports.begin();
594     for ( ; ito != outports.end(); ++ito)
595       {
596         string val = _proc->getOutPortValue(numid, (*ito)->getName().c_str());
597         YASSERT(_context->_mapOfSubjectDataPort.count(*ito));
598         SubjectDataPort* port = _context->_mapOfSubjectDataPort[*ito];
599         port->setExecValue(val);
600         port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
601       }
602     snode->update(YACS::HMI::UPDATEPROGRESS, state, snode);
603   }
604   state = _proc->getRootNode()->getEffectiveState();
605   switch(state){
606   case YACS::LOADED:
607   case YACS::ACTIVATED:
608     if(jobState!="RUNNING")
609       execState = YACS::FINISHED;
610     else
611       execState = YACS::RUNNING;
612     break;
613   case YACS::FAILED:
614   case YACS::DONE:
615     execState = YACS::FINISHED;
616     break;
617   case YACS::SUSPENDED:
618     execState = YACS::PAUSED;
619     break;
620   }
621   SubjectProc *sproc = _context->getSubjectProc();
622   sproc->update(YACS::HMI::UPDATEPROGRESS, execState, sproc);
623
624   return execState;
625 }