def get_lock_count(self): """Returns the reentrant lock count if the lock is held by any thread in the cluster. Returns: hazelcast.future.Future[int]: The reentrant lock count if the lock is held by any thread in the cluster Raises: LockOwnershipLostError: If the underlying CP session was closed before the client releases the lock """ current_thread_id = thread_id() session_id = self._get_session_id() try: self._verify_locked_session_id_if_present(current_thread_id, session_id, False) except LockOwnershipLostError as e: return ImmediateExceptionFuture(e) def check_response(f): state = _LockOwnershipState(f.result()) if state.is_locked_by(session_id, current_thread_id): self._lock_session_ids[current_thread_id] = session_id else: self._verify_no_locked_session_id_present(current_thread_id) return state.lock_count return self._request_get_lock_ownership_state().continue_with(check_response)
def is_locked_by_current_thread(self): """Returns whether the lock is held by the current thread or not. Returns: hazelcast.future.Future[bool]: ``True`` if the lock is held by the current thread, ``False`` otherwise. Raises: LockOwnershipLostError: If the underlying CP session was closed before the client releases the lock """ current_thread_id = thread_id() session_id = self._get_session_id() try: self._verify_locked_session_id_if_present(current_thread_id, session_id, False) except LockOwnershipLostError as e: return ImmediateExceptionFuture(e) def check_response(f): state = _LockOwnershipState(f.result()) locked_by_the_current_thread = state.is_locked_by(session_id, current_thread_id) if locked_by_the_current_thread: self._lock_session_ids[current_thread_id] = session_id else: self._verify_no_locked_session_id_present(current_thread_id) return locked_by_the_current_thread return self._request_get_lock_ownership_state().continue_with(check_response)
def send_state_to_cluster_fn(): counter.add(1) if counter.get() == 5: # Let's pretend it succeeds at some point return ImmediateFuture(None) return ImmediateExceptionFuture(RuntimeError("expected"))
def setUp(self): try: raise RuntimeError("error") except: self.exc = sys.exc_info()[1] self.traceback = sys.exc_info()[2] self.f = ImmediateExceptionFuture(self.exc, self.traceback)
def get_or_connect(self, address, authenticator=None): """ Gets the existing connection for a given address. If it does not exist, the system will try to connect asynchronously. In this case, it returns a Future. When the connection is established at some point in time, it can be retrieved by using the get_connection(:class:`~hazelcast.core.Address`) or from Future. :param address: (:class:`~hazelcast.core.Address`), the address to connect to. :param authenticator: (Function), function to be used for authentication (optional). :return: (:class:`~hazelcast.connection.Connection`), the existing connection or it returns a Future which includes asynchronously. """ if address in self.connections: return ImmediateFuture(self.connections[address]) else: with self._new_connection_mutex: if address in self._pending_connections: return self._pending_connections[address] else: authenticator = authenticator or self._cluster_authenticator try: translated_address = self._address_translator.translate(address) if translated_address is None: raise ValueError("Address translator could not translate address: {}".format(address)) connection = self._new_connection_func(translated_address, self._client.config.network_config.connection_timeout, self._client.config.network_config.socket_options, connection_closed_callback=self._connection_closed, message_callback=self._client.invoker._handle_client_message, network_config=self._client.config.network_config) except IOError: return ImmediateExceptionFuture(sys.exc_info()[1], sys.exc_info()[2]) future = authenticator(connection).continue_with(self.on_auth, connection, address) if not future.done(): self._pending_connections[address] = future return future
def test_read_many_on_illegal_argument_error_with_loss_tolerant_listener_when_head_sequence_fails( self, ): self.error_on_first_read_many(IllegalArgumentError("expected")) self.ringbuffer.head_sequence.return_value = ImmediateExceptionFuture( RuntimeError("expected")) class Listener(ReliableMessageListener): def on_message(self, message): pass def retrieve_initial_sequence(self): return 0 def store_sequence(self, sequence): pass def is_loss_tolerant(self): return True def is_terminal(self, error): pass self.topic.add_listener(Listener()) self.assertEqual(1, self.ringbuffer.read_many.call_count) self.assertEqual(0, len(self.topic._runners))
def unlock(self): """Releases the lock if the lock is currently held by the current thread. Returns: hazelcast.future.Future[None]: Raises: LockOwnershipLostError: If the underlying CP session was closed before the client releases the lock IllegalMonitorStateError: If the lock is not held by the current thread """ current_thread_id = thread_id() session_id = self._get_session_id() # the order of the following checks is important try: self._verify_locked_session_id_if_present(current_thread_id, session_id, False) except LockOwnershipLostError as e: return ImmediateExceptionFuture(e) if session_id == _NO_SESSION_ID: self._lock_session_ids.pop(current_thread_id, None) return ImmediateExceptionFuture( self._new_illegal_monitor_state_error()) def check_response(f): try: still_locked_by_the_current_thread = f.result() if still_locked_by_the_current_thread: self._lock_session_ids[current_thread_id] = session_id else: self._lock_session_ids.pop(current_thread_id, None) self._release_session(session_id) except SessionExpiredError: self._invalidate_session(session_id) self._lock_session_ids.pop(current_thread_id, None) raise self._new_lock_ownership_lost_error(session_id) except IllegalMonitorStateError as e: self._lock_session_ids.pop(current_thread_id, None) raise e return self._request_unlock(session_id, current_thread_id, uuid.uuid4()).continue_with(check_response)
def _get_or_connect_to_member(self, member): connection = self.active_connections.get(member.uuid, None) if connection: return ImmediateFuture(connection) try: translated = self._translate(member.address) connection = self._create_connection(translated) return self._authenticate(connection).continue_with(self._on_auth, connection) except Exception as e: return ImmediateExceptionFuture(e)
def _get_or_connect_to_address(self, address): for connection in list(six.itervalues(self.active_connections)): if connection.remote_address == address: return ImmediateFuture(connection) try: translated = self._translate(address) connection = self._create_connection(translated) return self._authenticate(connection).continue_with(self._on_auth, connection) except Exception as e: return ImmediateExceptionFuture(e)
def execute(self, sql, params, kwargs): """Constructs a statement and executes it. Args: sql (str): SQL string. params (tuple): Query parameters. kwargs (dict): Arguments to customize the query. Returns: hazelcast.future.Future[SqlResult]: The execution result. """ statement = _SqlStatement(sql, params, **kwargs) connection = None try: connection = self._get_query_connection() # Create a new, unique query id. query_id = _SqlQueryId.from_uuid(connection.remote_uuid) # Serialize the passed parameters. serialized_params = [ self._serialization_service.to_data(param) for param in statement.parameters ] request = sql_execute_codec.encode_request( statement.sql, serialized_params, # to_millis expects None to produce -1 to_millis(None if statement.timeout == -1 else statement.timeout), statement.cursor_buffer_size, statement.schema, statement.expected_result_type, query_id, False, ) invocation = Invocation( request, connection=connection, response_handler=sql_execute_codec.decode_response) self._invocation_service.invoke(invocation) return invocation.future.continue_with(lambda future: SqlResult( self, connection, query_id, statement.cursor_buffer_size, self._handle_execute_response(future, connection), )) except Exception as e: return ImmediateExceptionFuture(self.re_raise(e, connection))
def _get_or_create_session(self, group_id): with self._lock: if self._shutdown: error = HazelcastClientNotActiveError("Session manager is already shut down!") return ImmediateExceptionFuture(error) session = self._sessions.get(group_id, None) if session is None or not session.is_valid(): with self._mutex(group_id): session = self._sessions.get(group_id) if session is None or not session.is_valid(): return self._create_new_session(group_id) return ImmediateFuture(session)
def _get_or_connect(self, address): connection = self.get_connection_from_address(address) if connection: return ImmediateFuture(connection) with self._lock: connection = self.get_connection_from_address(address) if connection: return ImmediateFuture(connection) else: pending = self._pending_connections.get(address, None) if pending: return pending else: try: translated = self._address_provider.translate(address) if not translated: error = ValueError( "Address translator could not translate address %s" % address) return ImmediateExceptionFuture(error) factory = self._reactor.connection_factory connection = factory( self, self._connection_id_generator.get_and_increment(), translated, self._client.config, self._invocation_service.handle_client_message, ) except IOError: error = sys.exc_info() return ImmediateExceptionFuture(error[1], error[2]) future = self._authenticate(connection).continue_with( self._on_auth, connection, address) self._pending_connections[address] = future return future
def get_or_create_unique_thread_id(self, group_id): with self._lock: if self._shutdown: error = HazelcastClientNotActiveError( "Session manager is already shut down!") return ImmediateExceptionFuture(error) key = (group_id, thread_id()) global_thread_id = self._thread_ids.get(key) if global_thread_id: return ImmediateFuture(global_thread_id) return self._request_generate_thread_id(group_id).continue_with( lambda t_id: self._thread_ids.setdefault(key, t_id.result()))
def prepare_acquire_session(self, session_id, err=None): if err: val = ImmediateExceptionFuture(err) else: val = ImmediateFuture(session_id) acquire_mock = MagicMock(return_value=val) release_mock = MagicMock() invalidate_mock = MagicMock() self.session_manager.acquire_session = acquire_mock self.session_manager.release_session = release_mock self.session_manager.invalidate_session = invalidate_mock self.acquire_session = acquire_mock self.release_session = release_mock self.invalidate_session = invalidate_mock
def test_heartbeat_on_failure(self): reactor = self.mock_reactor() self.mock_request_new_session() self.manager._request_heartbeat = MagicMock( return_value=ImmediateExceptionFuture(SessionExpiredError())) m = MagicMock(side_effect=self.manager.invalidate_session) self.manager.invalidate_session = m self.manager.acquire_session(self.raft_group_id, 1).result() time.sleep(2) self.manager.shutdown() reactor.shutdown() self.assertGreater(self.context.reactor.add_timer.call_count, 1) # assert that the heartbeat task is executed m.assert_called_once_with(self.raft_group_id, self.session_id) self.assertEqual(0, len(self.manager._sessions))
def release(self, permits=1): check_true(permits > 0, "Permits must be positive") session_id = self._get_session_id() if session_id == _NO_SESSION_ID: return ImmediateExceptionFuture(self._new_illegal_state_error()) current_thread_id = thread_id() invocation_uuid = uuid.uuid4() def check_response(response): try: response.result() except SessionExpiredError as e: self._invalidate_session(session_id) raise self._new_illegal_state_error(e) finally: self._release_session(session_id, permits) return self._request_release(session_id, current_thread_id, invocation_uuid, permits).continue_with( check_response)
def get_or_connect(self, address, authenticator=None): if address in self.connections: return ImmediateFuture(self.connections[address]) else: with self._new_connection_mutex: if address in self._pending_connections: return self._pending_connections[address] else: authenticator = authenticator or self._cluster_authenticator try: connection = self._new_connection_func(address, self._client.config.network_config.connection_timeout, self._client.config.network_config.socket_options, connection_closed_callback=self._connection_closed, message_callback=self._client.invoker._handle_client_message) except IOError: return ImmediateExceptionFuture(sys.exc_info()[1], sys.exc_info()[2]) future = authenticator(connection).continue_with(self.on_auth, connection, address) if not future.done(): self._pending_connections[address] = future return future
def prepare_thread_id(self, thread_id, err=None): if err: value = ImmediateExceptionFuture(err) else: value = ImmediateFuture(thread_id) self.session_manager.get_or_create_unique_thread_id = MagicMock(return_value=value)
def mock(expected_round, invocation_uuid): if called_count.get_and_increment() < 2: return ImmediateExceptionFuture(OperationTimeoutError("xx")) return original(expected_round, invocation_uuid)
def read_many_mock(*_): if next(counter) == 0: return ImmediateExceptionFuture(error) return Future()
def mock(*_, **__): if called.get_and_increment() == 0 and first_call_err: return ImmediateExceptionFuture(first_call_err) return ImmediateFuture(result)
def execute(self, sql, params, cursor_buffer_size, timeout, expected_result_type, schema): """Constructs a statement and executes it. Args: sql (str): SQL string. params (tuple): Query parameters. cursor_buffer_size (int): Cursor buffer size. timeout (float): Timeout of the query. expected_result_type (SqlExpectedResultType): Expected result type of the query. schema (str or None): The schema name. Returns: hazelcast.future.Future[SqlResult]: The execution result. """ statement = _SqlStatement(sql, params, cursor_buffer_size, timeout, expected_result_type, schema) connection = None try: try: # Serialize the passed parameters. serialized_params = [ self._serialization_service.to_data(param) for param in statement.parameters ] except SchemaNotReplicatedError as e: return self._send_schema_and_retry_fn( e, self.execute, sql, params, cursor_buffer_size, timeout, expected_result_type, schema, ) connection = self._get_query_connection() # Create a new, unique query id. query_id = _SqlQueryId.from_uuid(connection.remote_uuid) request = sql_execute_codec.encode_request( statement.sql, serialized_params, # to_millis expects None to produce -1 to_millis(None if statement.timeout == -1 else statement.timeout), statement.cursor_buffer_size, statement.schema, statement.expected_result_type, query_id, False, ) invocation = Invocation( request, connection=connection, response_handler=sql_execute_codec.decode_response) self._invocation_service.invoke(invocation) return invocation.future.continue_with(lambda future: SqlResult( self, connection, query_id, statement.cursor_buffer_size, self._handle_execute_response(future, connection), )) except Exception as e: return ImmediateExceptionFuture(self.re_raise(e, connection))