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