Skip to content

LocalOperations::get_single_instance is added #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions testgres/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@
from .operations.os_ops import OsOperations


def cached_initdb(data_dir, logfile=None, params=None, os_ops: OsOperations = LocalOperations(), bin_path=None, cached=True):
def cached_initdb(data_dir, logfile=None, params=None, os_ops: OsOperations = None, bin_path=None, cached=True):
"""
Perform initdb or use cached node files.
"""

assert os_ops is not None
assert os_ops is None or isinstance(os_ops, OsOperations)

if os_ops is None:
os_ops = LocalOperations.get_single_instance()

assert isinstance(os_ops, OsOperations)

def make_utility_path(name):
Expand Down
3 changes: 2 additions & 1 deletion testgres/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ class GlobalConfig(object):
_cached_initdb_dir = None
""" underlying class attribute for cached_initdb_dir property """

os_ops = LocalOperations()
os_ops = LocalOperations.get_single_instance()
""" OsOperation object that allows work on remote host """

@property
def cached_initdb_dir(self):
""" path to a temp directory for cached initdb. """
Expand Down
23 changes: 19 additions & 4 deletions testgres/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@

from .standby import First

from . import utils

from .utils import \
PgVer, \
eprint, \
Expand Down Expand Up @@ -265,14 +267,17 @@ def _get_os_ops() -> OsOperations:
if testgres_config.os_ops:
return testgres_config.os_ops

return LocalOperations()
return LocalOperations.get_single_instance()

@staticmethod
def _get_port_manager(os_ops: OsOperations) -> PortManager:
assert os_ops is not None
assert isinstance(os_ops, OsOperations)

if isinstance(os_ops, LocalOperations):
if os_ops is LocalOperations.get_single_instance():
assert utils._old_port_manager is not None
assert type(utils._old_port_manager) == PortManager__Generic # noqa: E721
assert utils._old_port_manager._os_ops is os_ops
return PortManager__ThisHost.get_single_instance()

# TODO: Throw the exception "Please define a port manager." ?
Expand Down Expand Up @@ -816,10 +821,13 @@ def init(self, initdb_params=None, cached=True, **kwargs):
"""

# initialize this PostgreSQL node
assert self._os_ops is not None
assert isinstance(self._os_ops, OsOperations)

cached_initdb(
data_dir=self.data_dir,
logfile=self.utils_log_file,
os_ops=self.os_ops,
os_ops=self._os_ops,
params=initdb_params,
bin_path=self.bin_dir,
cached=False)
Expand Down Expand Up @@ -2186,7 +2194,14 @@ def _escape_config_value(value):

class NodeApp:

def __init__(self, test_path=None, nodes_to_cleanup=None, os_ops=LocalOperations()):
def __init__(self, test_path=None, nodes_to_cleanup=None, os_ops=None):
assert os_ops is None or isinstance(os_ops, OsOperations)

if os_ops is None:
os_ops = LocalOperations.get_single_instance()

assert isinstance(os_ops, OsOperations)

if test_path:
if os.path.isabs(test_path):
self.test_path = test_path
Expand Down
20 changes: 20 additions & 0 deletions testgres/operations/local_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import psutil
import typing
import threading

from ..exceptions import ExecUtilException
from ..exceptions import InvalidOperationException
Expand All @@ -28,6 +29,9 @@


class LocalOperations(OsOperations):
sm_single_instance: OsOperations = None
sm_single_instance_guard = threading.Lock()

def __init__(self, conn_params=None):
if conn_params is None:
conn_params = ConnectionParams()
Expand All @@ -38,6 +42,22 @@ def __init__(self, conn_params=None):
self.remote = False
self.username = conn_params.username or getpass.getuser()

@staticmethod
def get_single_instance() -> OsOperations:
assert __class__ == LocalOperations
assert __class__.sm_single_instance_guard is not None

if __class__.sm_single_instance is not None:
assert type(__class__.sm_single_instance) == __class__ # noqa: E721
return __class__.sm_single_instance

with __class__.sm_single_instance_guard:
if __class__.sm_single_instance is None:
__class__.sm_single_instance = __class__()
assert __class__.sm_single_instance is not None
assert type(__class__.sm_single_instance) == __class__ # noqa: E721
return __class__.sm_single_instance

@staticmethod
def _process_output(encoding, temp_file_path):
"""Process the output of a command from a temporary file."""
Expand Down
4 changes: 1 addition & 3 deletions testgres/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@
# rows returned by PG_CONFIG
_pg_config_data = {}

_local_operations = LocalOperations()

#
# The old, global "port manager" always worked with LOCAL system
#
_old_port_manager = PortManager__Generic(_local_operations)
_old_port_manager = PortManager__Generic(LocalOperations.get_single_instance())

# ports used by nodes
bound_ports = _old_port_manager._reserved_ports
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/global_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class OsOpsDescrs:

sm_remote_os_ops_descr = OsOpsDescr("remote_ops", sm_remote_os_ops)

sm_local_os_ops = LocalOperations()
sm_local_os_ops = LocalOperations.get_single_instance()

sm_local_os_ops_descr = OsOpsDescr("local_ops", sm_local_os_ops)

Expand Down