com.gemstone.gemfire.cache.client.internal.ConnectionFactoryImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
The newest version!
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.cache.client.internal;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import com.gemstone.gemfire.CancelCriterion;
import com.gemstone.gemfire.cache.GatewayConfigurationException;
import com.gemstone.gemfire.cache.client.ServerRefusedConnectionException;
import com.gemstone.gemfire.cache.client.internal.ServerBlackList.FailureTracker;
import com.gemstone.gemfire.cache.wan.GatewaySender;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.PoolCancelledException;
import com.gemstone.gemfire.distributed.internal.ServerLocation;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.cache.PoolManagerImpl;
import com.gemstone.gemfire.internal.cache.tier.Acceptor;
import com.gemstone.gemfire.internal.cache.tier.sockets.CacheClientUpdater;
import com.gemstone.gemfire.internal.cache.tier.sockets.ClientProxyMembershipID;
import com.gemstone.gemfire.internal.cache.tier.sockets.HandShake;
import com.gemstone.gemfire.internal.cache.wan.GatewaySenderConfigurationException;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.security.GemFireSecurityException;
/**
* Creates connections, using a connection source to determine
* which server to connect to.
* @author dsmith
* @since 5.7
*
*/
public class ConnectionFactoryImpl implements ConnectionFactory {
//TODO - the handshake holds state. It seems like the code depends
//on all of the handshake operations happening in a single thread. I don't think we
//want that, need to refactor.
private final HandShake handshake;
private final int socketBufferSize;
private final int handShakeTimeout;
private final LogWriterI18n logger;
private final boolean usedByGateway;
private final ServerBlackList blackList;
private final CancelCriterion cancelCriterion;
private ConnectionSource source;
private int readTimeout;
private DistributedSystem ds;
private EndpointManager endpointManager;
private GatewaySender gatewaySender;
/**
* Test hook for client version support
* @since 5.7
*/
public static boolean testFailedConnectionToServer = false;
public ConnectionFactoryImpl(ConnectionSource source,
EndpointManager endpointManager, DistributedSystem sys,
int socketBufferSize, int handShakeTimeout, int readTimeout,
LogWriterI18n logger, ClientProxyMembershipID proxyId,
CancelCriterion cancelCriterion, boolean usedByGateway,GatewaySender sender,
long pingInterval, boolean multiuserSecureMode) {
this.handshake = new HandShake(proxyId, sys);
this.handshake.setClientReadTimeout(readTimeout);
this.source = source;
this.endpointManager = endpointManager;
this.ds = sys;
this.socketBufferSize = socketBufferSize;
this.handShakeTimeout = handShakeTimeout;
this.handshake.setMultiuserSecureMode(multiuserSecureMode);
this.readTimeout = readTimeout;
this.logger = logger;
this.usedByGateway = usedByGateway;
this.gatewaySender = sender;
this.blackList = new ServerBlackList(logger, pingInterval);
this.cancelCriterion = cancelCriterion;
}
public void start(ScheduledExecutorService background) {
blackList.start(background);
}
private byte getCommMode(boolean forQueue) {
if (this.usedByGateway || (this.gatewaySender != null)) {
return Acceptor.GATEWAY_TO_GATEWAY;
} else if(forQueue) {
return Acceptor.CLIENT_TO_SERVER_FOR_QUEUE;
} else {
return Acceptor.CLIENT_TO_SERVER;
}
}
public ServerBlackList getBlackList() {
return blackList;
}
public Connection createClientToServerConnection(ServerLocation location, boolean forQueue) throws GemFireSecurityException {
ConnectionImpl connection = new ConnectionImpl(logger, this.ds, this.cancelCriterion);
FailureTracker failureTracker = blackList.getFailureTracker(location);
boolean initialized = false;
try {
//ds.getLogWriter().warning("CREATING CLIENT SERVER:"+location,new Exception());
HandShake connHandShake = new HandShake(handshake);
connection.connect(endpointManager, location, connHandShake,
socketBufferSize, handShakeTimeout, readTimeout, getCommMode(forQueue), this.gatewaySender);
failureTracker.reset();
connection.setHandShake(connHandShake);
authenticateIfRequired(connection);
initialized = true;
} catch(GemFireSecurityException e) {
//propagate this up, don't retry
throw e;
} catch(GatewayConfigurationException e) {
//propagate this up, don't retry
throw e;
} catch(ServerRefusedConnectionException src) {
//propagate this up, don't retry
logger.warning(LocalizedStrings.AutoConnectionSourceImpl_COULD_NOT_CREATE_A_NEW_CONNECTION_TO_SERVER_0, src.getMessage());
testFailedConnectionToServer = true;
throw src;
} catch (Exception e) {
if(logger.fineEnabled()) {
if (e.getMessage() != null &&
e.getMessage().equals("Connection refused")) { // this is the most common case, so don't print an exception
logger.fine("Unable to connect to " + location + ": connection refused");
} else {
logger.fine("Error attempting to connect to " + location + ": ", e);
}
}
testFailedConnectionToServer = true;
} finally {
if(!initialized) {
connection.destroy();
failureTracker.addFailure();
connection = null;
}
}
return connection;
}
private void authenticateIfRequired(Connection conn) {
PoolImpl pool = (PoolImpl)PoolManagerImpl.getPMI().find(
this.endpointManager.getPoolName());
if (pool == null) {
throw new PoolCancelledException(
LocalizedStrings.ConnectionFactoryImpl_POOL_0_IS_NOT_AVAILABLE
.toString(new Object[] { this.endpointManager.getPoolName() }));
}
if (!pool.isUsedByGateway() && !pool.getMultiuserAuthentication()) {
if (conn.getServer().getRequiresCredentials()) {
if (conn.getServer().getUserId() == -1) {
Long uniqueID = (Long)AuthenticateUserOp.executeOn(conn, pool);
conn.getServer().setUserId(uniqueID);
if (logger.fineEnabled()) {
logger.fine("CFI.authenticateIfRequired() Completed authentication on " + conn);
}
}
}
}
}
public ServerLocation findBestServer(ServerLocation currentServer, Set excludedServers) {
if (currentServer != null && source.isBalanced()) {
return currentServer;
}
final Set origExcludedServers = excludedServers;
excludedServers = new HashSet(excludedServers);
Set blackListedServers = blackList.getBadServers();
excludedServers.addAll(blackListedServers);
ServerLocation server = source.findReplacementServer(currentServer, excludedServers);
if (server == null) {
// Nothing worked! Let's try without the blacklist.
if (excludedServers.size() > origExcludedServers.size()) {
// We had some guys black listed so lets give this another whirl.
server = source.findReplacementServer(currentServer, origExcludedServers);
}
}
if (server == null) {
logger.fine("Source was unable to findForReplacement any servers");
}
return server;
}
public Connection createClientToServerConnection(Set excludedServers) throws GemFireSecurityException {
final Set origExcludedServers = excludedServers;
excludedServers = new HashSet(excludedServers);
Set blackListedServers = blackList.getBadServers();
excludedServers.addAll(blackListedServers);
Connection conn = null;
// long startTime = System.currentTimeMillis();
RuntimeException fatalException = null;
boolean tryBlackList = true;
do {
ServerLocation server = source.findServer(excludedServers);
if(server == null) {
if(tryBlackList) {
// Nothing worked! Let's try without the blacklist.
tryBlackList = false;
int size = excludedServers.size();
excludedServers.removeAll(blackListedServers);
// make sure we didn't remove any of the ones that the caller set not to use
excludedServers.addAll(origExcludedServers);
if(excludedServers.size()