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 PARAVIS_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 = 10
46 PARAVIEW_ROOT_DIR = "@PARAVIEW_ROOT_DIR@"
47 PVSERVER_DEFAULT_PORT = 11111
50 self.pvserverPort = -1
51 self.pvserverPop = None # Popen object from subprocess module
53 self.isGUIConnected = False # whether there is an active connection from the GUI.
56 Private. Identify a free port to launch the PVServer.
58 def __getFreePort(self, startPort):
61 while cnt < self.MAX_PVSERVER_PORT_TRIES:
63 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
64 s.bind(('', currPort))
67 except socket.error as e:
71 raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
72 "[PARAVIS] maximum number of tries to retrieve a free port for the PVServer",
75 def FindOrStartPVServer( self, port ):
76 MESSAGE("[PARAVIS] FindOrStartPVServer ...")
79 if self.pvserverPop is None:
82 # Poll active server to check if still alive
83 self.pvserverPop.poll()
84 if not self.pvserverPop.returncode is None: # server terminated
88 return "cs://%s:%d" % (host, self.pvserverPort)
90 # (else) Server not alive, start it:
91 pvServerPath = os.path.join(self.PARAVIEW_ROOT_DIR, 'bin', 'pvserver')
94 port = self.__getFreePort(self.PVSERVER_DEFAULT_PORT)
95 self.pvserverPop = subp.Popen([pvServerPath, "--multi-clients", "--server-port=%d" % port])
96 sleep(3) # Give some time to the server to start up to avoid
97 # ugly messages on the client side saying that it cannot connect
98 # Is PID still alive? If yes, consider that the launch was successful
99 self.pvserverPop.poll()
100 if self.pvserverPop.returncode is None:
102 self.pvserverPort = port
103 MESSAGE("[PARAVIS] pvserver successfully launched on port %d" % port)
105 raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
106 "[PARAVIS] Unable to start PVServer on port %d!" % port,
108 return "cs://%s:%d" % (host, self.pvserverPort)
110 def StopPVServer( self ):
111 MESSAGE("[PARAVIS] Trying to stop PVServer (sending KILL) ...")
112 if not self.pvserverPop is None:
113 self.pvserverPop.poll()
114 if self.pvserverPop.returncode is None:
115 # Terminate if still running:
116 self.pvserverPop.terminate()
117 MESSAGE("[PARAVIS] KILL signal sent.")
119 MESSAGE("[PARAVIS] Nothing to kill.")
122 def PutPythonTraceStringToEngine( self, t ):
125 def GetPythonTraceString(self):
126 return self.lastTrace
128 def SetGUIConnected( self, isConnected ):
129 self.isGUIConnected = isConnected
131 def GetGUIConnected( self ):
132 return self.isGUIConnected
134 class PARAVIS(PARAVIS_ORB__POA.PARAVIS_Gen,
135 SALOME_ComponentPy.SALOME_ComponentPy_i,
136 SALOME_DriverPy.SALOME_DriverPy_i,
139 Construct an instance of PARAVIS module engine.
140 The class PARAVIS implements CORBA interface PARAVIS_Gen (see PARAVIS_Gen.idl).
141 It is inherited from the classes SALOME_ComponentPy_i (implementation of
142 Engines::EngineComponent CORBA interface - SALOME component) and SALOME_DriverPy_i
143 (implementation of SALOMEDS::Driver CORBA interface - SALOME module's engine).
145 def __init__ ( self, orb, poa, contID, containerName, instanceName,
147 SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
148 contID, containerName, instanceName, interfaceName, 0)
149 SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
150 PARAVIS_Impl.__init__(self)
152 self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
155 """ Override base class destroy to make sure we try to kill the pvserver
161 SALOME_ComponentPy.destroy(self)
164 Get version information.
166 def getVersion( self ):
167 import salome_version
168 return salome_version.getVersion("PARAVIS", True)
171 return PARAVIS_utils.getEngineIOR()
176 def createObject( self, study, name ):
177 MESSAGE("createObject()")
178 self._createdNew = True # used for getModifiedData method
179 builder = study.NewBuilder()
180 father = findOrCreateComponent( study )
181 object = builder.NewObject( father )
182 attr = builder.FindOrCreateAttribute( object, "AttributeName" )
183 attr.SetValue( name )
184 attr = builder.FindOrCreateAttribute( object, "AttributeLocalID" )
185 attr.SetValue( PARAVIS_utils.objectID() )
189 Dump module data to the Python script.
191 def DumpPython( self, study, isPublished, isMultiFile ):
192 MESSAGE("dumpPython()")
193 abuffer = self.GetPythonTraceString().split("\n")
195 abuffer = [ " " + s for s in abuffer ]
196 abuffer[0:0] = [ "def RebuildData( theStudy ):" ]
197 abuffer += [ " pass" ]
199 return ("\n".join( abuffer ), 1)
202 Import file to restore module data
204 def importData(self, studyId, dataContainer, options):
205 MESSAGE("importData()")
207 obj = self._naming_service.Resolve("myStudyManager")
208 myStudyManager = obj._narrow(SALOMEDS.StudyManager)
209 study = myStudyManager.GetStudyByID(studyId)
210 # create all objects from the imported stream
211 stream = dataContainer.get()
212 for objname in stream.split("\n"):
213 if len(objname) != 0:
214 self.createObject(study, objname)
215 self._createdNew = False # to store the modification of the study information later
216 return ["objects"] # identifier what is in this file
218 def getModifiedData(self, studyId):
219 MESSAGE("getModifiedData()")
222 obj = self._naming_service.Resolve("myStudyManager")
223 myStudyManager = obj._narrow(SALOMEDS.StudyManager)
224 study = myStudyManager.GetStudyByID(studyId)
225 # iterate all objects to get their names and store this information in stream
227 father = study.FindComponent( moduleName() )
229 iter = study.NewChildIterator( father )
231 name = iter.Value().GetName()
232 stream += name + "\n"
234 # store stream to the temporary file to send it in DataContainer
235 dataContainer = SALOME_DataContainerPy_i(stream, "", "objects", False, True)
236 aVar = dataContainer._this()