1 # Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 # Author : Adrien Bruneton (CEA)
25 import PVSERVER_ORB__POA
26 import SALOME_ComponentPy
27 import SALOME_DriverPy
31 import subprocess as subp
33 from time import sleep
35 #from SALOME_utilities import MESSAGE
39 #os.system("echo \"%s\" >> /tmp/paravis_log.txt" % m)
42 """ The core implementation (non CORBA, or Study related).
43 See the IDL for the documentation.
45 MAX_PVSERVER_PORT_TRIES = 1000
46 PVSERVER_DEFAULT_PORT = 11111
49 self.pvserverPort = -1
50 self.pvserverPop = None # Popen object from subprocess module
52 self.isGUIConnected = False # whether there is an active connection from the GUI.
57 raise Exception("PVSERVER_Impl.__init__ : \"import paraview\" failed !")
58 # deduce dynamically PARAVIEW_ROOT_DIR from the paraview module location
59 self.PARAVIEW_ROOT_DIR = None
60 ZE_KEY_TO_FIND_PV_ROOT_DIR="lib"
61 li=tmp.split(os.path.sep) ; li.reverse()
62 if ZE_KEY_TO_FIND_PV_ROOT_DIR not in li:
63 raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
64 "PVSERVER_Impl.__init__ : error during dynamic deduction of PARAVIEW_ROOT_DIR : Loc of paraview module is \"%s\" ! \"%s\" is supposed to be the key to deduce it !"%(tmp,ZE_KEY_TO_FIND_PV_ROOT_DIR),
66 li=li[li.index("lib")+1:] ; li.reverse()
67 self.PARAVIEW_ROOT_DIR = os.path.sep.join(li)
70 Private. Identify a free port to launch the PVServer.
72 def __getFreePort(self, startPort):
75 while cnt < self.MAX_PVSERVER_PORT_TRIES:
77 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
78 s.bind(('', currPort))
81 except socket.error as e:
85 raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
86 "[PVSERVER] maximum number of tries to retrieve a free port for the PVServer",
89 def FindOrStartPVServer( self, port ):
90 MESSAGE("[PVSERVER] FindOrStartPVServer ...")
93 if self.pvserverPop is None:
96 # Poll active server to check if still alive
97 self.pvserverPop.poll()
98 if not self.pvserverPop.returncode is None: # server terminated
102 return "cs://%s:%d" % (host, self.pvserverPort)
104 # (else) Server not alive, start it:
105 pvServerPath = os.path.join(self.PARAVIEW_ROOT_DIR, 'bin', 'pvserver')
108 port = self.__getFreePort(self.PVSERVER_DEFAULT_PORT)
109 self.pvserverPop = subp.Popen([pvServerPath, "--multi-clients", "--server-port=%d" % port])
110 sleep(3) # Give some time to the server to start up to avoid
111 # ugly messages on the client side saying that it cannot connect
112 # Is PID still alive? If yes, consider that the launch was successful
113 self.pvserverPop.poll()
114 if self.pvserverPop.returncode is None:
116 self.pvserverPort = port
117 MESSAGE("[PVSERVER] pvserver successfully launched on port %d" % port)
119 raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
120 "[PVSERVER] Unable to start PVServer on port %d!" % port,
122 return "cs://%s:%d" % (host, self.pvserverPort)
124 def StopPVServer( self ):
125 MESSAGE("[PVSERVER] Trying to stop PVServer (sending KILL) ...")
126 if not self.pvserverPop is None:
127 self.pvserverPop.poll()
128 if self.pvserverPop.returncode is None:
129 # Terminate if still running:
130 self.pvserverPop.terminate()
131 MESSAGE("[PVSERVER] KILL signal sent.")
133 MESSAGE("[PVSERVER] Nothing to kill.")
136 def PutPythonTraceStringToEngine( self, t ):
139 def GetPythonTraceString(self):
140 return self.lastTrace
142 def SetGUIConnected( self, isConnected ):
143 self.isGUIConnected = isConnected
145 def GetGUIConnected( self ):
146 return self.isGUIConnected
148 class PVSERVER(PVSERVER_ORB__POA.PVSERVER_Gen,
149 SALOME_ComponentPy.SALOME_ComponentPy_i,
150 SALOME_DriverPy.SALOME_DriverPy_i,
153 Construct an instance of PVSERVER module engine.
154 The class PVSERVER implements CORBA interface PVSERVER_Gen (see PVSERVER_Gen.idl).
155 It is inherited from the classes SALOME_ComponentPy_i (implementation of
156 Engines::EngineComponent CORBA interface - SALOME component) and SALOME_DriverPy_i
157 (implementation of SALOMEDS::Driver CORBA interface - SALOME module's engine).
159 def __init__ ( self, orb, poa, contID, containerName, instanceName,
161 SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
162 contID, containerName, instanceName, interfaceName, 0)
163 SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
164 PVSERVER_Impl.__init__(self)
166 self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
169 """ Override base class destroy to make sure we try to kill the pvserver
175 SALOME_ComponentPy.destroy(self)
178 Get version information.
180 def getVersion( self ):
181 import salome_version
182 return salome_version.getVersion("PARAVIS", True)
185 return PVSERVER_utils.getEngineIOR()
190 def createObject( self, study, name ):
191 MESSAGE("createObject()")
192 self._createdNew = True # used for getModifiedData method
193 builder = study.NewBuilder()
194 father = findOrCreateComponent( study )
195 object = builder.NewObject( father )
196 attr = builder.FindOrCreateAttribute( object, "AttributeName" )
197 attr.SetValue( name )
198 attr = builder.FindOrCreateAttribute( object, "AttributeLocalID" )
199 attr.SetValue( PVSERVER_utils.objectID() )
203 Dump module data to the Python script.
205 def DumpPython( self, study, isPublished, isMultiFile ):
206 MESSAGE("dumpPython()")
207 abuffer = self.GetPythonTraceString().split("\n")
209 abuffer = [ " " + s for s in abuffer ]
210 abuffer[0:0] = [ "def RebuildData( theStudy ):" ]
211 abuffer += [ " pass" ]
213 return ("\n".join( abuffer ), 1)
216 Import file to restore module data
218 def importData(self, studyId, dataContainer, options):
219 MESSAGE("importData()")
221 obj = self._naming_service.Resolve("myStudyManager")
222 myStudyManager = obj._narrow(SALOMEDS.StudyManager)
223 study = myStudyManager.GetStudyByID(studyId)
224 # create all objects from the imported stream
225 stream = dataContainer.get()
226 for objname in stream.split("\n"):
227 if len(objname) != 0:
228 self.createObject(study, objname)
229 self._createdNew = False # to store the modification of the study information later
230 return ["objects"] # identifier what is in this file
232 def getModifiedData(self, studyId):
233 MESSAGE("getModifiedData()")
236 obj = self._naming_service.Resolve("myStudyManager")
237 myStudyManager = obj._narrow(SALOMEDS.StudyManager)
238 study = myStudyManager.GetStudyByID(studyId)
239 # iterate all objects to get their names and store this information in stream
241 father = study.FindComponent( moduleName() )
243 iter = study.NewChildIterator( father )
245 name = iter.Value().GetName()
246 stream += name + "\n"
248 # store stream to the temporary file to send it in DataContainer
249 dataContainer = SALOME_DataContainerPy_i(stream, "", "objects", False, True)
250 aVar = dataContainer._this()