]> SALOME platform Git repositories - modules/kernel.git/blob - bin/PortManager.py
Salome HOME
update doc for salome command and application
[modules/kernel.git] / bin / PortManager.py
1 #!/usr/bin/env python
2 #  -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 #
22 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #
24 import os
25 import sys
26
27 try:
28   import cPickle as pickle #@UnusedImport
29 except:
30   import pickle #@Reimport
31
32 import logging
33 def createLogger():
34   logger = logging.getLogger(__name__)
35 #  logger.setLevel(logging.DEBUG)
36   logger.setLevel(logging.INFO)
37   ch = logging.StreamHandler()
38   ch.setLevel(logging.DEBUG)
39   formatter = logging.Formatter("%(levelname)s:%(threadName)s:%(message)s")
40   ch.setFormatter(formatter)
41   logger.addHandler(ch)
42   return logger
43 #
44 logger = createLogger()
45
46 #------------------------------------
47 # A file locker
48 def __acquire_lock(lock):
49   if sys.platform == "win32":
50     import msvcrt
51     # lock 1 byte: file is supposed to be zero-byte long
52     msvcrt.locking(lock.fileno(), msvcrt.LK_LOCK, 1)
53   else:
54     import fcntl
55     fcntl.flock(lock, fcntl.LOCK_EX)
56 #
57 def __release_lock(lock):
58   if sys.platform == "win32":
59     import msvcrt
60     msvcrt.locking(lock.fileno(), msvcrt.LK_UNLCK, 1)
61   else:
62     import fcntl
63     fcntl.flock(lock, fcntl.LOCK_UN)
64 #
65 #------------------------------------
66
67 def _getConfigurationFilename():
68   omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
69
70   from salome_utils import generateFileName
71   portmanager_config = generateFileName(omniorbUserPath,
72                                         prefix="omniORB",
73                                         suffix="PortManager",
74                                         extension="cfg",
75                                         hidden=True)
76   import tempfile
77   temp = tempfile.NamedTemporaryFile()
78   lock_file = os.path.join(os.path.dirname(temp.name), ".omniORB_PortManager.lock")
79   temp.close()
80
81   return (portmanager_config, lock_file)
82 #
83
84 def __isPortUsed(port, busy_ports):
85   return (port in busy_ports) or __isNetworkConnectionActiveOnPort(port)
86 #
87
88 def __isNetworkConnectionActiveOnPort(port):
89   # :NOTE: Under windows:
90   #        netstat options -l and -t are unavailable
91   #        grep command is unavailable
92   if sys.platform == "win32":
93     cmd = ['netstat','-a','-n','-p tcp']
94   else:
95     cmd = ['netstat','-ant']
96     pass
97
98   err = None
99   try:
100     from subprocess import Popen, PIPE, STDOUT
101     p = Popen(cmd, stdout=PIPE, stderr=STDOUT)
102     out, err = p.communicate()
103   except:
104     print "Error when trying to access active network connections."
105     if err: print err
106     import traceback
107     traceback.print_exc()
108     return False
109
110   import StringIO
111   buf = StringIO.StringIO(out)
112   ports = buf.readlines()
113   # search for TCP - LISTEN connections
114   import re
115   regObj = re.compile( ".*tcp.*:([0-9]+).*:.*listen", re.IGNORECASE );
116   for item in ports:
117     try:
118       p = int(regObj.match(item).group(1))
119       if p == port: return True
120     except:
121       pass
122   return False
123 #
124
125 def getPort(preferedPort=None):
126   logger.debug("GET PORT")
127
128   config_file, lock_file = _getConfigurationFilename()
129   oldmask = os.umask(0)
130   with open(lock_file, 'w') as lock:
131     # acquire lock
132     __acquire_lock(lock)
133
134     # read config
135     config = {'busy_ports':[]}
136     logger.debug("read configuration file")
137     try:
138       with open(config_file, 'r') as f:
139         config = pickle.load(f)
140     except:
141       logger.info("Problem loading PortManager file: %s"%config_file)
142       # In this case config dictionary is reset
143
144     logger.debug("load busy_ports: %s"%str(config["busy_ports"]))
145
146     # append port
147     busy_ports = config["busy_ports"]
148     port = preferedPort
149     if not port or __isPortUsed(port, busy_ports):
150       port = 2810
151       while __isPortUsed(port, busy_ports):
152         if port == 2810+100:
153           msg  = "\n"
154           msg += "Can't find a free port to launch omniNames\n"
155           msg += "Try to kill the running servers and then launch SALOME again.\n"
156           raise RuntimeError, msg
157         logger.debug("Port %s seems to be busy"%str(port))
158         if not port in config["busy_ports"]:
159           config["busy_ports"].append(port)
160         port = port + 1
161     logger.debug("found free port: %s"%str(port))
162     config["busy_ports"].append(port)
163
164     # write config
165     logger.debug("write busy_ports: %s"%str(config["busy_ports"]))
166     try:
167       with open(config_file, 'w') as f:
168         pickle.dump(config, f)
169     except IOError:
170       pass
171
172     # release lock
173     __release_lock(lock)
174   #
175
176   os.umask(oldmask)
177   logger.debug("get port: %s"%str(port))
178   return port
179 #
180
181 def releasePort(port):
182   port = int(port)
183   logger.debug("RELEASE PORT (%s)"%port)
184
185   config_file, lock_file = _getConfigurationFilename()
186   oldmask = os.umask(0)
187   with open(lock_file, 'w') as lock:
188     # acquire lock
189     __acquire_lock(lock)
190
191     # read config
192     config = {'busy_ports':[]}
193     logger.debug("read configuration file")
194     try:
195       with open(config_file, 'r') as f:
196         config = pickle.load(f)
197     except IOError: # empty file
198       pass
199
200     logger.debug("load busy_ports: %s"%str(config["busy_ports"]))
201
202     # remove port from list
203     busy_ports = config["busy_ports"]
204
205     if port in busy_ports:
206       busy_ports.remove(port)
207       config["busy_ports"] = busy_ports
208
209     # write config
210     logger.debug("write busy_ports: %s"%str(config["busy_ports"]))
211     try:
212       with open(config_file, 'w') as f:
213         pickle.dump(config, f)
214     except IOError:
215       pass
216
217     # release lock
218     __release_lock(lock)
219
220     logger.debug("released port port: %s"%str(port))
221
222   os.umask(oldmask)
223 #
224
225 def getBusyPorts():
226   busy_ports = []
227   config_file, lock_file = _getConfigurationFilename()
228   oldmask = os.umask(0)
229   with open(lock_file, 'w') as lock:
230     # acquire lock
231     __acquire_lock(lock)
232
233     # read config
234     config = {'busy_ports':[]}
235     logger.debug("read configuration file")
236     try:
237       with open(config_file, 'r') as f:
238         config = pickle.load(f)
239     except IOError: # empty file
240       pass
241
242     logger.debug("load busy_ports: %s"%str(config["busy_ports"]))
243
244     busy_ports = config["busy_ports"]
245     # release lock
246     __release_lock(lock)
247
248   os.umask(oldmask)
249   return busy_ports
250 #