Salome HOME
d9ca886a68b05f27268c58271809c61810f2d308
[modules/yacs.git] / src / genericgui / ListJobs_GUI.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 <iostream>
21 #include <fstream>
22
23 #include "RuntimeSALOME.hxx"
24 #include "ListJobs_GUI.hxx"
25 #include "GenericGui.hxx"
26 #include "QtGuiContext.hxx"
27 #include "YACSGuiLoader.hxx"
28 #include "Logger.hxx"
29 #include "YacsTrace.hxx"
30 #include "LoadState.hxx"
31
32 #include <QBoxLayout>
33 #include <QFileInfo>
34 #include <QMessageBox>
35 #include <QPushButton>
36 #include <QTableWidget>
37 #include <QTimer>
38
39 using namespace std;
40 using namespace YACS::HMI;
41 using namespace YACS::ENGINE;
42
43 BatchJobsListDialog::BatchJobsListDialog(QString title,GenericGui* genericGui): QWidget(),_genericGui(genericGui),_proc(NULL) {
44
45   setWindowTitle(title);
46
47   // Connection to Salome Launcher
48   getSalomeLauncher();
49
50   // Add a layout
51   QBoxLayout* box = new QBoxLayout(QBoxLayout::TopToBottom, this);
52   setLayout(box);
53
54   _table = new QTableWidget(this);
55   _table->setColumnCount(4);
56
57   build_table();
58
59   // Add table
60   box->addWidget(_table);
61
62   // Add buttons
63   QWidget* buttons = build_buttons();
64   box->addWidget(buttons);
65
66   // No line selected
67   _ok->setEnabled(false);
68   _id = -1;
69
70   // Set timer to refresh table
71   _timer1 = new QTimer(this);
72   connect(_timer1, SIGNAL(timeout()), this, SLOT(build_table()));
73   _timer1->start(30000);
74
75 }
76
77 BatchJobsListDialog::~BatchJobsListDialog(){
78 }
79
80 void BatchJobsListDialog::getSalomeLauncher(){
81   YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
82   CORBA::ORB_ptr orb = runTime->getOrb();
83   SALOME_NamingService_Wrapper NS;
84   CORBA::Object_var obj = NS.Resolve("/SalomeLauncher");
85   _salome_launcher = Engines::SalomeLauncher::_narrow(obj);
86   if (CORBA::is_nil(_salome_launcher))
87     throw YACS::Exception("Salome Launcher not reachable!!");
88 }
89
90 // Display list of current batch jobs and allow selection only on running jobs
91 void BatchJobsListDialog::build_table() {
92
93   int irow = 0;
94
95   _table->clear();
96
97   Engines::JobsList* joblist = _salome_launcher->getJobsList();
98
99   int nblines = joblist->length();
100   _table->setRowCount(nblines);
101
102   QStringList titres;
103   titres << "Job Name" << "State" << "Resource" << "Launcher Id";
104   _table->setHorizontalHeaderLabels(titres);
105
106   for(int i=0;i<nblines;i++){
107     Engines::JobDescription descr = (*joblist)[i];
108     string jobType = CORBA::string_dup(descr.job_parameters.job_type);
109     // We display only jobs of type yacs_file
110     if(jobType.find("yacs_file")!=string::npos){
111       long jobId = descr.job_id;
112       ostringstream sstId;
113       sstId << jobId;
114       string jobName = CORBA::string_dup(descr.job_parameters.job_name);
115       string jobState = _salome_launcher->getJobState(jobId);
116       string jobMachine = CORBA::string_dup(descr.job_parameters.resource_required.name);
117       QTableWidgetItem* item0 = new QTableWidgetItem(jobName.c_str()    , type_job);
118       QTableWidgetItem* item1 = new QTableWidgetItem(jobState.c_str()   , type_state);
119       QTableWidgetItem* item2 = new QTableWidgetItem(jobMachine.c_str() , type_res  );
120       QTableWidgetItem* item3 = new QTableWidgetItem(sstId.str().c_str(), type_id   );
121       _table->setItem(irow, 0, item0);
122       _table->setItem(irow, 1, item1);
123       _table->setItem(irow, 2, item2);
124       _table->setItem(irow, 3, item3);
125       if(jobState != "RUNNING"){
126         item0->setFlags(Qt::NoItemFlags);
127         item1->setFlags(Qt::NoItemFlags);
128         item2->setFlags(Qt::NoItemFlags);
129         item3->setFlags(Qt::NoItemFlags);
130       }
131       else if(jobId == _id){
132         item0->setSelected(true);
133         item1->setSelected(true);
134         item2->setSelected(true);
135         item3->setSelected(true);
136       }
137       irow++;
138     }
139   }
140     
141   connect(_table, SIGNAL( itemClicked(QTableWidgetItem*) ), this, SLOT( userCell(QTableWidgetItem*) ));
142
143 }
144
145 // Build buttons in a layout
146 // -------------------------
147
148 QWidget* BatchJobsListDialog::build_buttons() {
149   _ok     = new QPushButton("OK"    , this);
150   QPushButton* cancel = new QPushButton("Cancel", this);
151
152   connect(_ok    , SIGNAL(clicked()), this, SLOT(userOK    ()));
153   connect(cancel, SIGNAL(clicked()), this, SLOT(userCancel()));
154
155   QBoxLayout* layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
156
157   layout->addWidget(_ok);
158   layout->addWidget(cancel);
159
160   QWidget* buttons = new QWidget(this);
161   buttons->setLayout(layout);
162
163   return(buttons);
164 }
165
166 // Click on a cell button
167 // ----------------------
168
169 void BatchJobsListDialog::userCell(QTableWidgetItem* cell) {
170   if ( cell->flags() ) {
171     int line = cell->row();
172     string sid = _table->item(line,3)->text().toStdString();
173     _id = atoi(sid.c_str());
174     _ok->setEnabled(true);
175
176     QTableWidget* table = cell->tableWidget();
177     for (int c=0; c<4; c++) {
178       QTableWidgetItem* it = table->item(line, c);
179       it->setSelected(true);
180     };
181   };
182 }
183
184 // Click on OK button
185 // ------------------
186
187 void BatchJobsListDialog::userOK() {
188
189   // get job file name
190   Engines::JobParameters* jobParam = _salome_launcher->getJobParameters(_id);
191   _jobFile = CORBA::string_dup(jobParam->job_file);
192   _dumpStateFile = QString("/tmp/%1/dumpState_%2.xml").arg(getenv("USER")).arg(QFileInfo(_jobFile).baseName());
193
194   // stop first timer and hide window
195   _timer1->stop();
196   hide();
197
198   // replace objref by string in YACS schema job file to avoid trying to reach remote objects
199   filterJobFile();
200
201   // display yacs graph
202   YACSGuiLoader *loader = _genericGui->getLoader();
203   _proc = loader->load(_filteredJobFile.toLatin1());
204   if (!_proc) {
205     QMessageBox msgBox(QMessageBox::Critical, "Import Batch Schema, native YACS XML format",
206                        "The xml graph has not the native YACS XML format or is not readable." );
207     msgBox.exec();
208   } 
209   else {
210     YACS::ENGINE::Logger* logger= _proc->getLogger("parser");
211     if(!logger->isEmpty()) {
212       DEBTRACE(logger->getStr());
213     };
214     _genericGui->createContext(_proc, _filteredJobFile, _filteredJobFile, false);
215   };
216
217   // start second timer to get remote graph state xml file
218   _timer2 = new QTimer(this);
219   connect(_timer2, SIGNAL(timeout()), this, SLOT(get_dump_file()));
220   _timer2->start(30000);
221   get_dump_file();
222 }
223
224 // Click on CANCEL button
225 // ----------------------
226
227 void BatchJobsListDialog::userCancel() {
228   _timer1->stop();
229   hide();
230 }
231
232 // get remote graph state xml file
233
234 void BatchJobsListDialog::get_dump_file()
235 {
236   int execState = YACS::NOTYETINITIALIZED;
237   // get batch job state
238   string jobState = _salome_launcher->getJobState(_id);
239   // get dump state remote file
240   bool ret = _salome_launcher->getJobDumpState(_id, QFileInfo(_dumpStateFile).absolutePath().toLatin1().constData());
241   if(ret){
242     // replace objref by string in dump state file
243     filterDumpStateFile();
244     // parse dump state file and load proc
245     YACS::ENGINE::loadState(_proc,_filteredDumpStateFile.toStdString());
246     // display remote graph states
247     GuiExecutor *executor = QtGuiContext::getQtCurrent()->getGuiExecutor();
248     execState = executor->updateSchema(jobState);
249   }
250   // stop timer if job is not running
251   if((execState!=YACS::RUNNING)&&(execState!=YACS::NOTYETINITIALIZED))
252     _timer2->stop();
253 }
254
255 // filtering of _jobFile to replace objref by string
256 void BatchJobsListDialog::filterJobFile()
257 {
258   _filteredJobFile = QString("/tmp/%1/%2.xml").arg(getenv("USER")).arg(QFileInfo(_jobFile).baseName());
259   // reading input file
260   ifstream infile(_jobFile.toStdString().c_str());
261   if(!infile){
262     string errmsg = "File " + _jobFile.toStdString() + " doesn't exist!!";
263     throw YACS::Exception(errmsg);
264   }
265   string buffer;
266   vector<string> objref;
267   while( !infile.eof() ){
268     getline(infile,buffer);
269     // look for objref and memorize them in vector
270     if( (buffer.find("objref") != string::npos) && (buffer.find("IDL") != string::npos) ){
271       size_t pos1 = buffer.find("\"");
272       size_t pos2 = buffer.find("\"",pos1+1);
273       objref.push_back(buffer.substr(pos1+1,pos2-pos1-1));
274     }
275   }
276   infile.close();
277   // reread the input file
278   infile.open(_jobFile.toStdString().c_str());
279   // open the output file
280   ofstream outfile(_filteredJobFile.toStdString().c_str());
281   if(!outfile){
282     string errmsg = "Impossible to create the file " + _filteredJobFile.toStdString() + "!!";
283     throw YACS::Exception(errmsg);
284   }
285   while( !infile.eof() ){
286     getline(infile,buffer);
287     // replace objref by string
288     if( ((buffer.find("objref") == string::npos) || (buffer.find("IDL") == string::npos)) && (buffer.find("/objref") == string::npos) ){
289       string tmp = buffer;
290       for(int i=0;i<objref.size();i++){
291         size_t pos = buffer.find(objref[i]);
292         if(pos != string::npos)
293           tmp = buffer.substr(0,pos) + "string" + buffer.substr(pos+objref[i].size());
294       }
295       outfile << tmp << endl;
296     }
297   }
298 }
299
300 // filtering of _dumpStateFile to replace objref by string
301 void BatchJobsListDialog::filterDumpStateFile()
302 {
303   string buffer;
304   _filteredDumpStateFile = QString("/tmp/%1/filtered_%2.xml").arg(getenv("USER")).arg(QFileInfo(_dumpStateFile).baseName());
305   ifstream infile(_dumpStateFile.toStdString().c_str());
306   if(!infile){
307     string errmsg = "File " + _dumpStateFile.toStdString() + " doesn't exist!!";
308     throw YACS::Exception(errmsg);
309   }
310   ofstream outfile(_filteredDumpStateFile.toStdString().c_str());
311   if(!outfile){
312     string errmsg = "Impossible to create the file " + _filteredDumpStateFile.toStdString() + "!!";
313     throw YACS::Exception(errmsg);
314   }
315   // replace objref by string in dump state file
316   while( !infile.eof() ){
317     getline(infile,buffer);
318     size_t pos = buffer.find("objref");
319     while(pos != string::npos){
320       buffer.replace(pos,6,"string");
321       pos = buffer.find("objref");
322     }
323     outfile << buffer << endl;
324   }
325 }
326