Salome HOME
Merge Qt5 porting.
[modules/yacs.git] / src / genericgui / GuiExecutor.cxx
1 // Copyright (C) 2006-2015  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 <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().toLatin1());
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     if ( !_procRef->saveState(xmlFile.c_str()) ) {
284       string what = "Impossible to open file for writing: " + xmlFile;
285       throw Exception(what);
286     }
287   }
288 }
289
290 void GuiExecutor::setLoadStateFile(std::string xmlFile)
291 {
292   DEBTRACE("GuiExecutor::setLoadStateFile " << xmlFile);
293   _loadStateFile = xmlFile;
294 }
295
296   
297 YACS_ORB::executionMode GuiExecutor::getCurrentExecMode()
298 {
299   DEBTRACE("GuiExecutor::getCurrentExecMode");
300   switch (_execMode)
301     {
302     case YACS::CONTINUE: return YACS_ORB::CONTINUE;
303     case YACS::STEPBYSTEP: return YACS_ORB::STEPBYSTEP;
304     case YACS::STOPBEFORENODES: return YACS_ORB::STOPBEFORENODES;
305     default: return YACS_ORB::CONTINUE;
306     }
307 }
308
309 int GuiExecutor::getExecutorState()
310 {
311   DEBTRACE("GuiExecutor::getExecutorState");
312   if (_isRunning || !CORBA::is_nil(_procRef))
313     return _procRef->getExecutorState();
314   else if (CORBA::is_nil(_procRef))
315     return YACS::NOTYETINITIALIZED;
316   else
317     return YACS::FINISHED;
318 }
319
320   
321 void GuiExecutor::setBreakpointList(std::list<std::string> breakpointList)
322 {
323   DEBTRACE("GuiExecutor::setBreakpointList");
324   if (!_context)
325     {
326       DEBTRACE("context closed");
327       return;
328     }
329   _breakpointList.clear();
330   _breakpointList = breakpointList;
331   setBPList();
332   if ((_execMode == YACS::CONTINUE) && ! _breakpointList.empty())
333     {
334       _context->getGMain()->_breakpointsModeAct->setChecked(true);
335       setBreakpointMode();
336     }
337 }
338
339 void GuiExecutor::addBreakpoint(std::string breakpoint)
340 {
341   DEBTRACE("addBreakpoint " << breakpoint);
342   if (!_context)
343     {
344       DEBTRACE("context closed");
345       return;
346     }
347   _breakpointList.push_back(breakpoint);
348   setBPList();
349   if ((_execMode == YACS::CONTINUE) && ! _breakpointList.empty())
350     {
351       _context->getGMain()->_breakpointsModeAct->setChecked(true);
352       setBreakpointMode();
353     }
354 }
355
356 void GuiExecutor::removeBreakpoint(std::string breakpoint)
357 {
358   DEBTRACE("removeBreakpoint " << breakpoint);
359   _breakpointList.remove(breakpoint);
360   setBPList();
361 }
362
363 void GuiExecutor::setNextStepList(std::list<std::string> nextStepList)
364 {
365   DEBTRACE("GuiExecutor::setNextStepList");
366   if (_isRunning)
367     {
368       YACS_ORB::stringArray listOfNextStep;
369       listOfNextStep.length(nextStepList.size());
370       int i=0;
371       for (list<string>::iterator it = nextStepList.begin(); it != nextStepList.end(); ++it)
372         listOfNextStep[i++] = (*it).c_str();
373       _procRef->setStepsToExecute(listOfNextStep);
374     }
375 }
376
377 void GuiExecutor::registerStatusObservers()
378 {
379   DEBTRACE("GuiExecutor::registerStatusObservers");
380   if (CORBA::is_nil(_procRef))
381     {
382       DEBTRACE("Runtime error (yacsgui): Lost connection on YACS executor");
383       return;
384     }
385   if (CORBA::is_nil(_observerRef))
386     {
387       _serv = new GuiObserver_i(_proc);
388       _serv->SetImpl(this);
389       _observerRef = _serv->_this();
390     }
391   DEBTRACE("---");
392   _serv->SetRemoteProc(_procRef);
393   _serv->setConversion();
394   DEBTRACE("---");
395   std::list<Node*> aNodeSet = _proc->getAllRecursiveConstituents();
396   for ( std::list<Node*>::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ )
397     {
398       _procRef->addObserver(_observerRef, _serv->getEngineId((*it)->getNumId()) , "status");
399       _procRef->addObserver(_observerRef, _serv->getEngineId((*it)->getNumId()) , "progress");
400     }
401   _procRef->addObserver(_observerRef, _serv->getEngineId(_proc->getNumId()) , "executor"); 
402 }
403
404
405
406 void GuiExecutor::setEngineRef(YACS_ORB::YACS_Gen_ptr ref)
407 {
408   DEBTRACE("GuiExecutor::setEngineRef");
409   _engineRef = ref;
410 }
411
412 std::string GuiExecutor::getErrorDetails(YACS::ENGINE::Node* node)
413 {
414   DEBTRACE("GuiExecutor::getErrorDetails");
415   if (_serv)
416   {
417     int engineId=_serv->getEngineId(node->getNumId());
418     return _procRef->getErrorDetails(engineId);
419   }
420   return "---";
421 }
422
423 std::string GuiExecutor::getErrorReport(YACS::ENGINE::Node* node)
424 {
425   DEBTRACE("GuiExecutor::getErrorReport");
426   if (_serv)
427   {
428     int engineId=_serv->getEngineId(node->getNumId());
429     return _procRef->getErrorReport(engineId);
430   }
431   return "---";
432 }
433
434 std::string GuiExecutor::getContainerLog()
435 {
436   DEBTRACE("GuiExecutor::getContainerLog");
437   std::string msg="";
438   if (!CORBA::is_nil(_engineRef))
439     {
440       Engines::Container_var cont= _engineRef->GetContainerRef();
441       CORBA::String_var logname = cont->logfilename();
442       DEBTRACE(logname);
443       msg=logname;
444       std::string::size_type pos = msg.find(":");
445       msg=msg.substr(pos+1);
446     }
447   return msg;
448 }
449
450 std::string GuiExecutor::getContainerLog(YACS::ENGINE::Node* node)
451 {
452   DEBTRACE("GuiExecutor::getContainerLog(YACS::ENGINE::Node* node)");
453   std::string msg;
454   if (_serv)
455     {
456       int engineId=_serv->getEngineId(node->getNumId());
457       CORBA::String_var logname = _procRef->getContainerLog(engineId);
458       msg=logname;
459       std::string::size_type pos = msg.find(":");
460       msg=msg.substr(pos+1);
461     }
462   return msg;
463 }
464
465 void GuiExecutor::shutdownProc()
466 {
467   DEBTRACE("GuiExecutor::shutdownProc " << _shutdownLevel << "," << _isRunning);
468   checkEndOfDataflow();
469   if (!_isRunning)
470     _procRef->shutdownProc(_shutdownLevel);
471 }
472
473 void GuiExecutor::setInPortValue(YACS::ENGINE::DataPort* port, std::string value)
474 {
475   DEBTRACE("GuiExecutor::setInPortValue");
476
477   YACS::ENGINE::Node* node = port->getNode();
478   YACS::ENGINE::ComposedNode* rootNode = node->getRootNode();
479
480   std::string nodeName;
481   if(rootNode == node)
482     nodeName = node->getName();
483   else
484     nodeName = rootNode->getChildName(node);
485
486   std::string msg = _procRef->setInPortValue(nodeName.c_str(), port->getName().c_str(), value.c_str());
487 }
488
489 bool GuiExecutor::event(QEvent *e)
490 {
491   DEBTRACE("GuiExecutor::event");
492   YACSEvent *yev = dynamic_cast<YACSEvent*>(e);
493   if (!yev) return false;
494   int numid = yev->getYACSEvent().first;
495   string event = yev->getYACSEvent().second;
496   DEBTRACE("<" << numid << "," << event << ">");
497   if (!_context)
498     {
499       DEBTRACE("context closed");
500       return true;
501     }
502   if (event == "executor") // --- Executor notification: state
503     {
504       int execState = _procRef->getExecutorState();
505       list<string> nextSteps;
506       if ((execState == YACS::WAITINGTASKS) || (execState == YACS::PAUSED))
507         {
508           YACS_ORB::stringArray_var nstp = _procRef->getTasksToLoad();
509           for (CORBA::ULong i=0; i<nstp->length(); i++)
510             nextSteps.push_back(nstp[i].in());
511           if (execState == YACS::PAUSED)
512             _isSuspended = true;
513         }
514       SubjectProc *sproc = _context->getSubjectProc();
515       sproc->update(YACS::HMI::UPDATEPROGRESS, execState, sproc);
516     }
517   else // --- Node notification
518     {
519       if (! _serv->_engineToGuiMap.count(numid))
520         return true;
521       int state = _procRef->getNodeState(numid);
522       int iGui = _serv->_engineToGuiMap[numid];
523       YASSERT(_context->_mapOfExecSubjectNode.count(iGui));
524       SubjectNode *snode = _context->_mapOfExecSubjectNode[iGui];
525       DEBTRACE("node " << snode->getName() << " state=" << state);
526
527       if (event == "progress") { // --- Update progress bar
528         std::string progress = _procRef->getNodeProgress(numid);
529         snode->setProgress( progress );
530         snode->update(YACS::HMI::PROGRESS, state, snode);
531       }
532       else { // --- Update node ports
533         YACS::ENGINE::Node *node = snode->getNode();
534         list<InputPort*> inports = node->getLocalInputPorts();
535         list<InputPort*>::iterator iti = inports.begin();
536         for ( ; iti != inports.end(); ++iti)
537           {
538             string val = _procRef->getInPortValue(numid, (*iti)->getName().c_str());
539             DEBTRACE("node " << snode->getName() << " inport " << (*iti)->getName() 
540                      << " value " << val);
541             YASSERT(_context->_mapOfSubjectDataPort.count(*iti));
542             SubjectDataPort* port = _context->_mapOfSubjectDataPort[*iti];
543             port->setExecValue(val);
544             port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
545           }
546         list<OutputPort*> outports = node->getLocalOutputPorts();
547         list<OutputPort*>::iterator ito = outports.begin();
548         for ( ; ito != outports.end(); ++ito)
549           {
550             string val = _procRef->getOutPortValue(numid, (*ito)->getName().c_str());
551             DEBTRACE("node " << snode->getName() << " outport " << (*ito)->getName() 
552                      << " value " << val);
553             YASSERT(_context->_mapOfSubjectDataPort.count(*ito));
554             SubjectDataPort* port = _context->_mapOfSubjectDataPort[*ito];
555             port->setExecValue(val);
556             port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
557           }
558         snode->update(YACS::HMI::UPDATEPROGRESS, state, snode);
559       }
560    }
561
562   return true;
563 }
564
565 void GuiExecutor::setBPList()
566 {
567   DEBTRACE("GuiExecutor::setBPList");
568   if (_isRunning)
569   {
570     YACS_ORB::stringArray listOfBreakPoints;
571     listOfBreakPoints.length(_breakpointList.size());
572     int i=0;
573     for (list<string>::iterator it = _breakpointList.begin(); it != _breakpointList.end(); ++it)
574       listOfBreakPoints[i++] = (*it).c_str();
575     _procRef->setListOfBreakPoints(listOfBreakPoints);
576   }
577 }
578
579 YACS::ExecutorState GuiExecutor::updateSchema(string jobState)
580 {
581   YACS::ExecutorState execState = YACS::NOTYETINITIALIZED;
582
583   int numid;
584   int state;
585   std::list<Node*> aNodeSet = _proc->getAllRecursiveConstituents();
586   for ( std::list<Node*>::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ){
587
588     numid = (*it)->getNumId();
589
590     state = _proc->getNodeState(numid);
591     SubjectNode *snode = _context->_mapOfExecSubjectNode[numid];
592
593     YACS::ENGINE::Node *node = snode->getNode();
594     list<InputPort*> inports = node->getLocalInputPorts();
595     list<InputPort*>::iterator iti = inports.begin();
596     for ( ; iti != inports.end(); ++iti)
597       {
598         string val = _proc->getInPortValue(numid, (*iti)->getName().c_str());
599         YASSERT(_context->_mapOfSubjectDataPort.count(*iti));
600         SubjectDataPort* port = _context->_mapOfSubjectDataPort[*iti];
601         port->setExecValue(val);
602         port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
603       }
604     list<OutputPort*> outports = node->getLocalOutputPorts();
605     list<OutputPort*>::iterator ito = outports.begin();
606     for ( ; ito != outports.end(); ++ito)
607       {
608         string val = _proc->getOutPortValue(numid, (*ito)->getName().c_str());
609         YASSERT(_context->_mapOfSubjectDataPort.count(*ito));
610         SubjectDataPort* port = _context->_mapOfSubjectDataPort[*ito];
611         port->setExecValue(val);
612         port->update(YACS::HMI::UPDATEPROGRESS, 0, port);
613       }
614     snode->update(YACS::HMI::UPDATEPROGRESS, state, snode);
615   }
616   state = _proc->getRootNode()->getEffectiveState();
617   switch(state){
618   case YACS::LOADED:
619   case YACS::ACTIVATED:
620     if(jobState!="RUNNING")
621       execState = YACS::FINISHED;
622     else
623       execState = YACS::RUNNING;
624     break;
625   case YACS::FAILED:
626   case YACS::DONE:
627     execState = YACS::FINISHED;
628     break;
629   case YACS::SUSPENDED:
630     execState = YACS::PAUSED;
631     break;
632   }
633   SubjectProc *sproc = _context->getSubjectProc();
634   sproc->update(YACS::HMI::UPDATEPROGRESS, execState, sproc);
635
636   return execState;
637 }