8000 NodeApp is refactored (#278) · postgrespro/testgres@bbbec3e · GitHub
[go: up one dir, main page]

Skip to content

Commit bbbec3e

Browse files
NodeApp is refactored (#278)
This patch contains a lot of improvements for NodeApp. Fixes and changes: - NodeApp was moved to own py-file - NodeApp::os_ops is RO-property - NodeApp::test_path is RO-property - NodeApp::nodes_to_cleanup is RO-property - NodeApp supports an external port manager object - NodeApp.make_simple changes input parameter initdb_params #267 - NodeApp::make_empty has a problem with base_dir = None #277 - NodeApp.make_empty must pass os_ops and port_manager to nodes #265 Also - OsOperations::create_clone is added - PostgresNode::release_resources is added
1 parent 69f8d49 commit bbbec3e

File tree

8 files changed

+670
-189
lines changed

8 files changed

+670
-189
lines changed

testgres/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@
3333
ProcessType, \
3434
DumpFormat
3535

36-
from .node import PostgresNode, NodeApp
36+
from .node import PostgresNode
3737
from .node import PortManager
38+
from .node_app import NodeApp
3839

3940
from .utils import \
4041
reserve_port, \
@@ -62,8 +63,9 @@
6263
"NodeConnection", "DatabaseError", "InternalError", "ProgrammingError", "OperationalError",
6364
"TestgresException", "ExecUtilException", "QueryException", "TimeoutException", "CatchUpException", "StartNodeException", "InitNodeException", "BackupException", "InvalidOperationException",
6465
"XLogMethod", "IsolationLevel", "NodeStatus", "ProcessType", "DumpFormat",
65-
"PostgresNode", "NodeApp",
66-
"PortManager",
66+
NodeApp.__name__,
67+
PostgresNode.__name__,
68+
PortManager.__name__,
6769
"reserve_port", "release_port", "bound_ports", "get_bin_path", "get_pg_config", "get_pg_version",
6870
"First", "Any",
6971
"OsOperations", "LocalOperations", "RemoteOperations", "ConnectionParams"

testgres/node.py

Lines changed: 26 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import signal
88
import subprocess
99
import threading
10-
import tempfile
11-
import platform
1210
from queue import Queue
1311

1412
import time
@@ -692,9 +690,6 @@ def _try_shutdown(self, max_attempts, with_force=False):
692690
ps_output,
693691
ps_command)
694692

695-
def _release_resources(self):
696-
self.free_port()
697-
698693
@staticmethod
699694
def _throw_bugcheck__unexpected_result_of_ps(result, cmd):
700695
assert type(result) == str # noqa: E721
@@ -1326,25 +1321,18 @@ def pg_ctl(self, params):
13261321

13271322
return execute_utility2(self.os_ops, _params, self.utils_log_file)
13281323

1324+
def release_resources(self):
1325+
"""
1326+
Release resorces owned by this node.
1327+
"""
1328+
return self._release_resources()
1329+
13291330
def free_port(self):
13301331
"""
13311332
Reclaim port owned by this node.
13321333
NOTE: this method does not release manually defined port but reset it.
13331334
"""
1334-
assert type(self._should_free_port) == bool # noqa: E721
1335-
1336-
if not self._should_free_port:
1337-
self._port = None
1338-
else:
1339-
assert type(self._port) == int # noqa: E721
1340-
1341-
assert self._port_manager is not None
1342-
assert isinstance(self._port_manager, PortManager)
1343-
1344-
port = self._port
1345-
self._should_free_port = False
1346-
self._port = None
1347-
self._port_manager.release_port(port)
1335+
return self._free_port()
13481336

13491337
def cleanup(self, max_attempts=3, full=False, release_resources=False):
13501338
"""
@@ -2158,6 +2146,25 @@ def upgrade_from(self, old_node, options=None, expect_error=False):
21582146

21592147
return self.os_ops.exec_command(upgrade_command, expect_error=expect_error)
21602148

2149+
def _release_resources(self):
2150+
self._free_port()
2151+
2152+
def _free_port(self):
2153+
assert type(self._should_free_port) == bool # noqa: E721
2154+
2155+
if not self._should_free_port:
2156+
self._port = None
2157+
else:
2158+
assert type(self._port) == int # noqa: E721
2159+
2160+
assert self._port_manager is not None
2161+
assert isinstance(self._port_manager, PortManager)
2162+
2163+
port = self._port
2164+
self._should_free_port = False
2165+
self._port = None
2166+
self._port_manager.release_port(port)
2167+
21612168
def _get_bin_path(self, filename):
21622169
assert self._os_ops is not None
21632170
assert isinstance(self._os_ops, OsOperations)
@@ -2352,164 +2359,3 @@ def delect_port_conflict(log_reader: PostgresNodeLogReader) -> bool:
23522359
return True
23532360

23542361
return False
2355-
2356-
2357-
class NodeApp:
2358-
2359-
def __init__(self, test_path=None, nodes_to_cleanup=None, os_ops=None):
2360-
assert os_ops is None or isinstance(os_ops, OsOperations)
2361-
2362-
if os_ops is None:
2363-
os_ops = LocalOperations.get_single_instance()
2364-
2365-
assert isinstance(os_ops, OsOperations)
2366-
2367-
if test_path:
2368-
if os.path.isabs(test_path):
2369-
self.test_path = test_path
2370-
else:
2371-
self.test_path = os_ops.build_path(os_ops.cwd(), test_path)
2372-
else:
2373-
self.test_path = os_ops.cwd()
2374-
self.nodes_to_cleanup = nodes_to_cleanup if nodes_to_cleanup else []
2375-
self.os_ops = os_ops
2376-
2377-
def make_empty(
2378-
self,
2379-
base_dir=None,
2380-
port=None,
2381-
bin_dir=None):
2382-
real_base_dir = self.os_ops.build_path(self.test_path, base_dir)
2383-
self.os_ops.rmdirs(real_base_dir, ignore_errors=True)
2384-
self.os_ops.makedirs(real_base_dir)
2385-
2386-
node = PostgresNode(base_dir=real_base_dir, port=port, bin_dir=bin_dir)
2387-
self.nodes_to_cleanup.append(node)
2388-
2389-
return node
2390-
2391-
def make_simple(
2392-
self,
2393-
base_dir=None,
2394-
port=None,
2395-
set_replication=False,
2396-
ptrack_enable=False,
2397-
initdb_params=[],
2398-
pg_options={},
2399-
checksum=True,
2400-
bin_dir=None):
2401-
assert type(pg_options) == dict # noqa: E721
2402-
2403-
if checksum and '--data-checksums' not in initdb_params:
2404-
initdb_params.append('--data-checksums')
2405-
node = self.make_empty(base_dir, port, bin_dir=bin_dir)
2406-
node.init(
2407-
initdb_params=initdb_params, allow_streaming=set_replication)
2408-
2409-
# set major version
2410-
pg_version_file = self.os_ops.read(self.os_ops.build_path(node.data_dir, 'PG_VERSION'))
2411-
node.major_version_str = str(pg_version_file.rstrip())
2412-
node.major_version = float(node.major_version_str)
2413-
2414-
# Set default parameters
2415-
options = {
2416-
'max_connections': 100,
2417-
'shared_buffers': '10MB',
2418-
'fsync': 'off',
2419-
'wal_level': 'logical',
2420-
'hot_standby': 'off',
2421-
'log_line_prefix': '%t [%p]: [%l-1] ',
2422-
'log_statement': 'none',
2423-
'log_duration': 'on',
2424-
'log_min_duration_statement': 0,
2425-
'log_connections': 'on',
2426-
'log_disconnections': 'on',
2427-
'restart_after_crash': 'off',
2428-
'autovacuum': 'off',
2429-
# unix_socket_directories will be defined later
2430-
}
2431-
2432-
# Allow replication in pg_hba.conf
2433-
if set_replication:
2434-
options['max_wal_senders'] = 10
2435-
2436-
if ptrack_enable:
2437-
options['ptrack.map_size'] = '1'
2438-
options['shared_preload_libraries'] = 'ptrack'
2439-
2440-
if node.major_version >= 13:
2441-
options['wal_keep_size'] = '200MB'
2442-
else:
2443-
options['wal_keep_segments'] = '12'
2444-
2445-
# Apply given parameters
2446-
for option_name, option_value in iteritems(pg_options):
2447-
options[option_name] = option_value
2448-
2449-
# Define delayed propertyes
2450-
if not ("unix_socket_directories" in options.keys()):
2451-
options["unix_socket_directories"] = __class__._gettempdir_for_socket()
2452-
2453-
# Set config values
2454-
node.set_auto_conf(options)
2455-
2456-
# kludge for testgres
2457-
# https://github.com/postgrespro/testgres/issues/54
2458-
# for PG >= 13 remove 'wal_keep_segments' parameter
2459-
if node.major_version >= 13:
2460-
node.set_auto_conf({}, 'postgresql.conf', ['wal_keep_segments'])
2461-
2462-
return node
2463-
2464-
@staticmethod
2465-
def _gettempdir_for_socket():
2466-
platform_system_name = platform.system().lower()
2467-
2468-
if platform_system_name == "windows":
2469-
return __class__._gettempdir()
2470-
2471-
#
2472-
# [2025-02-17] Hot fix.
2473-
#
2474-
# Let's use hard coded path as Postgres likes.
2475-
#
2476-
# pg_config_manual.h:
2477-
#
2478-
# #ifndef WIN32
2479-
# #define DEFAULT_PGSOCKET_DIR "/tmp"
2480-
# #else
2481-
# #define DEFAULT_PGSOCKET_DIR ""
2482-
# #endif
2483-
#
2484-
# On the altlinux-10 tempfile.gettempdir() may return
2485-
# the path to "private" temp directiry - "/temp/.private/<username>/"
2486-
#
2487-
# But Postgres want to find a socket file in "/tmp" (see above).
2488-
#
2489-
2490-
return "/tmp"
2491-
2492-
@staticmethod
2493-
def _gettempdir():
2494-
v = tempfile.gettempdir()
2495-
2496-
#
2497-
# Paranoid checks
2498-
#
2499-
if type(v) != str: # noqa: E721
2500-
__class__._raise_bugcheck("tempfile.gettempdir returned a value with type {0}.".format(type(v).__name__))
2501-
2502-
if v == "":
2503-
__class__._raise_bugcheck("tempfile.gettempdir returned an empty string.")
2504-
2505-
if not os.path.exists(v):
2506-
__class__._raise_bugcheck("tempfile.gettempdir returned a not exist path [{0}].".format(v))
2507-
2508-
# OK
2509-
return v
2510-
2511-
@staticmethod
2512-
def _raise_bugcheck(msg):
2513-
assert type(msg) == str # noqa: E721
2514-
assert msg != ""
2515-
raise Exception("[BUG CHECK] " + msg)

0 commit comments

Comments
 (0)
0