All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.distributed.internal.membership.jgroup.LocatorImpl Maven / Gradle / Ivy

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;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy