2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2007-2021 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 from socket import AF_INET, SOCK_STREAM
31 import cPickle as pickle #@UnusedImport
33 import pickle #@Reimport
35 __PORT_MIN_NUMBER = 2810
36 __PORT_MAX_NUMBER = 2910
40 logger = logging.getLogger(__name__)
41 #logger.setLevel(logging.DEBUG)
42 logger.setLevel(logging.INFO)
43 ch = logging.StreamHandler()
44 ch.setLevel(logging.DEBUG)
45 formatter = logging.Formatter("%(levelname)s:%(threadName)s:%(pathname)s[%(lineno)s]%(message)s")
46 ch.setFormatter(formatter)
50 logger = createLogger()
52 #------------------------------------
54 def __acquire_lock(lock):
55 logger.debug("ACQUIRE LOCK")
56 if sys.platform == "win32":
58 # lock 1 byte: file is supposed to be zero-byte long
59 msvcrt.locking(lock.fileno(), msvcrt.LK_LOCK, 1)
62 fcntl.flock(lock, fcntl.LOCK_EX)
63 logger.debug("LOCK ACQUIRED")
65 def __release_lock(lock):
66 logger.debug("RELEASE LOCK")
67 if sys.platform == "win32":
69 msvcrt.locking(lock.fileno(), msvcrt.LK_UNLCK, 1)
72 fcntl.flock(lock, fcntl.LOCK_UN)
73 logger.debug("LOCK RELEASED")
75 #------------------------------------
77 def _getConfigurationFilename():
78 omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
80 from salome_utils import generateFileName
81 portmanager_config = generateFileName(omniorbUserPath,
87 temp = tempfile.NamedTemporaryFile()
88 lock_file = os.path.join(os.path.dirname(temp.name), ".salome", ".PortManager.lock")
91 os.makedirs(os.path.dirname(lock_file))
98 return (portmanager_config, lock_file)
101 def __isPortUsed(port, config):
103 for ports in config.values():
105 return (port in busy_ports) or __isNetworkConnectionActiveOnPort(port)
108 def __isNetworkConnectionActiveOnPort(port):
110 return port in [c.laddr.port for c in psutil.net_connections(kind='inet') if \
111 (c.family, c.type, c.status) == (AF_INET, SOCK_STREAM, "LISTEN")]
114 def getPort(preferredPort=None):
115 logger.debug("GET PORT")
117 config_file, lock_file = _getConfigurationFilename()
118 oldmask = os.umask(0)
119 with open(lock_file, 'wb') as lock:
125 logger.debug("read configuration file")
127 with open(config_file, 'rb') as f:
128 config = pickle.load(f)
130 logger.debug("Problem loading PortManager file: %s"%config_file)
131 # In this case config dictionary is reset
133 logger.debug("load config: %s"%str(config))
134 appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown")
138 config[appli_path] = []
142 if not port or __isPortUsed(port, config):
143 port = __PORT_MIN_NUMBER
144 while __isPortUsed(port, config):
145 if port == __PORT_MAX_NUMBER:
147 msg += "Can't find a free port to launch omniNames\n"
148 msg += "Try to kill the running servers and then launch SALOME again.\n"
149 raise RuntimeError(msg)
150 logger.debug("Port %s seems to be busy"%str(port))
152 logger.debug("found free port: %s"%str(port))
153 config[appli_path].append(port)
156 logger.debug("write config: %s"%str(config))
158 with open(config_file, 'wb') as f:
159 pickle.dump(config, f, protocol=0)
168 logger.debug("get port: %s"%str(port))
172 def releasePort(port):
174 logger.debug("RELEASE PORT (%s)"%port)
176 config_file, lock_file = _getConfigurationFilename()
177 oldmask = os.umask(0)
178 with open(lock_file, 'wb') as lock:
184 logger.debug("read configuration file")
186 with open(config_file, 'rb') as f:
187 config = pickle.load(f)
188 except IOError: # empty file
191 logger.debug("load config: %s"%str(config))
192 appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown")
196 config[appli_path] = []
198 # remove port from list
199 ports_info = config[appli_path]
200 config[appli_path] = [x for x in ports_info if x != port]
203 logger.debug("write config: %s"%str(config))
205 with open(config_file, 'wb') as f:
206 pickle.dump(config, f, protocol=0)
213 logger.debug("released port port: %s"%str(port))
219 config_file, lock_file = _getConfigurationFilename()
220 oldmask = os.umask(0)
221 with open(lock_file, 'wb') as lock:
227 logger.debug("read configuration file")
229 with open(config_file, 'rb') as f:
230 config = pickle.load(f)
231 except IOError: # empty file
234 logger.debug("load config: %s"%str(config))
235 appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown")
239 config[appli_path] = []
241 # Scan all possible ports to determine which ones are owned by other applications
242 ports_info = { 'this': [], 'other': [] }
243 my_busy_ports = config[appli_path]
244 for port in range(__PORT_MIN_NUMBER, __PORT_MAX_NUMBER):
245 if __isPortUsed(port, config):
246 logger.debug("Port %s seems to be busy"%str(port))
247 if port in my_busy_ports:
248 ports_info["this"].append(port)
250 ports_info["other"].append(port)
252 logger.debug("all busy_ports: %s"%str(ports_info))
254 sorted_ports = { 'this': sorted(ports_info['this']),
255 'other': sorted(ports_info['other']) }