Salome HOME
b1ca2d285360c2bd568bb326c18f1ff2491e9b9e
[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 WIN32
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       _procRef->addObserver(_observerRef, _serv->getEngineId((*it)->getNumId()) , "progress");
396     }
397   _procRef->addObserver(_observerRef, _serv->getEngineId(_proc->getNumId()) , "executor"); 
398 }
399
400
401
402 void GuiExecutor::setEngineRef(YACS_ORB::YACS_Gen_ptr ref)
403 {
404   DEBTRACE("GuiExecutor::setEngineRef");
405   _engineRef = ref;
406 }
407
408 std::string GuiExecutor::getErrorDetails(YACS::ENGINE::Node* node)
409 {
410   DEBTRACE("GuiExecutor::getErrorDetails");
411   if (_serv)
412   {
413     int engineId=_serv->getEngineId(node->getNumId());
414     return _procRef->getErrorDetails(engineId);
415   }
416   return "---";
417 }
418
419 std::string GuiExecutor::getErrorReport(YACS::ENGINE::Node* node)
420 {
421   DEBTRACE("GuiExecutor::getErrorReport");
422   if (_serv)
423   {
424     int engineId=_serv->getEngineId(node->getNumId());
425     return _procRef->getErrorReport(engineId);
426   }
427   return "---";
428 }
429
430 std::string GuiExecutor::getContainerLog()
431 {
432   DEBTRACE("GuiExecutor::getContainerLog");
433   std::string msg="";
434   if (!CORBA::is_nil(_engineRef))
435     {
436       Engines::Container_var cont= _engineRef->GetContainerRef();
437       CORBA::String_var logname = cont->logfilename();
438       DEBTRACE(logname);
439       msg=logname;
440       std::string::size_type pos = msg.find(":");
441       msg=msg.substr(pos+1);
442     }
443   return msg;
444 }
445
446 std::string GuiExecutor::getContainerLog(YACS::ENGINE::Node* node)
447 {
448   DEBTRACE("GuiExecutor::getContainerLog(YACS::ENGINE::Node* node)");
449   std::string msg;
450   if (_serv)
451     {
452       int engineId=_serv->getEngineId(node->getNumId());
453       CORBA::String_var logname = _procRef->getContainerLog(engineId);
454       msg=logname;
455       std::string::size_type pos = msg.find(":");
456       msg=msg.substr(pos+1);
457     }
458   return msg;
459 }
460
461 void GuiExecutor::shutdownProc()
462 {
463   DEBTRACE("GuiExecutor::shutdownProc " << _shutdownLevel << "," << _isRunning);
464   checkEndOfDataflow();
465   if (!_isRunning)
466     _procRef->shutdownProc(_shutdownLevel);
467 }
468
469 void GuiExecutor::setInPortValue(YACS::ENGINE::DataPort* port, std::string value)
470 {
471   DEBTRACE("GuiExecutor::setInPortValue");
472
473   YACS::ENGINE::Node* node = port->getNode();
474   YACS::ENGINE::ComposedNode* rootNode = node->getRootNode();
475
476   std::string nodeName;
477   if(rootNode == node)
478     nodeName = node->getName();
479   else
480     nodeName = rootNode->getChildName(node);
481
482   std::string msg = _procRef->setInPortValue(nodeName.c_str(), port->getName().c_str(), value.c_str());
483 }
484
485 bool GuiExecutor::event(QEvent *e)
486 {
487   DEBTRACE("GuiExecutor::event");
488   YACSEvent *yev = dynamic_cast<YACSEvent*>(e);
489   if (!yev) return false;
490   int numid = yev->getYACSEvent().first;
491   string event = yev->getYACSEvent().second;
492   DEBTRACE("<" << numid << "," << event << ">");
493   if (!_context)
494     {
495       DEBTRACE("context closed");
496       return true;
497     }
498   if (event == "executor") // --- Executor notification: state
499     {
500       int execState = _procRef->getExecutorState();
501       list<string> nextSteps;
502       if ((execState == YACS::WAITINGTASKS) || (execState == YACS::PAUSED))
503         {
504           YACS_ORB::stringArray_var nstp = _procRef->getTasksToLoad();
505           for (CORBA::ULong i=0; i<nstp->length(); i++)
506             nextSteps.push_back(nstp[i].in());
507           if (execState == YACS::PAUSED)
508             _isSuspended = true;
509         }
510       SubjectProc *sproc = _context->getSubjectProc();
511       sproc->update(YACS::HMI::UPDATEPROGRESS, execState, sproc);
512     }
513   else // --- Node notification
514     {
515       if (! _serv->_engineToGuiMap.count(numid))
516         return true;
517       int state = _procRef->getNodeState(numid);
518       int iGui = _serv->_engineToGuiMap[numid];
519       YASSERT(_context->_mapOfExecSubjectNode.count(iGui));
520       SubjectNode *snode = _context->_mapOfExecSubjectNode[iGui];
521       DEBTRACE("node " << snode->getName() << " state=" << state);
522
523       if (event == "progress") { // --- Update progress bar
524         std::string progress = _procRef->getNodeProgress(numid);
525         snode->setProgress( progress );
526         snode->update(YACS::HMI::PROGRESS, state, snode);
527       }
528       else { // --- Update node ports
529         YACS::ENGINE::Node *node = snode->getNode();
530         list<InputPort*> inports = node->getLocalInputPorts();
531         list<InputPort*>::iterator iti = inports.begin();
532         for ( ; iti != inports.end(); ++iti)
533           {
534             string val = _procRef->getInPortValue(numid, (*iti)->getName().c_str());
535             DEBTRACE("node " << snode->getName() << " inport " << (*iti)->getName() 
536                      << " value " << val);
537             YASSERT(_context->_mapOfSubjectDataPort.count(*iti));
538             SubjectDataPort* port = _context->_mapOfSubjectDataPort[*iti];
539             port->setExecValue(val);
540             port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
541           }
542         list<OutputPort*> outports = node->getLocalOutputPorts();
543         list<OutputPort*>::iterator ito = outports.begin();
544         for ( ; ito != outports.end(); ++ito)
545           {
546             string val = _procRef->getOutPortValue(numid, (*ito)->getName().c_str());
547             DEBTRACE("node " << snode->getName() << " outport " << (*ito)->getName() 
548                      << " value " << val);
549             YASSERT(_context->_mapOfSubjectDataPort.count(*ito));
550             SubjectDataPort* port = _context->_mapOfSubjectDataPort[*ito];
551             port->setExecValue(val);
552             port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
553           }
554         snode->update(YACS::HMI::UPDATEPROGRESS, state, snode);
555       }
556    }
557
558   return true;
559 }
560
561 void GuiExecutor::setBPList()
562 {
563   DEBTRACE("GuiExecutor::setBPList");
564   if (_isRunning)
565   {
566     YACS_ORB::stringArray listOfBreakPoints;
567     listOfBreakPoints.length(_breakpointList.size());
568     int i=0;
569     for (list<string>::iterator it = _breakpointList.begin(); it != _breakpointList.end(); ++it)
570       listOfBreakPoints[i++] = (*it).c_str();
571     _procRef->setListOfBreakPoints(listOfBreakPoints);
572   }
573 }
574
575 YACS::ExecutorState GuiExecutor::updateSchema(string jobState)
576 {
577   YACS::ExecutorState execState = YACS::NOTYETINITIALIZED;
578
579   int numid;
580   int state;
581   std::list<Node*> aNodeSet = _proc->getAllRecursiveConstituents();
582   for ( std::list<Node*>::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ){
583
584     numid = (*it)->getNumId();
585
586     state = _proc->getNodeState(numid);
587     SubjectNode *snode = _context->_mapOfExecSubjectNode[numid];
588
589     YACS::ENGINE::Node *node = snode->getNode();
590     list<InputPort*> inports = node->getLocalInputPorts();
591     list<InputPort*>::iterator iti = inports.begin();
592     for ( ; iti != inports.end(); ++iti)
593       {
594         string val = _proc->getInPortValue(numid, (*iti)->getName().c_str());
595         YASSERT(_context->_mapOfSubjectDataPort.count(*iti));
596         SubjectDataPort* port = _context->_mapOfSubjectDataPort[*iti];
597         port->setExecValue(val);
598         port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
599       }
600     list<OutputPort*> outports = node->getLocalOutputPorts();
601     list<OutputPort*>::iterator ito = outports.begin();
602     for ( ; ito != outports.end(); ++ito)
603       {
604         string val = _proc->getOutPortValue(numid, (*ito)->getName().c_str());
605         YASSERT(_context->_mapOfSubjectDataPort.count(*ito));
606         SubjectDataPort* port = _context->_mapOfSubjectDataPort[*ito];
607         port->setExecValue(val);
608         port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
609       }
610     snode->update(YACS::HMI::UPDATEPROGRESS, state, snode);
611   }
612   state = _proc->getRootNode()->getEffectiveState();
613   switch(state){
614   case YACS::LOADED:
615   case YACS::ACTIVATED:
616     if(jobState!="RUNNING")
617       execState = YACS::FINISHED;
618     else
619       execState = YACS::RUNNING;
620     break;
621   case YACS::FAILED:
622   case YACS::DONE:
623     execState = YACS::FINISHED;
624     break;
625   case YACS::SUSPENDED:
626     execState = YACS::PAUSED;
627     break;
628   }
629   SubjectProc *sproc = _context->getSubjectProc();
630   sproc->update(YACS::HMI::UPDATEPROGRESS, execState, sproc);
631
632   return execState;
633 }