Beispiel #1
0
    def __init__(self, site_alias: str, client_socket: socket.socket,
                 **context):
        threading.Thread.__init__(self, daemon=True)
        communication.GenericSocketUser.__init__(self)

        self.protocol_db = protocol.ProtocolDatabase(context['protocol_db'])
        self.socket = client_socket
        self.context = context
        self.active_map = {}

        # Initialize our site-list, which describes our cluster.
        self.site_list = self.context['site_list']
        logger.info(f'Coordinator is aware of site: {self.site_list}')

        # Identify which node we are in our "ring".
        self.node_id = [
            i for i, j in enumerate(self.site_list) if j['alias'] == site_alias
        ][0]
        logger.info(f'Transaction started at node {self.node_id}.')

        # Setup a connection to the RM (i.e. Postgres).
        self.conn = psycopg2.connect(
            user=self.context['postgres_username'],
            password=self.context['postgres_password'],
            host=self.context['postgres_hostname'],
            database=self.context['postgres_database'])

        # To enter the ABORT / POLLING state instead, parent must explicitly change the state after instantiation.
        self.transaction_id = psycopg2.extensions.Xid.from_string(
            str(uuid.uuid4()))
        self.state = CoordinatorStates.INITIALIZE
        self.previous_state = None
Beispiel #2
0
    def _recovery_state(self):
        # Initialize our site-list, which describes our cluster.
        logger.info(f"TM is aware of site: {self.site_list}")

        # Setup a connection to the RM (i.e. Postgres).
        recovery_conn = psycopg2.connect(
            user=self.context['postgres_username'],
            password=self.context['postgres_password'],
            host=self.context['postgres_hostname'],
            database=self.context['postgres_database']
        ) if 'test_rm' not in self.context else self.context['test_rm']
        protocol_db = protocol.ProtocolDatabase(self.context['protocol_db'])

        for transaction_id in protocol_db.get_abortable_transactions():
            logger.info(
                f"Working on to-be-aborted transaction {transaction_id}.")
            self._abort_transaction(protocol_db, transaction_id)

        for transaction_id in protocol_db.get_prepared_transactions():
            logger.info(f"Working on prepared transaction {transaction_id}.")
            self._recover_transaction(protocol_db, transaction_id)

        # We are done with recovery.
        recovery_conn.close()
        protocol_db.close()
        self.state = TransactionManagerStates.INITIALIZE
    def test_transaction_abort(self):
        transaction_id = str(uuid.uuid4())

        coordinator_pdb = protocol.ProtocolDatabase('coordinator_' + self.test_file)
        participant_pdb = protocol.ProtocolDatabase('participant_' + self.test_file)
        coordinator_pdb.log_initialize_of(transaction_id, TransactionRole.COORDINATOR)
        participant_pdb.log_initialize_of(transaction_id, TransactionRole.PARTICIPANT)

        self.assertEqual(coordinator_pdb.get_role_in(transaction_id), TransactionRole.COORDINATOR)
        self.assertEqual(participant_pdb.get_role_in(transaction_id), TransactionRole.PARTICIPANT)

        coordinator_pdb.log_abort_of(transaction_id)
        participant_pdb.log_abort_of(transaction_id)

        coordinator_pdb.close()
        participant_pdb.close()
        time.sleep(0.5)
    def test_site_awareness(self):
        transaction_id = str(uuid.uuid4())

        coordinator_pdb = protocol.ProtocolDatabase('coordinator_' + self.test_file)
        participant_pdb = protocol.ProtocolDatabase('participant_' + self.test_file)
        coordinator_pdb.log_initialize_of(transaction_id, TransactionRole.COORDINATOR)
        participant_pdb.log_initialize_of(transaction_id, TransactionRole.PARTICIPANT)

        coordinator_pdb.add_participant(transaction_id, 1)
        coordinator_pdb.add_participant(transaction_id, 2)
        participant_pdb.add_coordinator(transaction_id, 2)

        participants = coordinator_pdb.get_participants_in(transaction_id)
        self.assertEqual(len(participants), 2)
        self.assertIn(1, participants)
        self.assertIn(2, participants)

        coordinator = participant_pdb.get_coordinator_for(transaction_id)
        self.assertEqual(coordinator, 2)

        coordinator_pdb.close()
        participant_pdb.close()
        time.sleep(0.5)
    def test_transaction_recovery(self):
        transaction_id_1 = str(uuid.uuid4())
        transaction_id_2 = str(uuid.uuid4())

        coordinator_pdb = protocol.ProtocolDatabase('coordinator_' + self.test_file)
        coordinator_pdb.log_initialize_of(transaction_id_1, TransactionRole.COORDINATOR)
        coordinator_pdb.log_initialize_of(transaction_id_2, TransactionRole.COORDINATOR)
        coordinator_pdb.log_prepare_of(transaction_id_1)

        abortable_transactions = coordinator_pdb.get_abortable_transactions()
        prepared_transactions = coordinator_pdb.get_prepared_transactions()
        self.assertEqual(len(abortable_transactions), 1)
        self.assertEqual(len(prepared_transactions), 1)
        self.assertEqual(abortable_transactions[0], transaction_id_2)
        self.assertEqual(prepared_transactions[0], transaction_id_1)

        coordinator_pdb.close()
        time.sleep(0.5)
Beispiel #6
0
    def __init__(self, transaction_id: str, client_socket: socket.socket,
                 **context):
        communication.GenericSocketUser.__init__(self, client_socket)
        threading.Thread.__init__(self, daemon=True)

        self.protocol_db = protocol.ProtocolDatabase(context['protocol_db'])
        self.transaction_coordinator = context['transaction_coordinator']
        self.context = context

        # Setup a connection to the RM (i.e. Postgres).
        self.conn = psycopg2.connect(user=context['postgres_username'],
                                     password=context['postgres_password'],
                                     host=context['postgres_hostname'],
                                     database=context['postgres_database'])
        self.transaction_id = psycopg2.extensions.Xid.from_string(
            transaction_id)
        self.conn.autocommit = False
        self.conn.tpc_begin(self.transaction_id)

        # To enter the PREPARE / ABORT state instead, parent must explicitly change the state after instantiation.
        self.state = ParticipantStates.INITIALIZE
        self.socket_token = queue.Queue(1)
        self.previous_edge_property = None
        self.is_prepared = False
Beispiel #7
0
    def test_recovery_coordinator(self):
        transaction_id_1 = str(uuid.uuid4())
        conn = self.get_postgres_connection()
        conn.tpc_begin(psycopg2.extensions.Xid.from_string(transaction_id_1))
        cur = conn.cursor()
        cur.execute("""
            INSERT INTO thermometerobservation 
            VALUES ('a239a033-b340-426d-a686-ad32908709ae', 48, '2017-11-08 00:00:00', 
                    '9592a785_d3a4_4de2_bc3d_cfa1a127bf40');
        """)

        # Coordinator knows COMMIT, but does not have the ACK.
        pdb1 = protocol.ProtocolDatabase(self.test_file + '1')
        pdb1.log_initialize_of(transaction_id_1, TransactionRole.COORDINATOR)
        pdb1.add_participant(transaction_id_1, 1)
        pdb1.log_commit_of(transaction_id_1)
        conn.tpc_prepare()
        pdb1.close()

        class TestRM(object):
            def tpc_recover(self):
                return []

            def close(self):
                pass

        manager_thread_1 = manager.TransactionManagerThread(
            **self.get_postgres_context(),
            protocol_db=self.test_file + '1',
            role_factory=_TestCoordinatorRecoveryTransactionStateFactory(
                transaction_id_1=transaction_id_1),
            site_alias=socket.gethostname(),
            node_port=self.test_port + 5,
            site_list=[{
                'alias': socket.gethostname(),
                'hostname': socket.gethostname(),
                'port': self.test_port + 5
            }, {
                'alias': socket.gethostname(),
                'hostname': socket.gethostname(),
                'port': self.test_port + 6
            }])
        manager_thread_2 = manager.TransactionManagerThread(
            **self.get_postgres_context(),
            test_rm=TestRM(),
            protocol_db=self.test_file,
            role_factory=_TestDummyTransactionRoleFactory(),
            site_alias=socket.gethostname(),
            node_port=self.test_port + 6,
            site_list=[{
                'alias': socket.gethostname(),
                'hostname': socket.gethostname(),
                'port': self.test_port + 5
            }, {
                'alias': socket.gethostname(),
                'hostname': socket.gethostname(),
                'port': self.test_port + 6
            }])

        manager_thread_2.start()
        time.sleep(1.0)
        manager_thread_1.start()
        time.sleep(0.5)

        # Create new connection to TM, and issue the shutdown.
        client_socket = communication.GenericSocketUser()
        client_socket.socket.connect(
            (socket.gethostname(), self.test_port + 5))
        client_socket.send_op(OpCode.SHUTDOWN)
        time.sleep(0.5)
        client_socket.socket.close()

        manager_thread_1.join()
        manager_thread_2.join()