2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
5 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
22 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
28 import cPickle as pickle #@UnusedImport
30 import pickle #@Reimport
32 __PORT_MIN_NUMBER = 2810
33 __PORT_MAX_NUMBER = 2910
37 logger = logging.getLogger(__name__)
38 #logger.setLevel(logging.DEBUG)
39 logger.setLevel(logging.INFO)
40 ch = logging.StreamHandler()
41 ch.setLevel(logging.DEBUG)
42 formatter = logging.Formatter("%(levelname)s:%(threadName)s:%(pathname)s[%(lineno)s]%(message)s")
43 ch.setFormatter(formatter)
47 logger = createLogger()
49 #------------------------------------
51 def __acquire_lock(lock):
52 logger.debug("ACQUIRE LOCK")
53 if sys.platform == "win32":
55 # lock 1 byte: file is supposed to be zero-byte long
56 msvcrt.locking(lock.fileno(), msvcrt.LK_LOCK, 1)
59 fcntl.flock(lock, fcntl.LOCK_EX)
60 logger.debug("LOCK ACQUIRED")
62 def __release_lock(lock):
63 logger.debug("RELEASE LOCK")
64 if sys.platform == "win32":
66 msvcrt.locking(lock.fileno(), msvcrt.LK_UNLCK, 1)
69 fcntl.flock(lock, fcntl.LOCK_UN)
70 logger.debug("LOCK RELEASED")
72 #------------------------------------
74 def _getConfigurationFilename():
75 omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
77 from salome_utils import generateFileName
78 portmanager_config = generateFileName(omniorbUserPath,
84 temp = tempfile.NamedTemporaryFile()
85 lock_file = os.path.join(os.path.dirname(temp.name), ".salome_PortManager.lock")
87 with open(lock_file, 'wb'):
93 return (portmanager_config, lock_file)
96 def __isPortUsed(port, config):
98 for ports in config.values():
100 return (port in busy_ports) or __isNetworkConnectionActiveOnPort(port)
103 def __isNetworkConnectionActiveOnPort(port):
104 # :NOTE: Under windows:
105 # netstat options -l and -t are unavailable
106 # grep command is unavailable
107 if sys.platform == "win32":
108 cmd = ['netstat','-a','-n','-p','tcp']
110 cmd = ['netstat','-ant']
115 from subprocess import Popen, PIPE, STDOUT
116 p = Popen(cmd, stdout=PIPE, stderr=STDOUT)
117 out, err = p.communicate()
119 print("Error when trying to access active network connections.")
122 traceback.print_exc()
125 from io import StringIO
126 buf = StringIO(out.decode('utf-8', 'ignore'))
127 ports = buf.readlines()
128 # search for TCP - LISTEN connections
130 regObj = re.compile( ".*tcp.*:([0-9]+).*:.*listen", re.IGNORECASE );
133 p = int(regObj.match(item).group(1))
134 if p == port: return True
140 def getPort(preferredPort=None):
141 logger.debug("GET PORT")
143 config_file, lock_file = _getConfigurationFilename()
144 oldmask = os.umask(0)
145 with open(lock_file, 'rb') as lock:
151 logger.debug("read configuration file")
153 with open(config_file, 'rb') as f:
154 config = pickle.load(f)
156 logger.info("Problem loading PortManager file: %s"%config_file)
157 # In this case config dictionary is reset
159 logger.debug("load config: %s"%str(config))
160 appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown")
164 config[appli_path] = []
168 if not port or __isPortUsed(port, config):
169 port = __PORT_MIN_NUMBER
170 while __isPortUsed(port, config):
171 if port == __PORT_MAX_NUMBER:
173 msg += "Can't find a free port to launch omniNames\n"
174 msg += "Try to kill the running servers and then launch SALOME again.\n"
175 raise RuntimeError(msg)
176 logger.debug("Port %s seems to be busy"%str(port))
178 logger.debug("found free port: %s"%str(port))
179 config[appli_path].append(port)
182 logger.debug("write config: %s"%str(config))
184 with open(config_file, 'wb') as f:
185 pickle.dump(config, f, protocol=0)
194 logger.debug("get port: %s"%str(port))
198 def releasePort(port):
200 logger.debug("RELEASE PORT (%s)"%port)
202 config_file, lock_file = _getConfigurationFilename()
203 oldmask = os.umask(0)
204 with open(lock_file, 'rb') as lock:
210 logger.debug("read configuration file")
212 with open(config_file, 'rb') as f:
213 config = pickle.load(f)
214 except IOError: # empty file
217 logger.debug("load config: %s"%str(config))
218 appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown")
222 config[appli_path] = []
224 # remove port from list
225 ports_info = config[appli_path]
226 config[appli_path] = [x for x in ports_info if x != port]
229 logger.debug("write config: %s"%str(config))
231 with open(config_file, 'wb') as f:
232 pickle.dump(config, f, protocol=0)
239 logger.debug("released port port: %s"%str(port))
245 config_file, lock_file = _getConfigurationFilename()
246 oldmask = os.umask(0)
247 with open(lock_file, 'wb') as lock:
253 logger.debug("read configuration file")
255 with open(config_file, 'rb') as f:
256 config = pickle.load(f)
257 except IOError: # empty file
260 logger.debug("load config: %s"%str(config))
261 appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown")
265 config[appli_path] = []
267 # Scan all possible ports to determine which ones are owned by other applications
268 ports_info = { 'this': [], 'other': [] }
269 my_busy_ports = config[appli_path]
270 for port in range(__PORT_MIN_NUMBER, __PORT_MAX_NUMBER):
271 if __isPortUsed(port, config):
272 logger.debug("Port %s seems to be busy"%str(port))
273 if port in my_busy_ports:
274 ports_info["this"].append(port)
276 ports_info["other"].append(port)
278 logger.debug("all busy_ports: %s"%str(ports_info))
280 sorted_ports = { 'this': sorted(ports_info['this']),
281 'other': sorted(ports_info['other']) }