Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / gui / YACSGui_Executor.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA 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 <YACSGui_Executor.h>
21 #include <YACSGui_XMLDriver.h>
22 #include <YACSGui_Observer.h>
23 #include <YACSGui_Module.h>
24 #include <SUIT_MessageBox.h>
25 #include <SalomeApp_Application.h>
26 #include <Executor.hxx>
27 #include "utilities.h"
28
29 #include <Qtx.h>
30
31 #include <qdir.h>
32
33 #include <iostream> //for debug only
34
35 //#define _DEVDEBUG_
36 #include "YacsTrace.hxx"
37
38 using namespace YACS::ENGINE;
39 using namespace YACS;
40 using namespace std;
41
42 //! Constructor
43 /*!
44  */
45 YACSGui_Executor::YACSGui_Executor(YACSGui_Module* guiMod, Proc* theProc) :
46   QThread(),
47   _guiMod(guiMod),
48   _proc(theProc)
49 {
50   _localEngine = 0;
51   _engineRef = YACS_ORB::YACS_Gen::_nil();
52   _procRef = YACS_ORB::ProcExec::_nil();
53   _observerRef = YACS_ORB::Observer::_nil();
54   _serv = 0;
55   _isRunning = false;
56   _isSuspended = false;
57   _isStopOnError = false;
58   _execMode = YACS::CONTINUE;
59   _loadStateFile = "";
60 }
61
62 //! Destructor
63 /*!
64  */
65 YACSGui_Executor::~YACSGui_Executor()
66 {
67 }
68
69 //! local run in a QThread
70 /*! local run in a QThread Reimplemented from QThread class.
71  */
72 void YACSGui_Executor::run()
73 {
74   if (!_proc)
75     return;
76   int debug = 0; // for debug only
77   _localEngine->RunW(_proc, debug);
78   _isRunning = false;
79 }
80
81 //! Run dataflow.
82 /*! local run or remote (in a SALOME Container)
83  */
84 void YACSGui_Executor::runDataflow(const bool isRemoteRun)
85 {
86   DEBTRACE("YACSGui_Executor::runDataflow");
87   _isRemoteRun = isRemoteRun;
88   if (!isRemoteRun)  // --- wanted local run
89     {
90       if (! _localEngine)
91         _localEngine = new Executor();
92       if (_isRunning)
93         if (! checkEndOfDataFlow()) return;
94       _isRunning = true;
95       _localEngine->setExecMode(YACS::CONTINUE); // --- control only on remote run
96       start();
97     }
98   else              // --- wanted run in a SALOME Container
99     {
100       if (CORBA::is_nil(_engineRef))
101       {
102         DEBTRACE(">> Create YACS ORB engine!");
103         _engineRef = YACSGui_Module::InitYACSGuiGen(_guiMod->getApp());
104       }
105
106       if (_isRunning)
107         if (! checkEndOfDataFlow()) return;
108       _isRunning = true;
109       //Export the proc into temporary XML file
110       QString aFileName = Qtx::tmpDir() + QDir::QDir::separator() + "tmp_" + _proc->getName();
111       
112       if (CORBA::is_nil(_procRef))
113         {
114           DEBTRACE("init _procRef");
115           VisitorSaveSalomeSchema aWriter( _proc );
116           aWriter.openFileSchema( aFileName );
117           aWriter.visitProc( _proc );
118           aWriter.closeFileSchema();
119           _procRef = _engineRef->LoadProc(aFileName.latin1());
120           registerStatusObservers();
121           DEBTRACE("_procRef _init");
122         }
123       _procRef->setExecMode(getCurrentExecMode());
124       _setBPList();
125       if ( _loadStateFile.empty() )
126       {
127         DEBTRACE(">> Run!");
128         cout<<">> this = "<<this<<endl<<endl;
129         _procRef->Run();
130       }
131       else
132       {
133         DEBTRACE(">> Run from STATE!");
134         try {
135         _procRef->RunFromState(_loadStateFile.c_str());
136         }
137         catch (...) {
138           SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), 
139                                   tr("ERROR"), 
140                                   tr("Runtime error: execution from the loaded state failed"), 
141                                   tr("BUT_OK"));
142           return;
143         }
144         cout<<">> this = "<<this<<endl<<endl;
145       }
146     }
147 }
148
149 //! test if a dataflow is running
150 /*!
151  * return true if no running dataflow (TODO: check save state ? delete procexec servant ?)
152  */
153 bool YACSGui_Executor::checkEndOfDataFlow(bool display)
154 {
155   if (_isRunning)
156     {
157       if(running()) // --- local run not finished
158         {
159           if (display)
160             SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), 
161                                     tr("ERROR"), 
162                                     tr("Local Execution Already running..."), 
163                                     tr("BUT_OK"));
164           return false;
165         }
166       if (CORBA::is_nil(_procRef))
167         {
168           if (display)
169             SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), 
170                                     tr("ERROR"), 
171                                     tr("Runtime error: connection lost on a running scheme"), 
172                                     tr("BUT_OK"));
173           _isRunning = false;
174           return false;              
175         }
176       if (_procRef->isNotFinished())
177         {
178           if (display)
179             SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), 
180                                     tr("ERROR"), 
181                                     tr("Remote Execution Already running..."), 
182                                     tr("BUT_OK"));
183           return false;
184         }
185       else
186         {
187           _isRunning = false;
188           // --- TODO: delete procExec on server ...
189         }
190     }
191   return true;
192 }
193
194 //! Kill dataflow.
195 /*!
196  */
197 void YACSGui_Executor::killDataflow()
198 {
199   DEBTRACE("YACSGui_Executor::killDataflow");
200   //terminate(); // not safe!
201   if (running())        // --- local run
202     {
203       _localEngine->stopExecution();
204     }
205   else if (_isRunning)  // --- remote run
206     {
207       _procRef->stopExecution();
208     }
209 }
210
211
212 //! Suspend/Resume dataflow.
213 /*!
214  */
215 void YACSGui_Executor::suspendResumeDataflow()
216 {
217   DEBTRACE("YACSGui_Executor::suspendResumeDataflow");
218   if (running())        // --- local run
219     {
220       if (_isSuspended)
221         {
222           _localEngine->setExecMode(_execMode);
223           _localEngine->resumeCurrentBreakPoint();
224         }
225       else
226         _localEngine->setExecMode(YACS::STEPBYSTEP);
227     }
228   else if (_isRunning)  // --- remote run
229     {
230       if (_isSuspended)
231         {
232           _procRef->setExecMode(getCurrentExecMode());
233           _procRef->resumeCurrentBreakPoint();
234         }
235       else
236         _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
237     }
238   _isSuspended = !_isSuspended;
239 }
240
241 void YACSGui_Executor::suspendDataflow()
242 {
243   DEBTRACE("YACSGui_Executor::suspendDataflow");
244   if (running())        // --- local run
245     {
246       _localEngine->setExecMode(YACS::STEPBYSTEP);
247     }
248   else if (_isRunning)  // --- remote run
249     {
250       _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
251     }
252 }
253
254 void YACSGui_Executor::resumeDataflow()
255 {
256   DEBTRACE("YACSGui_Executor::ResumeDataflow");
257   if (running())        // --- local run
258     {
259       _localEngine->setExecMode(_execMode);
260       _localEngine->resumeCurrentBreakPoint();
261     }
262   else if (_isRunning)  // --- remote run
263     {
264       _procRef->setExecMode(getCurrentExecMode());
265       _procRef->resumeCurrentBreakPoint();
266     }
267 }
268
269 //! Stop dataflow.
270 /*!
271  */
272 void YACSGui_Executor::stopDataflow()
273 {
274   DEBTRACE("YACSGui_Executor::stopDataflow");
275   if (running())        // --- local run
276     {
277       _localEngine->stopExecution();
278     }
279   else if (_isRunning)  // --- remote run
280     {
281       _procRef->stopExecution();
282     }
283
284 }
285
286 void YACSGui_Executor::setStepByStepMode()
287 {
288   DEBTRACE("YACSGui_Executor::setStepByStepMode");
289   _execMode = YACS::STEPBYSTEP;
290   if (running())        // --- local run
291     _localEngine->setExecMode(YACS::STEPBYSTEP);
292   else if (_isRunning)  // --- remote run
293     _procRef->setExecMode(YACS_ORB::STEPBYSTEP);
294 }
295
296 void YACSGui_Executor::setContinueMode()
297 {
298   DEBTRACE("YACSGui_Executor::setContinueMode");
299   _execMode = YACS::CONTINUE;
300   if (running())        // --- local run
301     {
302       _localEngine->setExecMode(YACS::CONTINUE);
303     }
304   else if (_isRunning)  // --- remote run
305     {
306       _procRef->setExecMode(YACS_ORB::CONTINUE);
307     }
308 }
309
310 void YACSGui_Executor::setBreakpointMode()
311 {
312   DEBTRACE("YACSGui_Executor::setBreakpointMode");
313   _execMode = YACS::STOPBEFORENODES;
314   if (running())        // --- local run
315     {
316       _localEngine->setExecMode(YACS::STOPBEFORENODES);
317     }
318   else if (_isRunning)  // --- remote run
319     {
320       _procRef->setExecMode(YACS_ORB::STOPBEFORENODES);
321     }
322 }
323
324 void YACSGui_Executor::setStopOnError(bool aMode)
325 {
326   DEBTRACE("YACSGui_Executor::setStopOnError");
327   if (running())        // --- local run
328     {
329       _localEngine->setStopOnError(aMode, "/tmp/dumpStateOnError.xml");
330       _isStopOnError = true;
331     }
332   else if (_isRunning)  // --- remote run
333     {
334       _procRef->setStopOnError(aMode, "/tmp/dumpStateOnError.xml");
335       _isStopOnError = true;
336     }
337 }
338
339 void YACSGui_Executor::unsetStopOnError()
340 {
341   DEBTRACE("YACSGui_Executor::unsetStopOnError");
342   if (running())        // --- local run
343     {
344       _localEngine->unsetStopOnError();
345       _isStopOnError = false;
346     }
347   else if (_isRunning)  // --- remote run
348     {
349       _procRef->unsetStopOnError();
350       _isStopOnError = false;
351     }
352 }
353
354 void YACSGui_Executor::saveState(const std::string& xmlFile)
355 {
356   DEBTRACE("YACSGui_Executor::saveState");
357   bool StartFinish = (getExecutorState() == YACS::NOTYETINITIALIZED || getExecutorState() == YACS::FINISHED );
358
359   if ( running()
360        ||
361        _localEngine && (CORBA::is_nil(_procRef)) && StartFinish )        // --- local run
362     _localEngine->saveState(xmlFile);
363   else if ( _isRunning
364             ||
365             !_localEngine && !(CORBA::is_nil(_procRef)) && StartFinish )  // --- remote run
366     _procRef->saveState(xmlFile.c_str());
367 }
368
369 void YACSGui_Executor::setLoadStateFile(std::string xmlFile)
370 {
371   _loadStateFile = xmlFile;
372 }
373
374 void YACSGui_Executor::setNextStepList(std::list<std::string> nextStepList)
375 {
376   DEBTRACE("YACSGui_Executor::setNextStepList");
377   if (running())        // --- local run
378     {
379       _localEngine->setStepsToExecute(nextStepList);
380     }
381   else if (_isRunning)  // --- remote run
382     {
383       YACS_ORB::stringArray listOfNextStep;
384       listOfNextStep.length(nextStepList.size());
385       int i=0;
386       for (list<string>::iterator it = nextStepList.begin(); it != nextStepList.end(); ++it)
387         listOfNextStep[i++] = (*it).c_str();
388       _procRef->setStepsToExecute(listOfNextStep);
389     }
390 }
391
392 void YACSGui_Executor::setBreakpointList(std::list<std::string> breakpointList)
393 {
394   DEBTRACE("YACSGui_Executor::setBreakpointList");
395   _breakpointList.clear();
396   _breakpointList = breakpointList;
397   _setBPList();
398 }
399
400 //! list must be sent, even empty (only way to remove all breakpoints)
401 void YACSGui_Executor::_setBPList()
402 {
403   if (running())        // --- local run
404     {
405       _localEngine->setListOfBreakPoints(_breakpointList);
406     }
407   else if (_isRunning)  // --- remote run
408     {
409       YACS_ORB::stringArray listOfBreakPoints;
410       listOfBreakPoints.length(_breakpointList.size());
411       int i=0;
412       for (list<string>::iterator it = _breakpointList.begin(); it != _breakpointList.end(); ++it)
413         listOfBreakPoints[i++] = (*it).c_str();
414       _procRef->setListOfBreakPoints(listOfBreakPoints);
415     }
416 }
417
418 void YACSGui_Executor::registerStatusObservers()
419 {
420   DEBTRACE("YACSGui_Executor::registerStatusObservers");
421   if (CORBA::is_nil(_procRef))
422     {
423       SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), 
424                               tr("ERROR"), 
425                               tr("Runtime error (yacsgui): Lost connection on YACS executor"), 
426                               tr("BUT_OK"));
427       return;
428     }
429   if (CORBA::is_nil(_observerRef))
430     {
431       _serv = new Observer_i(_proc, _guiMod, this);
432       _observerRef = _serv->_this();
433       _serv->SetImpl(_graph->getStatusObserver());
434     }
435   DEBTRACE("---");
436   _serv->SetRemoteProc(_procRef);
437   _serv->setConversion();
438   DEBTRACE("---");
439   std::list<Node*> aNodeSet = _proc->getAllRecursiveConstituents();
440   for ( std::list<Node*>::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ )
441     {
442       _procRef->addObserver(_observerRef, _serv->getEngineId((*it)->getNumId()) , "status");
443     }
444   _procRef->addObserver(_observerRef, _serv->getEngineId(_proc->getNumId()) , "executor"); 
445 }
446
447 YACS_ORB::executionMode YACSGui_Executor::getCurrentExecMode()
448 {
449   switch (_execMode)
450     {
451     case YACS::CONTINUE: return YACS_ORB::CONTINUE;
452     case YACS::STEPBYSTEP: return YACS_ORB::STEPBYSTEP;
453     case YACS::STOPBEFORENODES: return YACS_ORB::STOPBEFORENODES;
454     default: return YACS_ORB::CONTINUE;
455     }
456 }
457
458 int YACSGui_Executor::getExecutorState()
459 {
460   if ( running()
461        ||
462        _localEngine && (CORBA::is_nil(_procRef)) )        // --- local run
463     return _localEngine->getExecutorState();
464   else if ( _isRunning
465             ||
466             !_localEngine && !(CORBA::is_nil(_procRef)) )  // --- remote run
467     return _procRef->getExecutorState();
468   else if ( !_localEngine && (CORBA::is_nil(_procRef)) )
469     return YACS::NOTYETINITIALIZED;
470   else if ( _localEngine && !(CORBA::is_nil(_procRef)) )
471     return YACS::FINISHED;
472 }
473
474 void YACSGui_Executor::setEngineRef(YACS_ORB::YACS_Gen_ptr theRef)
475 {
476   _engineRef = theRef;
477 }
478
479 std::string YACSGui_Executor::getErrorDetails(YACS::ENGINE::Node* node)
480 {
481   if (_serv)
482   {
483     //get the node engine id
484     int engineId=_serv->getEngineId(node->getNumId());
485     return _procRef->getErrorDetails(engineId);
486   }
487   return "---";
488 }
489
490 std::string YACSGui_Executor::getErrorReport(YACS::ENGINE::Node* node)
491 {
492   if (_serv)
493   {
494     //get the node engine id
495     int engineId=_serv->getEngineId(node->getNumId());
496     return _procRef->getErrorReport(engineId);
497   }
498   return "---";
499 }
500
501 std::string YACSGui_Executor::getContainerLog()
502 {
503   DEBTRACE("YACSGui_Executor::getContainerLog");
504   std::string msg="";
505   if (!CORBA::is_nil(_engineRef))
506     {
507       Engines::Container_var cont= _engineRef->GetContainerRef();
508       CORBA::String_var logname = cont->logfilename();
509       DEBTRACE(logname);
510       msg=logname;
511       std::string::size_type pos = msg.find(":");
512       msg=msg.substr(pos+1);
513     }
514   return msg;
515 }
516
517 std::string YACSGui_Executor::getContainerLog(YACS::ENGINE::Node* node)
518 {
519   std::string msg;
520   if (_serv)
521     {
522       //get the node engine id
523       int engineId=_serv->getEngineId(node->getNumId());
524       CORBA::String_var logname = _procRef->getContainerLog(engineId);
525       msg=logname;
526       std::string::size_type pos = msg.find(":");
527       msg=msg.substr(pos+1);
528     }
529   return msg;
530 }