Salome HOME
Re-wrote PARAVIS CORBA engine
[modules/paravis.git] / src / ENGINE / no_wrap / PARAVIS.py
1 # Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 #
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 #
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 #
20 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #
22 # Author : Adrien Bruneton (CEA)
23 #
24
25 import PARAVIS_ORB__POA
26 import SALOME_ComponentPy
27 import SALOME_DriverPy
28 import SALOMEDS
29 import PARAVIS_utils
30 import subprocess as subp
31 from time import sleep
32 import os
33 from SALOME_utilities import MESSAGE
34
35 class PARAVIS_Impl:
36     """ The core implementation (non CORBA, or Study related).
37         See the IDL for the documentation.
38     """
39     MAX_PVSERVER_PORT_TRIES = 10
40     
41     def __init__(self):
42         self.pvserverPort = -1
43         self.pvserverPop = None  # Popen object from subprocess module
44         self.liveConnection = None
45         self.lastTrace = ""
46     
47     """
48     Private. Keeps a connection to the PVServer to prevent 
49     it from stopping because all connections from GUI or scripts have been closed.
50     """
51     def __startKeepAlive(self, host, port):
52         print "[PARAVIS] 0 __startKeepAlive", host, port
53         from paraview import simple as pvs
54         self.liveConnection = pvs.Connect(host, port)
55         print "[PARAVIS] 1 __startKeepAlive", self.liveConnection
56                                            
57     def FindOrStartPVServer( self, port ):
58         print "[PARAVIS] FindOrStartPVServer"
59         MESSAGE("[PARAVIS] FindOrStartPVServer")
60         host = "localhost"
61         alive = True
62         if self.pvserverPop is None:
63             alive = False
64         else:
65             # Poll active server to check if still alive
66             self.pvserverPop.poll()
67             if not self.pvserverPop.returncode is None:  # server terminated
68                 alive = False
69         
70         if alive:
71             return "cs://%s:%d" % (host, self.pvserverPort)  
72           
73         # (else) Server not alive, start it:
74         pvRootDir = os.getenv("PARAVIEW_ROOT_DIR")
75         pvServerPath = os.path.join(pvRootDir, 'bin', 'pvserver')
76         opt = []
77         if port <= 0:
78             port = 11111
79         currPort = port
80         success = False
81         while not success and (currPort - port) < self.MAX_PVSERVER_PORT_TRIES:
82             self.pvserverPop = subp.Popen([pvServerPath, "--multi-clients", "--server-port=%d" % currPort])
83             sleep(2)
84             # Is PID still alive? If yes, consider that the launch was successful
85             self.pvserverPop.poll()
86             if self.pvserverPop.returncode is None:
87                 success = True
88                 self.pvserverPort = currPort
89                 MESSAGE("[PARAVIS] pvserver successfully launched on port %d" % currPort)
90             currPort += 1
91         if (currPort - port) == self.MAX_PVSERVER_PORT_TRIES:
92             self.pvserverPop = None
93             raise SalomeException("Unable to start PVServer after %d tries!" % self.MAX_PVSERVER_PORT_TRIES)
94 #         self.__startKeepAlive(host, self.pvserverPort)
95         return "cs://%s:%d" % (host, self.pvserverPort)
96
97     def StopPVServer( self ):
98         MESSAGE("[PARAVIS] Trying to stop PVServer (sending KILL) ...")
99         if not self.pvserverPop is None:
100             self.pvserverPop.poll()
101             if not self.pvserverPop.returncode is None:
102                 # Send KILL if still running:
103                 self.pvserverPop.kill()
104                 self.liveConnection = None
105     
106     def PutPythonTraceStringToEngine( self, t ):
107         self.lastTrace = t
108         
109     def GetPythonTraceString (self):
110         return self.lastTrace
111     
112 class PARAVIS(PARAVIS_ORB__POA.PARAVIS_Gen,
113               SALOME_ComponentPy.SALOME_ComponentPy_i,
114               SALOME_DriverPy.SALOME_DriverPy_i,
115               PARAVIS_Impl):
116   
117     """
118     Construct an instance of PARAVIS module engine.
119     The class PARAVIS implements CORBA interface PARAVIS_Gen (see PARAVIS_Gen.idl).
120     It is inherited from the classes SALOME_ComponentPy_i (implementation of
121     Engines::EngineComponent CORBA interface - SALOME component) and SALOME_DriverPy_i
122     (implementation of SALOMEDS::Driver CORBA interface - SALOME module's engine).
123     """
124     def __init__ ( self, orb, poa, contID, containerName, instanceName, 
125                    interfaceName ):
126         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
127                     contID, containerName, instanceName, interfaceName, 0)
128         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
129         PARAVIS_Impl.__init__(self)
130         #
131         self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
132         #
133
134     """ Override base class destroy to make sure we try to kill the pvserver
135         before leaving.
136     """
137     def destroy(self):    
138         self.StopPVServer()
139         # Invokes super():
140         SALOME_ComponentPy.destroy(self)
141       
142     """
143     Get version information.
144     """
145     def getVersion( self ):
146         import salome_version
147         return salome_version.getVersion("PARAVIS", True)
148
149     def GetIOR(self):
150         return PARAVIS_utils.getEngineIOR()
151
152     """
153     Create object.
154     """
155     def createObject( self, study, name ):
156         self._createdNew = True # used for getModifiedData method
157         builder = study.NewBuilder()
158         father  = findOrCreateComponent( study )
159         object  = builder.NewObject( father )
160         attr    = builder.FindOrCreateAttribute( object, "AttributeName" )
161         attr.SetValue( name )
162         attr    = builder.FindOrCreateAttribute( object, "AttributeLocalID" )
163         attr.SetValue( objectID() )
164         pass
165
166     """
167     Dump module data to the Python script.
168     """
169     def DumpPython( self, study, isPublished ):
170         print "@@@@ DumpPython"
171         abuffer = []
172         abuffer.append( "def RebuildData( theStudy ):" )
173         names = []
174         father = study.FindComponent( moduleName() )
175         if father:
176             iter = study.NewChildIterator( father )
177             while iter.More():
178                 name = iter.Value().GetName()
179                 if name: names.append( name )
180                 iter.Next()
181                 pass
182             pass
183         if names:
184             abuffer += [ "  from batchmode_salome import lcc" ]
185             abuffer += [ "  import PARAVIS_ORB" ]
186             abuffer += [ "  " ]
187             abuffer += [ "  pyhello = lcc.FindOrLoadComponent( 'FactoryServerPy', '%s' )" % moduleName() ]
188             abuffer += [ "  " ]
189             abuffer += [ "  pyhello.createObject( theStudy, '%s' )" % name for name in names ]
190             pass
191         abuffer += [ "  " ]
192         abuffer.append( "  pass" )
193         abuffer.append( "\0" )
194         return ("\n".join( abuffer ), 1)
195   
196     """
197     Import file to restore module data
198     """
199     def importData(self, studyId, dataContainer, options):
200       print "@@@@ ImportData"
201       # get study by Id
202       obj = self._naming_service.Resolve("myStudyManager")
203       myStudyManager = obj._narrow(SALOMEDS.StudyManager)
204       study = myStudyManager.GetStudyByID(studyId)
205       # create all objects from the imported stream
206       stream = dataContainer.get()
207       for objname in stream.split("\n"):
208         if len(objname) != 0:
209           self.createObject(study, objname)
210       self._createdNew = False # to store the modification of the study information later
211       return ["objects"] # identifier what is in this file
212  
213     def getModifiedData(self, studyId):
214       print "@@@@ GetModifiedData"
215       if self._createdNew:
216         # get study by Id
217         obj = self._naming_service.Resolve("myStudyManager")
218         myStudyManager = obj._narrow(SALOMEDS.StudyManager)
219         study = myStudyManager.GetStudyByID(studyId)
220         # iterate all objects to get their names and store this information in stream
221         stream=""
222         father = study.FindComponent( moduleName() )
223         if father:
224             iter = study.NewChildIterator( father )
225             while iter.More():
226                 name = iter.Value().GetName()
227                 stream += name + "\n"
228                 iter.Next()
229         # store stream to the temporary file to send it in DataContainer
230         dataContainer = SALOME_DataContainerPy_i(stream, "", "objects", False, True)
231         aVar = dataContainer._this()
232         return [aVar]
233       return []