2
2
3
3
from ..port_manager import PortManager
4
4
from ..exceptions import PortForException
5
+ from ..import consts
5
6
7
+ import os
6
8
import threading
7
9
import random
8
10
import typing
@@ -15,6 +17,8 @@ class PortManager__Generic(PortManager):
15
17
_available_ports :typing .Set [int ]
16
18
_reserved_ports :typing .Set [int ]
17
19
20
+ _lock_dir :str
21
+
18
22
def __init__ (self ,os_ops :OsOperations ):
19
23
assert os_ops is not None
20
24
assert isinstance (os_ops ,OsOperations )
@@ -23,6 +27,12 @@ def __init__(self, os_ops: OsOperations):
23
27
self ._available_ports :typing .Set [int ]= set (range (1024 ,65535 ))
24
28
self ._reserved_ports :typing .Set [int ]= set ()
25
29
30
+ temp_dir = os_ops .get_tempdir ()
31
+ assert type (temp_dir )== str # noqa: E721
32
+ self ._lock_dir = os .path .join (temp_dir ,consts .TMP_TESTGRES_PORTS )
33
+ assert type (self ._lock_dir )== str # noqa: E721
34
+ os_ops .makedirs (self ._lock_dir )
35
+
26
36
def reserve_port (self )-> int :
27
37
assert self ._guard is not None
28
38
assert type (self ._available_ports )== set # noqa: E721t
@@ -41,9 +51,23 @@ def reserve_port(self) -> int:
41
51
if not self ._os_ops .is_port_free (port ):
42
52
continue
43
53
44
- self ._reserved_ports .add (port )
45
- self ._available_ports .discard (port )
54
+ try :
55
+ lock_path = self .helper__make_lock_path (port )
56
+ self ._os_ops .makedir (lock_path )
57
+ except :# noqa: 722
58
+ continue
59
+
60
+ assert self ._os_ops .path_exists (lock_path )
61
+
62
+ try :
63
+ self ._reserved_ports .add (port )
64
+ except :# noqa: 722
65
+ assert not (port in self ._reserved_ports )
66
+ self ._os_ops .rmdir (lock_path )
67
+ raise
68
+
46
69
assert port in self ._reserved_ports
70
+ self ._available_ports .discard (port )
47
71
assert not (port in self ._available_ports )
48
72
return port
49
73
@@ -55,10 +79,26 @@ def release_port(self, number: int) -> None:
55
79
assert self ._guard is not None
56
80
assert type (self ._reserved_ports )== set # noqa: E721
57
81
82
+ lock_path = self .helper__make_lock_path (number )
83
+
58
84
with self ._guard :
59
85
assert number in self ._reserved_ports
60
86
assert not (number in self ._available_ports )
61
87
self ._available_ports .add (number )
62
88
self ._reserved_ports .discard (number )
63
89
assert not (number in self ._reserved_ports )
64
90
assert number in self ._available_ports
91
+
92
+ assert isinstance (self ._os_ops ,OsOperations )
93
+ assert self ._os_ops .path_exists (lock_path )
94
+ self ._os_ops .rmdir (lock_path )
95
+
96
+ return
97
+
98
+ def helper__make_lock_path (self ,port_number :int )-> str :
99
+ assert type (port_number )== int # noqa: E721
100
+ assert type (self ._lock_dir )== str # noqa: E721
101
+
102
+ result = os .path .join (self ._lock_dir ,str (port_number )+ ".lock" )
103
+ assert type (result )== str # noqa: E721
104
+ return result