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

com.gemstone.org.jgroups.protocols.TCPGOSSIP Maven / Gradle / Ivy

The newest version!
/** Notice of modification as required by the LGPL
 *  This file was modified by Gemstone Systems Inc. on
 *  $Date$
 **/
// $Id: TCPGOSSIP.java,v 1.16 2005/08/11 12:43:47 belaban Exp $

package com.gemstone.org.jgroups.protocols;


import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;

import com.gemstone.org.jgroups.Address;
import com.gemstone.org.jgroups.Event;
import com.gemstone.org.jgroups.JChannel;
import com.gemstone.org.jgroups.Message;
import com.gemstone.org.jgroups.stack.GossipClient;
import com.gemstone.org.jgroups.stack.IpAddress;
import com.gemstone.org.jgroups.util.ExternalStrings;


/**
 * The TCPGOSSIP protocol layer retrieves the initial membership (used by the GMS when started
 * by sending event FIND_INITIAL_MBRS down the stack).
 * We do this by contacting one or more GossipServers, which must be running at well-known
 * addresses:ports. The responses should allow us to determine the coordinator whom we have to
 * contact, e.g. in case we want to join the group.  When we are a server (after having
 * received the BECOME_SERVER event), we'll respond to TCPGOSSIP requests with a TCPGOSSIP
 * response.

The FIND_INITIAL_MBRS event will eventually be answered with a * FIND_INITIAL_MBRS_OK event up the stack. * * @author Bela Ban */ public class TCPGOSSIP extends Discovery { Vector initial_hosts=null; // (list of IpAddresses) hosts to be contacted for the initial membership GossipClient gossip_client=null; // accesses the GossipServer(s) to find initial mbrship // we need to refresh the registration with the GossipServer(s) periodically, // so that our entries are not purged from the cache long gossip_refresh_rate=20000; private boolean splitBrainDetectionEnabled; // GemStoneAddition private int gossipServerWaitTime; // GemStoneAddition final static Vector EMPTY_VECTOR=new Vector(); final static String name="TCPGOSSIP"; @Override // GemStoneAddition public String getName() { return name; } // start GemStoneAddition @Override // GemStoneAddition public int getProtocolEnum() { return com.gemstone.org.jgroups.stack.Protocol.enumTCPGOSSIP; } // end GemStone addition @Override // GemStoneAddition public boolean setProperties(Properties props) { String str; str=props.getProperty("gossip_refresh_rate"); // wait for at most n members if(str != null) { gossip_refresh_rate=Integer.parseInt(str); props.remove("gossip_refresh_rate"); } //GemStoneAddition - split-brain detection support str=props.getProperty("split-brain-detection"); if (str != null) { splitBrainDetectionEnabled = Boolean.valueOf(str).booleanValue(); props.remove("split-brain-detection"); } str=props.getProperty("initial_hosts"); if(str != null) { props.remove("initial_hosts"); initial_hosts=createInitialHosts(str); } str = props.getProperty("gossip_server_wait_time"); if (str != null) { props.remove("gossip_server_wait_time"); gossipServerWaitTime = Integer.parseInt(str); } if(initial_hosts == null || initial_hosts.size() == 0) { if(log.isErrorEnabled()) log.error(ExternalStrings.TCPGOSSIP_INITIAL_HOSTS_MUST_CONTAIN_THE_ADDRESS_OF_AT_LEAST_ONE_GOSSIPSERVER); return false; } return super.setProperties(props); } @Override // GemStoneAddition public void start() throws Exception { super.start(); if(gossip_client == null) { gossip_client=new GossipClient(initial_hosts, gossip_refresh_rate, this.stack); gossip_client.setTimeout((int)this.timeout); } } @Override // GemStoneAddition public void stop() { super.stop(); if(gossip_client != null) { gossip_client.stop(); //gossip_client=null; } } @Override // GemStoneAddition public void handleConnectOK() { if(group_addr == null || local_addr == null) { if(log.isErrorEnabled()) log.error("[CONNECT_OK]: group_addr or local_addr is null. " + "cannot register with GossipServer(s)"); } else { gossip_client.register(group_addr, local_addr, timeout, true); // GemStone - timeout, stack & inhibit registration } } private boolean ipWarningIssued; // GemStoneAddition - IP version checking @Override // GemStoneAddition public void sendGetMembersRequest(AtomicBoolean waiter_sync) { // GemStoneAddition - both parameters Message msg, copy; PingHeader hdr; Vector tmp_mbrs; Address mbr_addr; GossipClient client = gossip_client; // GemStoneAddition - gossip_client gets nulled when this proto is stopped // bug #41484 - only use coordinator advice from the gossip server once boolean shortcutOK = !this.stack.hasTriedJoinShortcut(); if(group_addr == null) { if(log.isErrorEnabled()) log.error(ExternalStrings.TCPGOSSIP_FIND_INITIAL_MBRS_GROUP_ADDR_IS_NULL_CANNOT_GET_MBRSHIP); passUp(new Event(Event.FIND_INITIAL_MBRS_OK, EMPTY_VECTOR)); return; } if(trace) log.trace("fetching members from GossipServer(s)"); // GemStoneAddition - bug 28965: don't allow startup if no gossip server boolean isAdminOnly = stack.gfPeerFunctions.isAdminOnlyMember(); //do { GemStone - see comment below if (gossip_client == null) return; long giveUpTime = System.currentTimeMillis() + (this.gossipServerWaitTime * 1000L); tmp_mbrs=client.getMembers(group_addr, local_addr, true, this.timeout); // GemStoneAddition - send local addr on get boolean firstWait = true; boolean startupStatusWaitingSet = false; // if (isAdminOnly) { // GemStoneAddition - this if-else block added while (gossip_client != null && client.getResponsiveServerCount() == 0 || tmp_mbrs == null || tmp_mbrs.size() == 0) { // Wait, until we can contact at least one of our // gossip servers and it had someone register with it if (!isAdminOnly && System.currentTimeMillis() >= giveUpTime) { break; } if (firstWait) { StringBuilder sb = new StringBuilder(100); for (Object obj: this.initial_hosts) { if (!firstWait) { sb.append(','); } firstWait = false; IpAddress addr = (IpAddress)obj; sb.append(addr.getIpAddress().getHostName()) .append('[') .append(addr.getPort()) .append(']'); } // inform gfsh / ServerLauncher startupStatusWaitingSet = true; stack.gfPeerFunctions.logStartup(ExternalStrings.WAITING_FOR_LOCATOR_TO_START,sb.toString()); } try { Thread.sleep(1000); } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); // GemStoneAddition return; // GemStoneAddition } tmp_mbrs=client.getMembers(group_addr, local_addr, true, timeout); // GemStone Addition 08-04-04 // if the VM is exiting, return so that the distributed system // sync can be released and the shutdown hook can do its job if (stack.gfPeerFunctions.shutdownHookIsAlive()) { throw stack.gfBasicFunctions.getGemFireConfigException("Unable to contact a Locator service before detecting that VM is exiting"); } } // } else { // if (gossip_client == null) GemStoneAddition (this is never null) // return; if (client.getResponsiveServerCount() == 0) { RuntimeException re = stack.gfBasicFunctions.getGemFireConfigException("Unable to contact a Locator service. Operation either timed out or Locator does not exist. Configured list of locators is \"" + initial_hosts + "\"."); throw re; } // } if (startupStatusWaitingSet) { stack.gfPeerFunctions.logStartup(ExternalStrings.WAITING_FOR_LOCATOR_TO_START_COMPLETED); } Set

serverAddresses = client.getServerAddresses(); if (client.getFloatingCoordinatorDisabled()) { passUp(new Event(Event.FLOATING_COORDINATOR_DISABLED, null)); } if (client.getNetworkPartitionDetectionEnabled() != splitBrainDetectionEnabled) { if (!splitBrainDetectionEnabled) { splitBrainDetectionEnabled = true; passUp(new Event(Event.ENABLE_NETWORK_PARTITION_DETECTION)); } else { throw stack.gfBasicFunctions.getGemFireConfigException("Locator has enable-network-partition-detection=" + client.getNetworkPartitionDetectionEnabled() +" but this member has enable-network-partition-detection=" + splitBrainDetectionEnabled); } } if (client.getNetworkPartitionDetectionEnabled()) { stack.gfBasicFunctions.checkDisableDNS(); } // GemStoneAddition for bug 39220 see if we're using an incompatible // version of IP if (tmp_mbrs != null && !ipWarningIssued) { TP protocol = (TP)stack.findProtocol("UDP"); if (protocol == null) protocol = (TP)stack.findProtocol("TCP"); InetAddress bindAddress = protocol.getInetBindAddress(); if (bindAddress != null) { boolean iAmIPv4 = (bindAddress instanceof Inet4Address); for (int i=0; i= 0; i--) { mbr_addr=(Address)tmp_mbrs.elementAt(i); // make sure all required responders get the message if (!serverAddresses.contains(mbr_addr) && (msgs_sent >= max_msgs)) { continue; } copy=msg.copy(); copy.setDest(mbr_addr); if(trace) log.trace("[FIND_INITIAL_MBRS] sending PING request to " + copy.getDest()); passDown(new Event(Event.MSG, copy)); if (Thread.currentThread().isInterrupted()) { break; } msgs_sent++; } // GemStoneAddition - not really an addition, just a note from Bruce // that this used to have a wait-for-initial-members section that is // now gone, making the loop a bit difficult to implement //} while (isAdminOnly && initial_members.size() <= 0); } /* -------------------------- Private methods ---------------------------- */ /** * Input is "daddy[8880],sindhu[8880],camille[5555]. Return list of IpAddresses */ public static Vector createInitialHosts(String l) { Vector tmp=new Vector(); String host; int port; IpAddress addr; StringTokenizer tok=new StringTokenizer(l, ","); String t; boolean isLoopback = false; InetAddress myAddress = null; String bindAddress = System.getProperty("gemfire.jg-bind-address"); try { if (bindAddress == null) { isLoopback = JChannel.getGfFunctions().getLocalHost().isLoopbackAddress(); } else { isLoopback = InetAddress.getByName(bindAddress).isLoopbackAddress(); } } catch (UnknownHostException e) { // ignore } while(tok.hasMoreTokens()) { try { t=tok.nextToken(); host=t.substring(0, t.indexOf('[')); // GemStoneAddition - support for name:bind-addr[port] format int idx = host.lastIndexOf('@'); if (idx < 0) { idx = host.lastIndexOf(':'); } String h = host.substring(0, idx > -1 ? idx : host.length()); if (h.indexOf(':') >= 0) { // a single numeric ipv6 address idx = host.lastIndexOf('@'); } if (idx >= 0) { host = host.substring(idx+1, host.length()); } port=Integer.parseInt(t.substring(t.indexOf('[') + 1, t.indexOf(']'))); addr=new IpAddress(host, port); if (isLoopback && !addr.getIpAddress().isLoopbackAddress()) { // GemStoneAddition // TODO this should be a GemFireConfigException but that class isn't available // in a static method in the jgroups project throw new RuntimeException("This process is attempting to join with a loopback address ("+myAddress+") using a locator that does not have a local address ("+addr.getIpAddress()+"). On Unix this usually means that /etc/hosts is misconfigured."); } tmp.addElement(addr); } catch(NumberFormatException e) { //if(log.isErrorEnabled()) log.error(JGroupsStrings.TCPGOSSIP_EXEPTION_IS__0, e); } } return tmp; } @Override // GemStoneAddition public void destroy() { // GemStoneAddition - get rid of gossip timer if (gossip_client != null) { gossip_client.destroy(); gossip_client = null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy