Ejemplo n.º 1
0
 def test_next_only_one_server(self):
     from relstorage.adapters.replica import ReplicaSelector
     with open(self.fn, 'w') as f:
         f.write('localhost\n')
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs.current(), 'localhost')
     self.assertEqual(rs.next(), None)
Ejemplo n.º 2
0
 def test_next_only_one_server(self):
     from relstorage.adapters.replica import ReplicaSelector
     f = open(self.fn, 'w')
     f.write('localhost\n')
     f.close()
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs.current(), 'localhost')
     self.assertEqual(rs.next(), None)
Ejemplo n.º 3
0
 def test_next_only_one_server(self):
     from relstorage.adapters.replica import ReplicaSelector
     f = open(self.fn, 'w')
     f.write('localhost\n')
     f.close()
     rs = ReplicaSelector(self.options)
     self.assertEqual(rs.current(), 'localhost')
     self.assertEqual(rs.next(), None)
Ejemplo n.º 4
0
 def test__select(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     rs._select(0)
     self.assertEqual(rs._current_replica, 'example.com:1234')
     self.assertEqual(rs._current_index, 0)
     self.assertEqual(rs._expiration, None)
     rs._select(1)
     self.assertEqual(rs._current_replica, 'localhost:4321')
     self.assertEqual(rs._current_index, 1)
     self.assertNotEqual(rs._expiration, None)
Ejemplo n.º 5
0
    def __init__(self, options):
        # options is a relstorage.options.Options instance
        if options.replica_conf:
            self.replica_selector = ReplicaSelector(options.replica_conf,
                                                    options.replica_timeout)
        else:
            self.replica_selector = None

        if options.ro_replica_conf:
            self.ro_replica_selector = ReplicaSelector(options.ro_replica_conf,
                                                       options.replica_timeout)
        else:
            self.ro_replica_selector = self.replica_selector
Ejemplo n.º 6
0
 def test_current(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs.current(), 'example.com:1234')
     # change the file and get the new current replica
     f = open(self.fn, 'w')
     f.write('localhost\nalternate\n')
     f.close()
     rs._config_checked = 0
     rs._config_modified = 0
     self.assertEqual(rs.current(), 'localhost')
     # switch to the alternate
     rs._select(1)
     self.assertEqual(rs.current(), 'alternate')
     # expire the alternate
     rs._expiration = 0
     self.assertEqual(rs.current(), 'localhost')
Ejemplo n.º 7
0
    def test_next_iteration(self):
        from relstorage.adapters.replica import ReplicaSelector
        rs = ReplicaSelector(self.fn, 600.0)

        # test forward iteration
        self.assertEqual(rs.current(), 'example.com:1234')
        self.assertEqual(rs.next(), 'localhost:4321')
        self.assertEqual(rs.next(), 'localhost:9999')
        self.assertEqual(rs.next(), None)

        # test iteration that skips over the replica that failed
        self.assertEqual(rs.current(), 'example.com:1234')
        self.assertEqual(rs.next(), 'localhost:4321')
        self.assertEqual(rs.current(), 'localhost:4321')
        # next() after current() indicates the last replica failed
        self.assertEqual(rs.next(), 'example.com:1234')
        self.assertEqual(rs.next(), 'localhost:9999')
        self.assertEqual(rs.next(), None)
Ejemplo n.º 8
0
 def test__is_config_modified(self):
     from relstorage.adapters.replica import ReplicaSelector
     import time
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs._is_config_modified(), False)
     # change the file
     rs._config_modified = 0
     # don't check the file yet
     rs._config_checked = time.time() + 3600
     self.assertEqual(rs._is_config_modified(), False)
     # now check the file
     rs._config_checked = 0
     self.assertEqual(rs._is_config_modified(), True)
Ejemplo n.º 9
0
    def test_next_iteration(self):
        from relstorage.adapters.replica import ReplicaSelector
        rs = ReplicaSelector(self.fn, 600.0)

        # test forward iteration
        self.assertEqual(rs.current(), 'example.com:1234')
        self.assertEqual(rs.next(), 'localhost:4321')
        self.assertEqual(rs.next(), 'localhost:9999')
        self.assertEqual(rs.next(), None)

        # test iteration that skips over the replica that failed
        self.assertEqual(rs.current(), 'example.com:1234')
        self.assertEqual(rs.next(), 'localhost:4321')
        self.assertEqual(rs.current(), 'localhost:4321')
        # next() after current() indicates the last replica failed
        self.assertEqual(rs.next(), 'example.com:1234')
        self.assertEqual(rs.next(), 'localhost:9999')
        self.assertEqual(rs.next(), None)
Ejemplo n.º 10
0
 def test_next_with_new_conf(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs.current(), 'example.com:1234')
     self.assertEqual(rs.next(), 'localhost:4321')
     # interrupt the iteration by changing the replica conf file
     with open(self.fn, 'w') as f:
         f.write('example.com:9999\n')
     rs._config_checked = 0
     rs._config_modified = 0
     self.assertEqual(rs.next(), 'example.com:9999')
     self.assertEqual(rs.next(), None)
Ejemplo n.º 11
0
 def test__is_config_modified(self):
     from relstorage.adapters.replica import ReplicaSelector
     import time
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs._is_config_modified(), False)
     # change the file
     rs._config_modified = 0
     # don't check the file yet
     rs._config_checked = time.time() + 3600
     self.assertEqual(rs._is_config_modified(), False)
     # now check the file
     rs._config_checked = 0
     self.assertEqual(rs._is_config_modified(), True)
Ejemplo n.º 12
0
 def test__select(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     rs._select(0)
     self.assertEqual(rs._current_replica, 'example.com:1234')
     self.assertEqual(rs._current_index, 0)
     self.assertEqual(rs._expiration, None)
     rs._select(1)
     self.assertEqual(rs._current_replica, 'localhost:4321')
     self.assertEqual(rs._current_index, 1)
     self.assertNotEqual(rs._expiration, None)
Ejemplo n.º 13
0
 def test_next_with_new_conf(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs.current(), 'example.com:1234')
     self.assertEqual(rs.next(), 'localhost:4321')
     # interrupt the iteration by changing the replica conf file
     f = open(self.fn, 'w')
     f.write('example.com:9999\n')
     f.close()
     rs._config_checked = 0
     rs._config_modified = 0
     self.assertEqual(rs.next(), 'example.com:9999')
     self.assertEqual(rs.next(), None)
Ejemplo n.º 14
0
 def test_current(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(rs.current(), 'example.com:1234')
     # change the file and get the new current replica
     f = open(self.fn, 'w')
     f.write('localhost\nalternate\n')
     f.close()
     rs._config_checked = 0
     rs._config_modified = 0
     self.assertEqual(rs.current(), 'localhost')
     # switch to the alternate
     rs._select(1)
     self.assertEqual(rs.current(), 'alternate')
     # expire the alternate
     rs._expiration = 0
     self.assertEqual(rs.current(), 'localhost')
Ejemplo n.º 15
0
 def test__read_config_normal(self):
     from relstorage.adapters.replica import ReplicaSelector
     rs = ReplicaSelector(self.fn, 600.0)
     self.assertEqual(
         rs._replicas,
         ['example.com:1234', 'localhost:4321', 'localhost:9999'])
Ejemplo n.º 16
0
class AbstractConnectionManager(object):
    """Abstract base class for connection management.

    Responsible for opening and closing database connections.
    """
    implements(IConnectionManager)

    # disconnected_exceptions contains the exception types that might be
    # raised when the connection to the database has been broken.
    disconnected_exceptions = (ReplicaClosedException,)

    # close_exceptions contains the exception types to ignore
    # when the adapter attempts to close a database connection.
    close_exceptions = ()

    # on_store_opened is either None or a callable that
    # will be called whenever a store cursor is opened or rolled back.
    on_store_opened = None

    def __init__(self, options):
        # options is a relstorage.options.Options instance
        if options.replica_conf:
            self.replica_selector = ReplicaSelector(options)
        else:
            self.replica_selector = None

    def set_on_store_opened(self, f):
        """Set the on_store_opened hook"""
        self.on_store_opened = f

    def open(self):
        """Open a database connection and return (conn, cursor)."""
        raise NotImplementedError()

    def close(self, conn, cursor):
        """Close a connection and cursor, ignoring certain errors.
        """
        for obj in (cursor, conn):
            if obj is not None:
                try:
                    obj.close()
                except self.close_exceptions:
                    pass

    def open_and_call(self, callback):
        """Call a function with an open connection and cursor.

        If the function returns, commits the transaction and returns the
        result returned by the function.
        If the function raises an exception, aborts the transaction
        then propagates the exception.
        """
        conn, cursor = self.open()
        try:
            try:
                res = callback(conn, cursor)
            except:
                conn.rollback()
                raise
            else:
                conn.commit()
                return res
        finally:
            self.close(conn, cursor)

    def open_for_load(self):
        raise NotImplementedError()

    def restart_load(self, conn, cursor):
        """Reinitialize a connection for loading objects."""
        self.check_replica(conn, cursor)
        conn.rollback()

    def check_replica(self, conn, cursor):
        """Raise an exception if the connection belongs to an old replica"""
        if self.replica_selector is not None:
            current = self.replica_selector.current()
            if conn.replica != current:
                # Prompt the change to a new replica by raising an exception.
                self.close(conn, cursor)
                raise ReplicaClosedException(
                    "Switched replica from %s to %s" % (conn.replica, current))

    def open_for_store(self):
        """Open and initialize a connection for storing objects.

        Returns (conn, cursor).
        """
        conn, cursor = self.open()
        try:
            if self.on_store_opened is not None:
                self.on_store_opened(cursor, restart=False)
            return conn, cursor
        except:
            self.close(conn, cursor)
            raise

    def restart_store(self, conn, cursor):
        """Reuse a store connection."""
        self.check_replica(conn, cursor)
        conn.rollback()
        if self.on_store_opened is not None:
            self.on_store_opened(cursor, restart=True)

    def open_for_pre_pack(self):
        """Open a connection to be used for the pre-pack phase.
        Returns (conn, cursor).
        """
        return self.open()