1 // Copyright (C) 2006-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "yacsconfig.h"
21 #include "RuntimeSALOME.hxx"
24 #include "Exception.hxx"
25 #include "Executor.hxx"
26 #include "parsers.hxx"
27 #include "VisitorSaveState.hxx"
28 #include "VisitorSaveSalomeSchema.hxx"
29 #include "LoadState.hxx"
30 #include "Dispatcher.hxx"
31 #include "LinkInfo.hxx"
34 #include "SALOME_NamingService.hxx"
35 #include "SALOME_ModuleCatalog.hh"
36 #include "Basics_Utils.hxx"
48 using YACS::YACSLoader;
49 using namespace YACS::ENGINE;
53 // --- use of glibc argp interface for parsing unix-style arguments
55 const char *argp_program_version ="driver V0.1";
56 const char *argp_program_bug_address ="<nepal@nepal.edf.fr>";
57 static char doc[] ="driver -- a SALOME YACS graph executor";
58 static char args_doc[] = "graph.xml";
62 static struct argp_option options[] =
64 {"display", 'd', "level", 0, "Display dot files: 0=never to 3=very often (default 0)"},
65 {"verbose", 'v', 0, 0, "Produce verbose output" },
66 {"stop-on-error", 's', 0, 0, "Stop on first error" },
67 {"dump-on-error", 'e', "file", OPTION_ARG_OPTIONAL, "Stop on first error and dump state"},
68 {"dump-final", 'f', "file", OPTION_ARG_OPTIONAL, "dump final state"},
69 {"dump", 'g', "nbsec", OPTION_ARG_OPTIONAL, "dump state"},
70 {"load-state", 'l', "file", 0, "Load State from a previous partial execution"},
71 {"save-xml-schema", 'x', "file", OPTION_ARG_OPTIONAL, "dump xml schema"},
72 {"shutdown", 't', "level", 0, "Shutdown the schema: 0=no shutdown to 3=full shutdown (default 1)"},
73 {"reset", 'r', "level", 0, "Reset the schema before execution: 0=nothing, 1=reset error nodes to ready state (default 0)"},
74 {"kill-port", 'k', "port", 0, "Kill Salome application running on the specified port if the driver process is killed (with SIGINT or SIGTERM)"},
106 parse_opt (int key, char *arg, struct argp_state *state)
110 // Get the input argument from argp_parse, which we
111 // know is a pointer to our arguments structure.
112 struct arguments *myArgs = (arguments*)state->input;
117 myArgs->display = atoi(arg);
120 myArgs->shutdown = atoi(arg);
123 myArgs->reset = atoi(arg);
134 myArgs->dumpErrorFile = arg;
136 myArgs->dumpErrorFile = (char *)"dumpErrorState.xml";
140 myArgs->finalDump = arg;
142 myArgs->finalDump = (char *)"finalDumpState.xml";
146 myArgs->dump = atoi(arg);
151 myArgs->loadState = arg;
155 myArgs->xmlSchema = arg;
157 myArgs->xmlSchema = (char *)"saveSchema.xml";
160 myArgs->killPort = atoi(arg);
164 if (state->arg_num >=1) // Too many arguments.
166 myArgs->args[state->arg_num] = arg;
170 if (state->arg_num < 1) // Not enough arguments.
175 return ARGP_ERR_UNKNOWN;
184 static struct argp argp = { options, parse_opt, args_doc, doc };
187 void timer(std::string msg)
192 gettimeofday(&tv,NULL);
193 long t=tv.tv_sec*1000+tv.tv_usec/1000;
195 gettimeofday(&tv,NULL);
196 std::cerr << msg << tv.tv_sec*1000+tv.tv_usec/1000-t0 << " ms" << std::endl;
201 static struct arguments myArgs;
203 void Handler(int theSigId)
208 //if requested save state
209 bool isFinalDump = (strlen(myArgs.finalDump) != 0);
212 YACS::ENGINE::VisitorSaveState vst(p);
213 vst.openFileDump(myArgs.finalDump);
217 //if requested shutdown schema
218 if(myArgs.shutdown < 999)
220 p->shutdown(myArgs.shutdown);
225 ostringstream command;
226 command << "killSalomeWithPort.py " << myArgs.killPort;
227 int status = system(command.str().c_str());
229 cerr << "Salome application on port " << myArgs.killPort << " is killed" << endl;
231 cerr << "Error: Can't kill Salome application on port " << myArgs.killPort << endl;
236 void * dumpState(void *arg)
238 thread_st *st = (thread_st*)arg;
239 YACS::StatesForNode state = p->getEffectiveState();
240 while((state != YACS::DONE) && (state != YACS::LOADFAILED) && (state != YACS::EXECFAILED) && (state != YACS::INTERNALERR) && (state != YACS::DISABLED) && (state != YACS::FAILED) && (state != YACS::ERROR)){
246 string cmd = "touch " + st->lockFile;
248 YACS::ENGINE::VisitorSaveState vst(p);
249 vst.openFileDump(st->dumpFile);
252 cmd = "rm -f " + st->lockFile;
254 state = p->getEffectiveState();
261 typedef void (*sighandler_t)(int);
262 sighandler_t setsig(int sig, sighandler_t handler)
264 struct sigaction context, ocontext;
265 context.sa_handler = handler;
266 sigemptyset(&context.sa_mask);
267 context.sa_flags = 0;
268 if (sigaction(sig, &context, &ocontext) == -1)
270 return ocontext.sa_handler;
275 int main (int argc, char* argv[])
282 myArgs.dumpErrorFile= (char *)"";
283 myArgs.finalDump = (char *)"";
285 myArgs.loadState = (char *)"";
286 myArgs.xmlSchema = (char *)"";
291 // Parse our arguments; every option seen by parse_opt will be reflected in arguments.
294 argp_parse (&argp, argc, argv, 0, 0, &myArgs);
295 std::cerr << "graph = " << myArgs.args[0];
296 std::cerr << " options: display=" << myArgs.display;
297 std::cerr << " verbose="<<myArgs.verbose;
298 std::cerr << " stop-on-error=" << myArgs.stop;
299 std::cerr << " shutdown=" << myArgs.shutdown;
300 std::cerr << " reset=" << myArgs.reset;
302 std::cerr << " kill-port=" << myArgs.killPort;
304 std::cerr << " dumpErrorFile=" << myArgs.dumpErrorFile << std::endl;
306 std::cerr << std::endl;
310 setsig(SIGINT,&Handler);
311 setsig(SIGTERM,&Handler);
315 RuntimeSALOME::setRuntime();
317 // Try to load the session catalog if it exists
320 YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
321 CORBA::ORB_ptr orb = runTime->getOrb();
324 SALOME_NamingService namingService(orb);
325 CORBA::Object_var obj = namingService.Resolve("/Kernel/ModulCatalog");
326 SALOME_ModuleCatalog::ModuleCatalog_var aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
327 if (! CORBA::is_nil(aModuleCatalog))
329 CORBA::String_var anIOR = orb->object_to_string( aModuleCatalog );
330 YACS::ENGINE::Catalog* aCatalog = runTime->loadCatalog( "session", anIOR.in() );
331 runTime->addCatalog(aCatalog);
335 catch(ServiceUnreachable& e)
337 //Naming service unreachable don't add catalog
345 timer("Elapsed time before load: ");
346 p=loader.load(myArgs.args[0]);
349 std::cerr << "The imported file is probably not a YACS schema file" << std::endl;
352 //Get the parser logger
353 Logger* logger=p->getLogger("parser");
354 //Print errors logged if any
355 if(!logger->isEmpty())
357 std::cerr << "The imported file has errors" << std::endl;
358 std::cerr << logger->getStr() << std::endl;
360 //Don't execute if there are errors
361 if(logger->hasErrors())
365 std::string report=p->getErrorReport();
366 std::cerr << "The schema is not valid and can not be executed" << std::endl;
367 std::cerr << report << std::endl;
370 Runtime* r=YACS::ENGINE::getRuntime();
371 Dispatcher* disp=Dispatcher::getDispatcher();
377 timer("Elapsed time after load: ");
381 std::string report=p->getErrorReport();
382 std::cerr << "The schema is not valid and can not be executed" << std::endl;
383 std::cerr << report << std::endl;
384 Runtime* r=YACS::ENGINE::getRuntime();
385 Dispatcher* disp=Dispatcher::getDispatcher();
391 timer("Elapsed time after validation: ");
394 LinkInfo info(LinkInfo::ALL_DONT_STOP);
395 p->checkConsistency(info);
396 if(info.areWarningsOrErrors())
398 std::cerr << "The schema is not consistent and can not be executed" << std::endl;
399 std::cerr << info.getGlobalRepr() << std::endl;
400 Runtime* r=YACS::ENGINE::getRuntime();
401 Dispatcher* disp=Dispatcher::getDispatcher();
407 timer("Elapsed time after check consistency: ");
410 bool isXmlSchema = (strlen(myArgs.xmlSchema) != 0);
413 YACS::ENGINE::VisitorSaveSalomeSchema vss(p);
414 vss.openFileSchema(myArgs.xmlSchema);
416 vss.closeFileSchema();
419 bool fromScratch = (strlen(myArgs.loadState) == 0);
424 stateParser* rootParser = new stateParser();
425 stateLoader myStateLoader(rootParser, p);
426 myStateLoader.parse(myArgs.loadState);
429 p->resetState(myArgs.reset);
435 if (strlen(myArgs.dumpErrorFile) >0)
436 executor.setStopOnError(true, myArgs.dumpErrorFile);
438 executor.setStopOnError(false, myArgs.dumpErrorFile);
442 std::ofstream f("toto");
447 bool isDump = (myArgs.dump != 0);
451 thread_st *st = new thread_st;
452 st->nbsec = myArgs.dump;
453 st->dumpFile = string("dumpState_") + myArgs.args[0];
454 string rootFile = st->dumpFile.substr(0,st->dumpFile.find("."));
455 st->lockFile = rootFile + ".lock";
456 pthread_create(&th,NULL,&dumpState,(void*)st);
459 cerr << "+++++++++++++++++++ start calculation +++++++++++++++++++" << endl;
460 executor.RunW(p,myArgs.display, fromScratch);
461 cerr << "+++++++++++++++++++ end calculation +++++++++++++++++++" << endl;
462 cerr << "Proc state : " << Node::getStateName(p->getEffectiveState()) << endl;
463 timer("Elapsed time after execution: ");
465 // Return 0 if SCHEMA OK
466 // Return 1 for YACS ERROR (EXCEPTION NOT CATCHED)
467 // Return 2 for YACS SCHEMA ERROR/FAILED
468 int return_value = 0;
470 if(p->getEffectiveState() != YACS::DONE)
472 std::string report=p->getErrorReport();
473 std::cerr << "Execution has ended in error" << std::endl;
474 std::cerr << report << std::endl;
480 std::ofstream g("titi");
487 pthread_join(th,NULL);
490 bool isFinalDump = (strlen(myArgs.finalDump) != 0);
493 YACS::ENGINE::VisitorSaveState vst(p);
494 vst.openFileDump(myArgs.finalDump);
498 if(myArgs.shutdown < 999)
500 p->shutdown(myArgs.shutdown);
503 Runtime* r=YACS::ENGINE::getRuntime();
504 Dispatcher* disp=Dispatcher::getDispatcher();
510 catch (YACS::Exception& e)
512 cerr << "Caught a YACS exception" << endl;
513 cerr << e.what() << endl;
514 Runtime* r=YACS::ENGINE::getRuntime();
515 Dispatcher* disp=Dispatcher::getDispatcher();
521 catch (const std::ios_base::failure&)
523 cerr << "Caught an io failure exception" << endl;
526 catch(CORBA::SystemException& ex)
528 cerr << "Caught a CORBA::SystemException.:" << __FILE__ << ":" << __LINE__ << ":" ;
531 CORBA::TypeCode_var tc = tmp.type();
532 const char *p = tc->name();
540 catch(omniORB::fatalException& fe)
542 cerr << "Caught omniORB::fatalException:" << endl;
543 cerr << " file: " << fe.file() << endl;
544 cerr << " line: " << fe.line() << endl;
545 cerr << " mesg: " << fe.errmsg() << endl;
550 cerr << "Caught unknown exception." << endl;