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