Salome HOME
4b55a6f34a004eac9965ef242aa606d37ce22e52
[modules/yacs.git] / src / yacsloader / driver.py
1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2024  CEA, EDF
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20
21 # python3 /home/H87074/salome/990_CEA/SALOME-master-native-DB11-SRC/SOURCES/yacs/src/yacsloader/driver.py -v -kt micro_schema.xml
22 # python3 /home/H87074/salome/990_CEA/SALOME-master-native-DB11-SRC/SOURCES/yacs/src/yacsloader/driver.py -d 3 -g 2 --stop-on-error --dump-on-error="popo.xml" -v -kt -ip "PyScript0.p1=7" --dump-final="tutu.xml" micro_schema2.xml
23 # python3 /home/H87074/salome/990_CEA/SALOME-master-native-DB11-SRC/SOURCES/yacs/src/yacsloader/driver.py -g 2 --stop-on-error --dump-on-error="popo.xml" -v -kt -ip "PyScript0.p1=7" --dump-final="tutu.xml" micro_schema2.xml
24 # python3 /home/H87074/salome/990_CEA/SALOME-master-native-DB11-SRC/SOURCES/yacs/src/yacsloader/driver.py -x -g 2 --stop-on-error --dump-on-error="popo.xml" -v -kt -ip "PyScript0.p1=7" --dump-final="tutu.xml" micro_schema2.xml
25
26 import loader
27 #import SALOMERuntime
28 import salome
29 import logging
30
31 """
32 struct arguments
33 {
34   int dump = 0;
35 };
36
37     {"dump",            'g', "nbsec", OPTION_ARG_OPTIONAL, "dump state"},
38     {"save-xml-schema", 'x', "file",  OPTION_ARG_OPTIONAL, "dump xml schema"},
39 """
40
41 my_runtime_yacs = None
42
43 def initializeSALOME():
44     import SALOMERuntime
45     global my_runtime_yacs
46     if my_runtime_yacs:
47       return
48     salome.salome_init()
49     flags = SALOMERuntime.RuntimeSALOME.UsePython + SALOMERuntime.RuntimeSALOME.UseCorba + SALOMERuntime.RuntimeSALOME.UseXml + SALOMERuntime.RuntimeSALOME.UseCpp + SALOMERuntime.RuntimeSALOME.UseSalome
50     SALOMERuntime.RuntimeSALOME.setRuntime( flags )
51     my_runtime_yacs = SALOMERuntime.getSALOMERuntime()
52     anIOR = salome.orb.object_to_string ( salome.modulcat )
53     aCatalog = my_runtime_yacs.loadCatalog( "session", anIOR )
54     my_runtime_yacs.addCatalog( aCatalog )
55
56 def SALOMEInitializationNeeded(func):
57     def decaratedFunc(*args,**kwargs):
58       initializeSALOME()
59       return func(*args,**kwargs)
60     return decaratedFunc
61
62 @SALOMEInitializationNeeded
63 def loadGraph( xmlFileName ):
64     """
65     Args:
66     -----
67     xmlFileName : XML file containing YACS schema
68
69     Returns
70     -------
71
72     SALOMERuntime.SalomeProc : YACS graph instance
73     """
74     l=loader.YACSLoader()
75     p=l.load( xmlFileName )
76     return p
77
78 def patchGraph( proc, squeezeMemory, initPorts, xmlSchema, loadStateXmlFile, reset, display):
79     """
80     Args:
81     -----
82
83     proc ( SALOMERuntime.SalomeProc ) : YACS Proc instance to be evaluated
84     squeezeMemory ( bool ) : squeezememory to be activated
85     initPorts (list<string>) : list of bloc.node.port=value.
86     xmlSchema (string) :
87     loadStateXmlFile (string) : file if any of state to be loaded inside proc
88     reset (int) : 
89     display (int) :
90     """
91     import SALOMERuntime
92     def parse_init_port(input):
93       """
94       Returns
95       -------
96       node, port, value
97       """
98       node_port, value = input.split("=")
99       nodePortSpl = node_port.split(".")
100       port = nodePortSpl[-1]
101       node = ".".join( nodePortSpl[:-1] )
102       return node,port,value
103        
104     if squeezeMemory:
105       logging.info("SqueezeMemory requested -> update proc")
106       allNodes = proc.getAllRecursiveNodes()
107       for node in allNodes:
108         if isinstance(proc,SALOMERuntime.PythonNode):
109           node.setSqueezeStatus( True )
110     #
111     for initPort in initPorts:
112         node,port,value = parse_init_port(initPort)
113         init_state = proc.setInPortValue(node, port, value)
114         if init_state != value:
115           raise RuntimeError(f"Error on initialization of {initPort}")
116     #
117     if xmlSchema:
118       SALOMERuntime.VisitorSaveSalomeSchemaUnsafe(proc,xmlSchema)
119       pass
120     #
121     if loadStateXmlFile:
122       loader.loadState( proc, loadStateXmlFile )
123       if reset > 0:
124         proc.resetState(reset)
125         proc.exUpdateState()
126     #
127     if display > 0:
128        proc.writeDotInFile("toto")
129          
130 @SALOMEInitializationNeeded
131 def prepareExecution(proc, isStop, dumpErrorFile):
132   """
133   Returns
134   -------
135
136   pilot.ExecutorSwig : Instance of executor
137   """
138   import pilot
139   ex=pilot.ExecutorSwig()
140   if isStop:
141     logging.info(f"Stop has been activated with {dumpErrorFile}")
142     ex.setStopOnError( dumpErrorFile!="", dumpErrorFile )
143   return ex
144
145 @SALOMEInitializationNeeded
146 def executeGraph( executor, xmlfilename, proc, dump, finalDump, display ):
147     """
148     Args:
149     -----
150   
151     executor (pilot.ExecutorSwig) : Executor in charge of evaluation.
152     proc ( SALOMERuntime.SalomeProc ) : YACS Proc instance to be evaluated
153     xmlfilename (string)
154     dump (int) : time interval between 2 dump state
155     finalDump ( string ) : filename containing final result of graph, if any.
156     display (int) :
157     """
158     global dump_thread
159     import pilot
160     import SALOMERuntime
161     import os
162
163     if dump != 0:
164        dumpFile = "dumpState_{}".format( os.path.basename(xmlfilename) )
165        lockFile = "{}.lock".format( os.path.splitext( os.path.basename(xmlfilename) )[0] )
166        dump_thread = SALOMERuntime.ThreadDumpState(proc,dump,dumpFile,lockFile)
167        dump_thread.start()
168
169     executor.RunPy(proc,display,isPyThread=True,fromscratch=True) # same as RunW but releasing GIL
170     if proc.getEffectiveState() != pilot.DONE:
171       raise RuntimeError( proc.getErrorReport() )
172     #
173     if display > 0:
174        proc.writeDotInFile("titi")
175     #
176     if dump_thread:
177        dump_thread.join()
178     #
179     if finalDump:
180       logging.info(f"Final dump requested : {finalDump}")
181       SALOMERuntime.schemaSaveStateUnsafe( proc, finalDump )
182
183 @SALOMEInitializationNeeded
184 def destroyElementsGeneratedByExecutionOfGraph( proc, shutdown ):
185     """
186     Args:
187     -----
188
189     shutdown (int) : shutdown level
190
191     """
192     if shutdown < 999:
193       proc.shutdown(shutdown)
194     salome.dsm.shutdownScopes()
195     my_runtime_yacs.fini( False )
196
197 if __name__ == "__main__":
198     from salome_utils import positionVerbosityOfLoggerRegardingState,setVerboseLevel,setVerbose
199     import argparse
200     parser = argparse.ArgumentParser()
201     parser.add_argument('xmlfilename',help = "XML file containing YACS schema to be executed")
202     parser.add_argument("-d", "--display", dest = "display", type=int, default=[0], nargs=1, help="Display dot files: 0=never to 3=very often")
203     parser.add_argument("-v", "--verbose", dest = "verbose",help="Produce verbose output", action='store_true')
204     parser.add_argument("--stop-on-error",dest="stop",help="Stop on first error", action='store_true')
205     parser.add_argument("-e","--dump-on-error",dest="dumpErrorFile", type=str, const='dumpErrorState.xml', default="", nargs='?', help="Stop on first error and dump state")
206     parser.add_argument("-g","--dump",dest="dump", type=int, const=60, default=0, nargs='?', help="dump state")
207     parser.add_argument("-kt", "--kerneltrace", dest = "kerneltrace",help="Produce verbose of SALOME/KERNEL", action='store_true')
208     parser.add_argument("-f","--dump-final", dest ="finalDump", type=str, const='finalDumpState.xml', default="", nargs='?', help="dump final state")
209     parser.add_argument("-l","--load-state", dest="loadState", type=str, default="", help="Load State from a previous partial execution")
210     parser.add_argument("-x","--save-xml-schema", dest="saveXMLSchema", type=str, const="saveSchema.xml", nargs='?', default="", help = "dump xml schema")
211     parser.add_argument("-t","--shutdown", dest = 'shutdown', type=int , default=1, help="Shutdown the schema: 0=no shutdown to 3=full shutdown")
212     parser.add_argument("--reset", dest = "reset", type=int , default = 0, help="Reset the schema before execution: 0=nothing, 1=reset error nodes to ready state")
213     parser.add_argument("-z","--donotsqueeze", dest = "donotsqueeze", help = "Desactivate squeeze memory optimization.", action='store_true')
214     parser.add_argument("-ip","--init-port", dest = 'init_port', type=str, help="Initialisation value of a port, specified as bloc.node.port=value.")
215     args = parser.parse_args()
216     args.display = args.display[0]
217     #
218     if args.verbose:
219       setVerbose( args.kerneltrace )
220       setVerboseLevel(logging.INFO)
221       positionVerbosityOfLoggerRegardingState()
222     #
223     proc = loadGraph( args.xmlfilename )
224     patchGraph( proc, not args.donotsqueeze, args.init_port.split(","), args.saveXMLSchema, args.loadState, args.reset, args.display)
225     executor = prepareExecution( proc, args.stop, args.dumpErrorFile)
226     executeGraph( executor, args.xmlfilename, proc, args.dump, args.finalDump, args.display)
227     destroyElementsGeneratedByExecutionOfGraph( proc, args.shutdown )