com.gemstone.gemfire.distributed.internal.membership.jgroup.LocatorImpl 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.distributed.internal.membership.jgroup;
import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Timer;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
import com.gemstone.gemfire.distributed.internal.tcpserver.TcpHandler;
import com.gemstone.gemfire.distributed.internal.tcpserver.TcpServer;
import com.gemstone.gemfire.internal.SocketCreator;
import com.gemstone.gemfire.internal.VersionedObjectInput;
import com.gemstone.gemfire.internal.VersionedObjectOutput;
import com.gemstone.gemfire.internal.admin.remote.DistributionLocatorId;
import com.gemstone.gemfire.internal.shared.Version;
import com.gemstone.org.jgroups.Address;
import com.gemstone.org.jgroups.JGroupsVersion;
import com.gemstone.org.jgroups.stack.GossipClient;
import com.gemstone.org.jgroups.stack.GossipServer;
import com.gemstone.org.jgroups.stack.IpAddress;
import com.gemstone.org.jgroups.util.ExternalStrings;
import com.gemstone.org.jgroups.util.GemFireTracer;
/**
* LocatorHandler extends the JGroup GossipServer to provide persistence and
* recovery for the discovery set.
*/
public class LocatorImpl extends GossipServer implements TcpHandler {
public final static int GOSSIPVERSION = TcpServer.getCurrentGossipVersion();
// OLDGOSSIPVERSION is only used in _getVersionForAddress in GossipClient.
public final static int OLDGOSSIPVERSION = TcpServer.getOldGossipVersion();
// public final static int FILE_FORMAT_VERSION = 1003 - GF 7.0.1;
public static int FILE_FORMAT_VERSION = 1004; // added ip address
private static/* GemStoneAddition */ final Map FILE_FORMAT_TO_GEMFIRE_VERSION_MAP = new HashMap();
public final static boolean LOCATOR_DISCOVERY_DISABLED = Boolean.getBoolean("gemfire.disable-locator-discovery");
protected final GemFireTracer log=GemFireTracer.getLog(getClass());
File gossipFile; // GemStoneAddition
private File stateFile;
/**
* GemStoneAddition - Initialize versions map.
* Warning: This map must be compatible with all GemFire versions being
* handled by this member "With different GOSSIPVERION". If GOSSIPVERIONS
* are same for then current GOSSIPVERSION should be used.
*
* @since 7.1
*/
static {
FILE_FORMAT_TO_GEMFIRE_VERSION_MAP.put(1003, JGroupsVersion.GFE_701_ORDINAL);
FILE_FORMAT_TO_GEMFIRE_VERSION_MAP.put(1004, JGroupsVersion.CURRENT_ORDINAL);
}
/**
*
* @param port number of the tcp/ip server socket port to use
* @param expiry_time time until registration entries expire
* @param bind_address network address to bind to
* @param stateFile name of the file to persist state to/recover from
* @param locatorString location of other locators (bootstrapping, failover)
* @param floatingCoordinatorDisabled true if Coordinator can only be in Locators
* @param networkPartitionDetectionEnabled true if network partition detection is enabled
* @param withDS true if a distributed system has been or will be started
*/
public LocatorImpl(int port, long expiry_time,
InetAddress bind_address,
File stateFile,
String locatorString,
boolean floatingCoordinatorDisabled,
boolean networkPartitionDetectionEnabled,
boolean withDS)
{
super(port, expiry_time, bind_address, locatorString, floatingCoordinatorDisabled, networkPartitionDetectionEnabled, withDS);
this.stateFile = stateFile;
}
public void restarting(DistributedSystem ds, GemFireCache cache) {
}
/** recover gossip state from another locator or from the given stateFile
*
* @param sFile
* a file containing gossipserver state from a past run
* @param locatorsString
* a GemFire distributed system locators string
*/
public void recover(File sFile, String locatorsString) {
// First recover from file to find out correct versions of GossipServers
recoverFromFile(sFile);
// Send getMembers request with correct GemFire version number.
recoverFromOthers(locatorsString);
}
/** GemStoneAddition - get gossip state from another locator. Return
* true if we're able to contact another locator and get its state.
* @param locatorsString
* a string with locator specs in GemFire form
*/
private boolean recoverFromOthers(String locatorsString) {
String myAddr;
String myAddr2 = null;
if (locatorsString != null && locatorsString.length() > 0) {
if (this.bind_address == null) {
try {
myAddr = SocketCreator.getLocalHost().getHostName();
myAddr2 = SocketCreator.getLocalHost().getCanonicalHostName();
}
catch (UnknownHostException ue) {
log.getLogWriter().warning(ExternalStrings.GossipServer_UNABLE_TO_RESOLVE_LOCAL_HOST_NAME, ue);
myAddr = "localhost";
}
}
else {
myAddr = this.bind_address.getHostAddress();
myAddr2 = this.bind_address.getCanonicalHostName();
}
StringTokenizer st = new StringTokenizer(locatorsString, ",");
while (st.hasMoreTokens()) {
String l = st.nextToken();
DistributionLocatorId locId = new DistributionLocatorId(l);
if (!locId.isMcastId()) {
String otherAddr = locId.getBindAddress();
String otherAddr2 = null;
if (otherAddr != null) {
otherAddr = otherAddr.trim();
}
if (otherAddr == null || otherAddr.length() == 0) {
otherAddr = locId.getHost().getHostName();
otherAddr2 = locId.getHost().getCanonicalHostName(); // some people use fqns
}
if ( !( (
otherAddr.equals(myAddr) || (otherAddr2 != null && otherAddr2.equals(myAddr)) || (myAddr2 != null && myAddr2.equals(otherAddr2))
)
&& locId.getPort() == this.port) ) {
log.getLogWriter().info(ExternalStrings.GossipServer_0__1__ATTEMPTING_TO_GET_STATE_FROM__2__3_, new Object[] {myAddr, Integer.valueOf(this.port), otherAddr, Integer.valueOf(locId.getPort())});
if (recover(otherAddr, locId.getPort())) {
return true;
}
}
}
} // while()
} // if (locatorsString)
return false;
}
/** try to recover gossip state from another locator */
private boolean recover(String address, int serverPort) {
// Contact existing locator first to find out all members in system.
GossipClient gc = new GossipClient(
new IpAddress(address, serverPort), 20000);
List info = gc.getMembers(CHANNEL_NAME, (Address)null, false, 15000);
if (gc.getResponsiveServerCount() > 0) {
List mbrs = new VersionedEntryList(info.size());
for (int i=0; i itr = this.iterator();
while(itr.hasNext()) {
Entry entry = itr.next();
entry.writeExternal(out);
}
}
}
/**
* Returns File Version for older Gemfire versions. If we have mappings
* "[1000 -> GF_70], [1001 -> GF_71]" and passed version is GF_701 and there
* is no mapping for GF_701 we will return 1000 which is lower closest
* possible to GF_701.
*
* @param ordinal
* @return gossip version
*/
public static int getFileVersionForOrdinal(short ordinal) {
// Sanity check
short closest = -1;
int closestFV = LocatorImpl.FILE_FORMAT_VERSION;
if (ordinal <= Version.CURRENT_ORDINAL) {
Iterator itr = LocatorImpl.FILE_FORMAT_TO_GEMFIRE_VERSION_MAP.entrySet().iterator();
while (itr.hasNext()) {
Map.Entry entry = (Map.Entry)itr.next();
short o = ((Short)entry.getValue()).shortValue();
if (o == ordinal) {
return ((Integer)entry.getKey()).intValue();
} else if (o < ordinal && o > closest ) {
closest = o;
closestFV = ((Integer)entry.getKey()).intValue();
}
}
}
return closestFV;
}
public static Map getFileVersionMapForTestOnly() {
return FILE_FORMAT_TO_GEMFIRE_VERSION_MAP;
}
}