if (deadConnection != null && ccu.equals(deadConnection.getUpdater())) { queueConnections = queueConnections.removeConnection(deadConnection); try { deadConnection.internalClose(pool.getKeepAlive()); } catch (Exception e) { logger.warn("Error destroying client to server connection to {}", deadConnection.getEndpoint(), e); (deadConnection != null && deadConnection.getUpdater() != null) ? (deadConnection.getUpdater().isPrimary() ? "Primary" : "Redundant") : "Queue", endpoint);
public void readyForEventsAfterFailover(QueueConnectionImpl primary) { try { logger.info("Sending ready for events to primary: {}", primary); ReadyForEventsOp.execute(pool, primary); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Error sending ready for events to {}", primary, e); } primary.destroy(); } }
@Override public Connection getConnection(Connection conn) { if (conn instanceof PooledConnection) { return ((PooledConnection) conn).getConnection(); } else if (conn instanceof QueueConnectionImpl) { return ((QueueConnectionImpl) conn).getConnection(); } else { return conn; } }
@Test public void testInternalDestroyFollowedByInternalClose() { // Mock ClientUpdater and Connection ClientUpdater updater = mock(ClientUpdater.class); Connection connection = mock(Connection.class); // Create a QueueConnectionImpl on the mocks QueueConnectionImpl qci = new QueueConnectionImpl(null, connection, updater, null); // Invoke internalDestroy (which sets the updater to null) qci.internalDestroy(); // Assert that invoking internalClose throws a ConnectionDestroyedException and not a // NullPointerException assertThatThrownBy(() -> qci.internalClose(false)) .isInstanceOf(ConnectionDestroyedException.class); } }
boolean haveSentClientReady = this.sentClientReady; if (haveSentClientReady) { cnx.sendClientReady(); ClientUpdater updater = cnx.getUpdater(); if (updater == null) { if (logger.isDebugEnabled()) { logger.debug("backup connection was destroyed before it could become the primary."); Assert.assertTrue(cnx.isDestroyed()); } else { updater.setFailedUpdater(queueConnections.getFailedUpdater()); if (PoolImpl.AFTER_PRIMARY_IDENTIFICATION_FROM_BACKUP_CALLBACK_FLAG) { ClientServerObserver bo = ClientServerObserverHolder.getInstance(); bo.afterPrimaryIdentificationFromBackup(cnx.getServer());
void endpointCrashed(Endpoint endpoint) { QueueConnectionImpl deadConnection = null; // We must be synchronized while checking to see if we have a queue connection for the endpoint, // because when we need to prevent a race between adding a queue connection to the map // and the endpoint for that connection crashing. synchronized (lock) { deadConnection = queueConnections.getConnection(endpoint); if (deadConnection != null) { queueConnections = queueConnections.removeConnection(deadConnection); } } if (deadConnection != null) { logger .info("{} subscription endpoint {} crashed. Scheduling recovery.", new Object[] {deadConnection.getUpdater() != null ? (deadConnection.getUpdater().isPrimary() ? "Primary" : "Redundant") : "Queue", endpoint}); scheduleRedundancySatisfierIfNeeded(0); deadConnection.internalDestroy(); } else { if (logger.isDebugEnabled()) { logger.debug("Ignoring crashed endpoint {} it does not have a queue.", endpoint); } } }
logger.debug("QueueManagerImpl - closing primary {}", primary); primary.internalClose(keepAlive); } catch (Exception e) { logger.warn("Error closing primary connection to " + primary.getEndpoint(), e); logger.debug("QueueManagerImpl - closing backup {}", backup); backup.internalClose(keepAlive); } catch (Exception e) { logger.warn("Error closing backup connection to " + backup.getEndpoint(), e);
private boolean recoverInterest(final QueueConnectionImpl newConnection, final boolean isFirstNewConnection) { if (pool.getPoolOrCacheCancelInProgress() != null) { return true; } // recover interest try { recoverAllInterestTypes(newConnection, isFirstNewConnection); newConnection.getFailureTracker().reset(); return true; } catch (CancelException ignore) { return true; // ok to ignore we are being shutdown } catch (VirtualMachineError err) { SystemFailure.initiateFailure(err); // If this ever returns, rethrow the error. We're poisoned // now, so don't let this thread continue. throw err; } catch (Throwable t) { SystemFailure.checkFailure(); pool.getCancelCriterion().checkCancelInProgress(t); logger.warn("QueueManagerImpl failed to recover interest to server " + newConnection.getServer(), t); newConnection.getFailureTracker().addFailure(); newConnection.destroy(); return false; } }
/** * Return the cache client updater from the previously failed primary * * @return the previous updater or null if there is no previous updater */ public ClientUpdater getFailedUpdater() { if (failedPrimary != null) { return failedPrimary.getUpdater(); } else { return null; } }
@Override public void readyForEvents(InternalDistributedSystem system) { synchronized (lock) { this.sentClientReady = true; } QueueConnectionImpl primary = null; while (primary == null) { try { primary = (QueueConnectionImpl) getAllConnections().getPrimary(); } catch (NoSubscriptionServersAvailableException ignore) { primary = null; break; } if (primary.sendClientReady()) { try { logger.info("Sending ready for events to primary: {}", primary); ReadyForEventsOp.execute(pool, primary); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Error sending ready for events to {}", primary, e); } primary.destroy(); primary = null; } } } }
logger.debug( "SubscriptionManager redundancy satisfier - Switched backup server to primary: {}", newPrimary.getEndpoint()); bo.afterPrimaryRecovered(newPrimary.getServer()); excludedServers.add(newPrimary.getServer()); newPrimary = null; logger.debug( "SubscriptionManager redundancy satisfier - Non backup server was made primary. Recovering interest {}", newPrimary.getEndpoint()); excludedServers.add(newPrimary.getServer()); newPrimary = null; bo.afterPrimaryRecovered(newPrimary.getServer());
private QueueConnectionImpl initializeQueueConnection(Connection connection, boolean isPrimary, ClientUpdater failedUpdater) { QueueConnectionImpl queueConnection = null; FailureTracker failureTracker = denyList.getFailureTracker(connection.getServer()); try { ClientUpdater updater = factory.createServerToClientConnection(connection.getEndpoint(), this, isPrimary, failedUpdater); if (updater != null) { queueConnection = new QueueConnectionImpl(this, connection, updater, failureTracker); } else { logger.warn("unable to create a subscription connection to server {}", connection.getEndpoint()); } } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("error creating subscription connection to server {}", connection.getEndpoint(), e); } } if (queueConnection == null) { failureTracker.addFailure(); connection.destroy(); } return queueConnection; }
@Override public ConnectionStats getStats() { return getEndpoint().getStats(); }
@Override public String toString() { Connection result = (Connection) this.clientToServerConn.get(); if (result != null) { return result.toString(); } else { return "SubscriptionConnectionImpl[" + getServer() + ":closed]"; } }
public boolean isPrimaryUpdaterAlive() { boolean result = false; QueueConnectionImpl primary = (QueueConnectionImpl) queueConnections.getPrimary(); if (primary != null) { ClientUpdater cu = primary.getUpdater(); if (cu != null) { result = cu.isAlive(); } } return result; }
@Override public ServerLocation getServer() { return getEndpoint().getLocation(); }
excludedServers.add(primaryQueue.getServer()); primaryQueue = null;
private boolean addToConnectionList(QueueConnectionImpl connection, boolean isPrimary) { boolean isBadConnection; synchronized (lock) { ClientUpdater cu = connection.getUpdater(); if (cu == null || (!cu.isAlive()) || (!cu.isProcessing())) return false;// don't add if (connection.getEndpoint().isClosed() || shuttingDown || pool.getPoolOrCacheCancelInProgress() != null) { isBadConnection = true; logger.debug( "Endpoint {} crashed while creating a connection. The connection will be destroyed", connection.getEndpoint()); connection.internalClose(pool.getKeepAlive()); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Error destroying client to server connection to {}", connection.getEndpoint(), e);
void createClientCacheAndVerifyPingIntervalIsSet(String host, int port) throws Exception { PoolImpl pool = null; try { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, ""); createCache(props); pool = (PoolImpl) PoolManager.createFactory().addServer(host, port) .setSubscriptionEnabled(true).setThreadLocalConnections(false).setReadTimeout(1000) .setSocketBufferSize(32768).setMinConnections(1).setSubscriptionRedundancy(-1) .setPingInterval(2000).create("test pool"); Region<Object, Object> region = cache.createRegionFactory(RegionShortcut.LOCAL) .setPoolName("test pool").create(REGION_NAME1); region.registerInterest(".*"); /** get the subscription connection and verify that it has the correct timeout setting */ QueueConnectionImpl primaryConnection = (QueueConnectionImpl) pool.getPrimaryConnection(); int pingInterval = ((CacheClientUpdater) primaryConnection.getUpdater()) .getServerQueueStatus().getPingInterval(); assertNotEquals(0, pingInterval); assertEquals(CacheClientNotifier.getClientPingInterval(), pingInterval); } finally { cache.close(); } }
@Override public Socket getSocket() { return getConnection().getSocket(); }