com.gemstone.gemfire.internal.cache.AbstractBridgeServer 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
/*
* 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.internal.cache;
import com.gemstone.gemfire.CancelException;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.cache.server.ClientSubscriptionConfig;
import com.gemstone.gemfire.cache.server.ServerLoadProbe;
import com.gemstone.gemfire.cache.util.BridgeMembership;
import com.gemstone.gemfire.cache.util.BridgeMembershipEvent;
import com.gemstone.gemfire.cache.util.BridgeMembershipListener;
import com.gemstone.gemfire.cache.util.BridgeMembershipListenerAdapter;
import com.gemstone.gemfire.cache.util.BridgeServer;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.internal.DM;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.internal.admin.ClientMembershipMessage;
import com.gemstone.gemfire.internal.cache.xmlcache.CacheCreation;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
/**
* Abstract class that contains common code that all true implementations
* of {@link CacheServer} can use.
*
* @author darrel
* @since 5.7
*/
public abstract class AbstractBridgeServer implements CacheServer, BridgeServer {
public static final String TEST_OVERRIDE_DEFAULT_PORT_PROPERTY = "gemfire.test.CacheServer.OVERRIDE_DEFAULT_PORT";
/** The cache that is served by this bridge server */
protected final Cache cache;
/** The port that the bridge server was configured to run on */
protected int port;
/** The maximum number of connections that the BridgeServer will accept */
protected int maxConnections;
/** The maximum number of threads that the BridgeServer will create */
protected int maxThreads;
/** Whether the bridge server notifies by subscription */
protected boolean notifyBySubscription = true;
/**
* The buffer size in bytes of the socket for this
* BridgeServer
*/
protected int socketBufferSize;
/**
* The tcpNoDelay setting for outgoing sockets
*/
protected boolean tcpNoDelay;
/**
* The maximum amount of time between client pings. This value is used by
* the ClientHealthMonitor
to determine the health of this
* BridgeServer
's clients.
*/
protected int maximumTimeBetweenPings;
/** the maximum number of messages that can be enqueued in a client-queue. */
protected int maximumMessageCount;
/**
* the time (in seconds) after which a message in the client queue will
* expire.
*/
protected int messageTimeToLive;
/**
* The groups this server belongs to. Use getGroups
to read.
* @since 5.7
*/
protected String[] groups;
protected ServerLoadProbe loadProbe;
/**
* The ip address or host name that this server is to listen on.
* @since 5.7
*/
protected String bindAddress;
/**
* The ip address or host name that will be given to clients so they can connect
* to this server
* @since 5.7
*/
protected String hostnameForClients;
/**
* How frequency to poll the load on this server.
*/
protected long loadPollInterval;
protected ClientSubscriptionConfig clientSubscriptionConfig;
/**
* Listener that would listen to bridge membership and notify the admin
* members(if any exist) as clients of this server leave/crash.
*/
protected final BridgeMembershipListener listener;
/**
* The number of seconds to keep transaction states for disconnected clients.
* This allows the client to fail over to another server and still find
* the transaction state to complete the transaction.
*/
private int transactionTimeToLive;
////////////////////// Constructors //////////////////////
/**
* Creates a new BridgeServer
with the default
* configuration.
*
* @param cache
* The cache being served
*/
public AbstractBridgeServer(Cache cache) {
this(cache, true);
}
public AbstractBridgeServer(Cache cache, boolean attachListener) {
this.cache = cache;
this.port = Integer.getInteger(TEST_OVERRIDE_DEFAULT_PORT_PROPERTY, CacheServer.DEFAULT_PORT);
this.maxConnections = CacheServer.DEFAULT_MAX_CONNECTIONS;
this.maxThreads = CacheServer.DEFAULT_MAX_THREADS;
this.socketBufferSize = CacheServer.DEFAULT_SOCKET_BUFFER_SIZE;
this.tcpNoDelay = CacheServer.DEFAULT_TCP_NO_DELAY;
this.maximumTimeBetweenPings = CacheServer.DEFAULT_MAXIMUM_TIME_BETWEEN_PINGS;
this.maximumMessageCount = CacheServer.DEFAULT_MAXIMUM_MESSAGE_COUNT;
this.messageTimeToLive = CacheServer.DEFAULT_MESSAGE_TIME_TO_LIVE;
// TODO this should be configurable in CacheServer
this.transactionTimeToLive = Integer.getInteger("gemfire.cacheServer.transactionTimeToLive", 180);
this.groups = CacheServer.DEFAULT_GROUPS;
this.bindAddress = CacheServer.DEFAULT_BIND_ADDRESS;
this.hostnameForClients = CacheServer.DEFAULT_HOSTNAME_FOR_CLIENTS;
this.loadProbe = CacheServer.DEFAULT_LOAD_PROBE;
this.loadPollInterval = CacheServer.DEFAULT_LOAD_POLL_INTERVAL;
this.clientSubscriptionConfig = new ClientSubscriptionConfigImpl();
if (!attachListener) {
this.listener = null;
return;
}
listener = new BridgeMembershipListenerAdapter() {
/**
* Invoked when a client connected to this process or when this process
* has got connected with a BridgeServer.
*
* @param event
* BridgeMembershipEvent associated with client getting connected
*/
@Override
public void memberJoined(BridgeMembershipEvent event) {
/* process events for clients only */
if (event.isClient()) {
createAndSendMessage(event, ClientMembershipMessage.JOINED);
}
}
/**
* Invoked when a client has gracefully disconnected from this process
* or when this process has gracefully disconnected from a BridgeServer.
*
* @param event
* BridgeMembershipEvent associated with client leaving gracefully
*/
@Override
public void memberLeft(BridgeMembershipEvent event) {
/* process events for clients only */
if (event.isClient()) {
createAndSendMessage(event, ClientMembershipMessage.LEFT);
}
}
/**
* Invoked when a client has unexpectedly disconnected from this process
* or when this process has unexpectedly disconnected from a BridgeServer.
*
* @param event
* BridgeMembershipEvent associated with client getting
* disconnected unexpectedly
*/
@Override
public void memberCrashed(BridgeMembershipEvent event) {
/* process events for clients only */
if (event.isClient()) {
createAndSendMessage(event, ClientMembershipMessage.CRASHED);
}
}
/**
* Method to create & send the ClientMembershipMessage to admin members.
* The message is sent only if there are any admin members in the
* distribution system.
*
* @param event
* BridgeMembershipEvent associated for a change in client
* membership
* @param type
* type of event - one of ClientMembershipMessage.JOINED,
* ClientMembershipMessage.LEFT, ClientMembershipMessage.CRASHED
*/
private void createAndSendMessage(BridgeMembershipEvent event, int type) {
InternalDistributedSystem ds = null;
Cache cacheInstance = AbstractBridgeServer.this.cache;
if (cacheInstance != null && !(cacheInstance instanceof CacheCreation)) {
ds = (InternalDistributedSystem)cacheInstance.getDistributedSystem();
} else {
ds = InternalDistributedSystem.getAnyInstance();
}
//ds could be null
if (ds != null && ds.isConnected()) {
DM dm = ds.getDistributionManager();
Set adminMemberSet = dm.getAdminMemberSet();
/* check if there are any admin members at all */
if (!adminMemberSet.isEmpty()) {
DistributedMember member = event.getMember();
ClientMembershipMessage msg =
new ClientMembershipMessage(event.getMemberId(),
member == null ? null : member.getHost(),
type);
msg.setRecipients(adminMemberSet);
dm.putOutgoing(msg);
}
}
}
};
BridgeMembership.registerBridgeMembershipListener(listener);
}
///////////////////// Instance Methods /////////////////////
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
public String getBindAddress() {
return this.bindAddress;
}
public void setBindAddress(String address) {
this.bindAddress = address;
}
public String getHostnameForClients() {
return this.hostnameForClients;
}
public void setHostnameForClients(String name) {
this.hostnameForClients = name;
}
public int getMaxConnections() {
return this.maxConnections;
}
public void setMaxConnections(int maxCon) {
this.maxConnections = maxCon;
}
public int getMaxThreads() {
return this.maxThreads;
}
public void setMaxThreads(int maxThreads) {
this.maxThreads = maxThreads;
}
public void start() throws IOException {
// This method is invoked during testing, but it is not necessary
// to do anything.
}
public void setNotifyBySubscription(boolean b) {
//this.notifyBySubscription = true;
}
public boolean getNotifyBySubscription() {
return this.notifyBySubscription;
}
public void setSocketBufferSize(int socketBufferSize) {
this.socketBufferSize = socketBufferSize;
}
public int getSocketBufferSize() {
return this.socketBufferSize;
}
public void setMaximumTimeBetweenPings(int maximumTimeBetweenPings) {
this.maximumTimeBetweenPings = maximumTimeBetweenPings;
}
public int getMaximumTimeBetweenPings() {
return this.maximumTimeBetweenPings;
}
public int getMaximumMessageCount() {
return this.maximumMessageCount;
}
public void setMaximumMessageCount(int maximumMessageCount) {
this.maximumMessageCount = maximumMessageCount;
}
public void setTransactionTimeToLive(int seconds) {
this.transactionTimeToLive = seconds;
}
public int getTransactionTimeToLive() {
return this.transactionTimeToLive;
}
public int getMessageTimeToLive() {
return this.messageTimeToLive;
}
public void setMessageTimeToLive(int messageTimeToLive) {
this.messageTimeToLive = messageTimeToLive;
}
public void setGroups(String[] groups) {
if (groups == null) {
this.groups = CacheServer.DEFAULT_GROUPS;
}
else if (groups.length > 0) {
// copy it for isolation
String [] copy = new String[groups.length];
System.arraycopy(groups, 0, copy, 0, groups.length);
this.groups = copy;
} else {
this.groups = CacheServer.DEFAULT_GROUPS; // keep findbugs happy
}
}
public String[] getGroups() {
String[] result = this.groups;
if (result.length > 0) {
// copy it for isolation
String [] copy = new String[result.length];
System.arraycopy(result, 0, copy, 0, result.length);
result = copy;
}
return result;
}
public ServerLoadProbe getLoadProbe() {
return loadProbe;
}
public void setLoadProbe(ServerLoadProbe loadProbe) {
this.loadProbe = loadProbe;
}
public long getLoadPollInterval() {
return loadPollInterval;
}
public void setLoadPollInterval(long loadPollInterval) {
this.loadPollInterval = loadPollInterval;
}
public void setTcpNoDelay(boolean setting) {
this.tcpNoDelay = setting;
}
public boolean getTcpNoDelay() {
return this.tcpNoDelay;
}
public Cache getCache() {
return this.cache;
}
private static boolean eq(String s1, String s2) {
if (s1 == null) {
return s2 == null;
} else {
return s1.equals(s2);
}
}
/**
* Returns whether or not this bridge server has the same
* configuration as another bridge server.
*/
public boolean sameAs(CacheServer other) {
return getPort() == other.getPort()
&& eq(getBindAddress(), other.getBindAddress())
&& getSocketBufferSize() == other.getSocketBufferSize()
&& getMaximumTimeBetweenPings() == other.getMaximumTimeBetweenPings()
&& getNotifyBySubscription() == other.getNotifyBySubscription()
&& getMaxConnections() == other.getMaxConnections()
&& getMaxThreads() == other.getMaxThreads()
&& getMaximumMessageCount() == other.getMaximumMessageCount()
&& getMessageTimeToLive() == other.getMessageTimeToLive()
&& Arrays.equals(getGroups(), other.getGroups())
&& getLoadProbe().equals(other.getLoadProbe())
&& getLoadPollInterval() == other.getLoadPollInterval()
&& getTcpNoDelay() == other.getTcpNoDelay();
}
}