]> SALOME platform Git repositories - modules/paravis.git/blob - src/ENGINE/no_wrap/PARAVIS.py.in
Salome HOME
Merge branch 'abn/rearch'
[modules/paravis.git] / src / ENGINE / no_wrap / PARAVIS.py.in
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 SALOME
30 import PARAVIS_utils
31 import subprocess as subp
32 import socket
33 from time import sleep
34 import os
35 #from SALOME_utilities import MESSAGE
36
37 def MESSAGE(m):
38     os.system("echo \"%s\" >> /tmp/paravis_log.txt" % m)
39
40 class PARAVIS_Impl:
41     """ The core implementation (non CORBA, or Study related).
42         See the IDL for the documentation.
43     """
44     MAX_PVSERVER_PORT_TRIES = 10
45     PARAVIEW_ROOT_DIR = "@PARAVIEW_ROOT_DIR@"
46     PVSERVER_DEFAULT_PORT = 11111
47     
48     def __init__(self):
49         self.pvserverPort = -1
50         self.pvserverPop = None  # Popen object from subprocess module
51         self.lastTrace = ""
52         self.isGUIConnected = False  # whether there is an active connection from the GUI.
53             
54     """
55     Private. Identify a free port to launch the PVServer. 
56     """
57     def __getFreePort(self, startPort):
58         cnt = 0
59         currPort = startPort
60         while cnt < self.MAX_PVSERVER_PORT_TRIES:
61             try:
62                 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
63                 s.bind(('', currPort))
64                 s.close()
65                 return currPort
66             except socket.error as e:
67                 cnt += 1
68                 currPort += 1
69                 pass
70         raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
71                             "[PARAVIS] maximum number of tries to retrieve a free port for the PVServer",
72                             "PARAVIS.py", 0))
73                                            
74     def FindOrStartPVServer( self, port ):
75         MESSAGE("[PARAVIS] FindOrStartPVServer ...")
76         host = "localhost"
77         alive = True
78         if self.pvserverPop is None:
79             alive = False
80         else:
81             # Poll active server to check if still alive
82             self.pvserverPop.poll()
83             if not self.pvserverPop.returncode is None:  # server terminated
84                 alive = False
85         
86         if alive:
87             return "cs://%s:%d" % (host, self.pvserverPort)  
88           
89         # (else) Server not alive, start it:
90         pvServerPath = os.path.join(self.PARAVIEW_ROOT_DIR, 'bin', 'pvserver')
91         opt = []
92         if port <= 0:
93             port = self.__getFreePort(self.PVSERVER_DEFAULT_PORT)
94         self.pvserverPop = subp.Popen([pvServerPath, "--multi-clients", "--server-port=%d" % port])
95         sleep(3)  # Give some time to the server to start up to avoid 
96                   # ugly messages on the client side saying that it cannot connect
97         # Is PID still alive? If yes, consider that the launch was successful
98         self.pvserverPop.poll()
99         if self.pvserverPop.returncode is None:
100             success = True
101             self.pvserverPort = port
102             MESSAGE("[PARAVIS] pvserver successfully launched on port %d" % port)
103         else:
104             raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR,
105                             "[PARAVIS] Unable to start PVServer on port %d!" % port,
106                             "PARAVIS.py", 0))
107         return "cs://%s:%d" % (host, self.pvserverPort)
108
109     def StopPVServer( self ):
110         MESSAGE("[PARAVIS] Trying to stop PVServer (sending KILL) ...")
111         if not self.pvserverPop is None:
112             self.pvserverPop.poll()
113             if self.pvserverPop.returncode is None:
114                 # Terminate if still running:
115                 self.pvserverPop.terminate()
116                 MESSAGE("[PARAVIS] KILL signal sent.")
117                 return True
118         MESSAGE("[PARAVIS] Nothing to kill.")
119         return False
120     
121     def PutPythonTraceStringToEngine( self, t ):
122         self.lastTrace = t
123         
124     def GetPythonTraceString(self):
125         return self.lastTrace
126       
127     def SetGUIConnected( self, isConnected ):
128         self.isGUIConnected = isConnected
129         
130     def GetGUIConnected( self ):
131         return self.isGUIConnected
132     
133 class PARAVIS(PARAVIS_ORB__POA.PARAVIS_Gen,
134               SALOME_ComponentPy.SALOME_ComponentPy_i,
135               SALOME_DriverPy.SALOME_DriverPy_i,
136               PARAVIS_Impl):
137     """
138     Construct an instance of PARAVIS module engine.
139     The class PARAVIS implements CORBA interface PARAVIS_Gen (see PARAVIS_Gen.idl).
140     It is inherited from the classes SALOME_ComponentPy_i (implementation of
141     Engines::EngineComponent CORBA interface - SALOME component) and SALOME_DriverPy_i
142     (implementation of SALOMEDS::Driver CORBA interface - SALOME module's engine).
143     """
144     def __init__ ( self, orb, poa, contID, containerName, instanceName, 
145                    interfaceName ):
146         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
147                     contID, containerName, instanceName, interfaceName, 0)
148         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
149         PARAVIS_Impl.__init__(self)
150         #
151         self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
152         #
153
154     """ Override base class destroy to make sure we try to kill the pvserver
155         before leaving.
156     """
157     def destroy(self):    
158         self.StopPVServer()
159         # Invokes super():
160         SALOME_ComponentPy.destroy(self)
161       
162     """
163     Get version information.
164     """
165     def getVersion( self ):
166         import salome_version
167         return salome_version.getVersion("PARAVIS", True)
168
169     def GetIOR(self):
170         return PARAVIS_utils.getEngineIOR()
171
172     """
173     Create object.
174     """
175     def createObject( self, study, name ):
176         MESSAGE("createObject()")
177         self._createdNew = True # used for getModifiedData method
178         builder = study.NewBuilder()
179         father  = findOrCreateComponent( study )
180         object  = builder.NewObject( father )
181         attr    = builder.FindOrCreateAttribute( object, "AttributeName" )
182         attr.SetValue( name )
183         attr    = builder.FindOrCreateAttribute( object, "AttributeLocalID" )
184         attr.SetValue( PARAVIS_utils.objectID() )
185         pass
186
187     """
188     Dump module data to the Python script.
189     """
190     def DumpPython( self, study, isPublished, isMultiFile ):
191         MESSAGE("dumpPython()") 
192         abuffer = self.GetPythonTraceString().split("\n")
193         if isMultiFile:
194             abuffer       = [ "  " + s for s in abuffer ]
195             abuffer[0:0]  = [ "def RebuildData( theStudy ):" ]
196             abuffer      += [ "  pass" ]
197         abuffer += [ "\0" ]
198         return ("\n".join( abuffer ), 1)
199   
200     """
201     Import file to restore module data
202     """
203     def importData(self, studyId, dataContainer, options):
204       MESSAGE("importData()")
205       # get study by Id
206       obj = self._naming_service.Resolve("myStudyManager")
207       myStudyManager = obj._narrow(SALOMEDS.StudyManager)
208       study = myStudyManager.GetStudyByID(studyId)
209       # create all objects from the imported stream
210       stream = dataContainer.get()
211       for objname in stream.split("\n"):
212         if len(objname) != 0:
213           self.createObject(study, objname)
214       self._createdNew = False # to store the modification of the study information later
215       return ["objects"] # identifier what is in this file
216  
217     def getModifiedData(self, studyId):
218       MESSAGE("getModifiedData()")
219       if self._createdNew:
220         # get study by Id
221         obj = self._naming_service.Resolve("myStudyManager")
222         myStudyManager = obj._narrow(SALOMEDS.StudyManager)
223         study = myStudyManager.GetStudyByID(studyId)
224         # iterate all objects to get their names and store this information in stream
225         stream=""
226         father = study.FindComponent( moduleName() )
227         if father:
228             iter = study.NewChildIterator( father )
229             while iter.More():
230                 name = iter.Value().GetName()
231                 stream += name + "\n"
232                 iter.Next()
233         # store stream to the temporary file to send it in DataContainer
234         dataContainer = SALOME_DataContainerPy_i(stream, "", "objects", False, True)
235         aVar = dataContainer._this()
236         return [aVar]
237       return []