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

com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember 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;

import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.InternalGemFireError;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.DurableClientAttributes;
import com.gemstone.gemfire.distributed.Role;
import com.gemstone.gemfire.distributed.internal.DistributionManager;
import com.gemstone.gemfire.distributed.internal.DistributionAdvisor.ProfileId;
import com.gemstone.gemfire.distributed.internal.membership.jgroup.GFJGBasicAdapter;
import com.gemstone.gemfire.distributed.internal.membership.jgroup.GFJGPeerAdapter;
import com.gemstone.gemfire.distributed.internal.membership.jgroup.JGroupMember;
import com.gemstone.gemfire.internal.Assert;
import com.gemstone.gemfire.internal.DataSerializableFixedID;
import com.gemstone.gemfire.internal.HeapDataOutputStream;
import com.gemstone.gemfire.internal.InternalDataSerializer;
import com.gemstone.gemfire.internal.SocketCreator;
import com.gemstone.gemfire.internal.cache.versions.VersionSource;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.shared.Version;
import com.gemstone.org.jgroups.stack.IpAddress;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * This is the fundamental representation of a member of a GemFire distributed
 * system.
 *
 * Unfortunately, this class serves two distinct functions. First, it is the
 * fundamental element of membership in the GemFire distributed system. As such,
 * it is used in enumerations and properly responds to hashing and equals()
 * comparisons.
 *
 * Second, it is used as a cheap way of representing an address. This is
 * unfortunate, because as a NetMember, it holds two separate port numbers: the
 * "membership" descriptor as well as a direct communication channel.
 *
 * TODO fix this.
 */
public final class InternalDistributedMember
 implements DistributedMember,
    Externalizable, DataSerializableFixedID, ProfileId,
    VersionSource
{
  private final static long serialVersionUID = -2785249969777296507L;
  
  protected NetMember ipAddr; // the underlying member object, e.g. from JGroups
  // private IpAddress ipAddr;

  /**
   * This is the direct channel port. The underlying NetMember must be able to
   * serialize and deliver this value.
   */
  private int dcPort = -1;

  /**
   * This is the process id of this member on its machine. The underlying
   * NetMember must be able to serialize and deliver this value.
   */
  private int vmPid = -1;

  /**
   * This is a representation of the type of VM. The underlying NetMember must
   * be able to serialize and deliver this value.
   */
  private int vmKind = -1;
  
  /**
   * This is the view identifier where this ID was born, or zero if this is
   * a loner member
   */
  private int vmViewId = -1;
  
  /**
   * whether this is a partial member ID (without roles, durable attributes).
   * We use partial IDs in EventID objects to reduce their size.  It would be
   * better to use canonical IDs but there is currently no central mechanism
   * that would allow that for both server and client identifiers
   */
  private boolean isPartial;

  /** Internal list of group/role names for this member. */
  private String[] groups;

  /**
   * The roles, if any, of this member. Lazily created first time getRoles()
   * is called.
   */
  private volatile Set rolesSet = null;

  /** lock object used when getting/setting roles/rolesSet fields */
  private final Object rolesLock = new Object();

  /**
   * The name of this member's distributed system connection.
   * @see com.gemstone.gemfire.distributed.DistributedSystem#getName
   */
  private String name = null;

  /**
   * Unique tag (such as randomly generated bytes) to help enforce uniqueness.
   * Note: this should be displayable.
   */
  private String uniqueTag = null;
  
  /**
   * essentialData is the serialized form of data that uniquely identifies this
   * member.  It is used to accelerate repeated serialization of the ID
   */
  private byte[] essentialData;

  /** serialization bit mask */
  private static final int SB_ENABLED_MASK = 0x1;

  /** serialization bit mask */
  private static final int COORD_ENABLED_MASK = 0x2;

  /** partial ID bit mask */
  private static final int PARTIAL_ID_MASK = 0x4;

  /** product version bit mask */
  private static final int VERSION_MASK = 0x8;

  /**
   * Representing the host name of this member.
   */
  private String hostName = null;

  private transient short version = Version.CURRENT_ORDINAL;

  private transient Version versionObj = Version.CURRENT;

  /**
   * User-defined attributes (id and timeout) used by durable clients.
   */
  private DurableClientAttributes durableClientAttributes = null;

  /** The versions in which this message was modified */
  private static final Version[] dsfidVersions = null;

  private void defaultToCurrentHost() {
    int defaultDcPort = MemberAttributes.DEFAULT.getPort();
 // [bruce] disabled to allow loners to modify the ID post-connect
 //    Assert.assertTrue(defaultDcPort > 0); 

    this.dcPort = defaultDcPort;;
    this.vmKind = MemberAttributes.DEFAULT.getVmKind();
    this.vmPid = MemberAttributes.DEFAULT.getVmPid();
    this.name = MemberAttributes.DEFAULT.getName();
    this.groups = MemberAttributes.DEFAULT.getGroups();
    this.vmViewId = MemberAttributes.DEFAULT.getVmViewId();
    this.durableClientAttributes = MemberAttributes.DEFAULT.getDurableClientAttributes();
    if (this.ipAddr instanceof JGroupMember) {
      ((JGroupMember)this.ipAddr).getAddress().setProcessId(this.vmPid);
    }
    try {
      if (SocketCreator.resolve_dns) {
        this.hostName = SocketCreator.getHostName(SocketCreator.getLocalHost());
      }
      else {
        this.hostName = SocketCreator.getLocalHost().getHostAddress();
      }
    }
    catch(UnknownHostException ee){
      throw new InternalGemFireError(ee);
    }
//    checkHostName();
  }


  // Used only by Externalization
  public InternalDistributedMember() {
    this.groups = new String[0];
  }

  /**
   * Construct a InternalDistributedMember.  All fields are specified.

* * This, and the following constructor are the only valid ways to create an ID * for a distributed member for use * in the P2P cache. Use of other constructors can break network-partition-detection. * * @param i * @param p * the membership port * @param splitBrainEnabled whether this feature is enabled for the member * @param canBeCoordinator whether the member is eligible to be the membership coordinator * @param attr * the member's attributes */ public InternalDistributedMember(InetAddress i, int p, boolean splitBrainEnabled, boolean canBeCoordinator, MemberAttributes attr) { this.dcPort = attr.getPort(); this.vmPid = attr.getVmPid(); this.vmKind = attr.getVmKind(); this.vmViewId = attr.getVmViewId(); this.name = attr.getName(); this.groups = attr.getGroups(); this.durableClientAttributes = attr.getDurableClientAttributes(); this.ipAddr = MemberFactory.newNetMember(i, p, splitBrainEnabled, canBeCoordinator, attr); this.hostName = SocketCreator.resolve_dns? SocketCreator.getHostName(i) : i.getHostAddress(); // checkHostName(); } /** * Construct a InternalDistributedMember based on the given NetMember.

* This is not the preferred way of creating an instance since the NetMember * may not have all required information (e.g., a JGroups address without * direct-port and other information). * @param m */ public InternalDistributedMember(NetMember m) { ipAddr = m; MemberAttributes attr = m.getAttributes(); this.hostName = SocketCreator.resolve_dns? SocketCreator.getHostName(m.getIpAddress()) : m.getIpAddress().getHostAddress(); // checkHostName(); if (attr == null) { // no extended information available, so this address is crippled } else { this.dcPort = attr.getPort(); this.vmPid = attr.getVmPid(); this.vmKind = attr.getVmKind(); this.vmViewId = attr.getVmViewId(); this.name = attr.getName(); this.groups = attr.getGroups(); this.durableClientAttributes = attr.getDurableClientAttributes(); } final IpAddress addr = ((JGroupMember)m).getAddress(); this.version = addr.getVersionOrdinal(); this.versionObj = Version.fromOrdinalOrCurrent(version); cachedToString = null; essentialData = null; } // private void checkHostName() { // // bug #44858: debug method to find who is putting a host name instead of addr into an ID // if (!SocketCreator.resolve_dns // && this.hostName != null && this.hostName.length() > 0 // && !Character.isDigit(this.hostName.charAt(0))) { // throw new RuntimeException("found hostname that doesn't start with a digit: " + this.hostName); // } // } /** * Create a InternalDistributedMember referring to the current host (as defined by the given * string).

* * * [bruce]THIS METHOD IS FOR TESTING ONLY. DO NOT USE IT TO CREATE IDs FOR * USE IN THE PRODUCT. IT DOES NOT PROPERLY INITIALIZE ATTRIBUTES NEEDED * FOR P2P FUNCTIONALITY. * * * * @param i * the hostname, must be for the current host * @param p * the membership listening port * @throws UnknownHostException if the given hostname cannot be resolved */ public InternalDistributedMember(String i, int p) throws UnknownHostException { ipAddr = MemberFactory.newNetMember(i, p); defaultToCurrentHost(); this.vmKind = DistributionManager.NORMAL_DM_TYPE; GFJGBasicAdapter.insertDefaultGemFireAttributes(((JGroupMember)ipAddr).getAddress()); } /** * Create a InternalDistributedMember referring to the current host * (as defined by the given string) with additional info including optional * connection name and an optional unique string. Currently these two * optional fields (and this constructor) are only used by the * LonerDistributionManager.

* * < b> * [bruce]DO NOT USE THIS METHOD TO CREATE ANYTHING OTHER THAN A LONER ID * WITHOUT TALKING TO ME FIRST. IT DOES NOT PROPERLY INITIALIZE THE ID. * * * @param i * the hostname, must be for the current host * @param p * the membership listening port * @param n * gemfire properties connection name * @param u * unique string used make the member more unique * @throws UnknownHostException if the given hostname cannot be resolved */ public InternalDistributedMember(String i, int p, String n, String u) throws UnknownHostException { ipAddr = MemberFactory.newNetMember(i, p); defaultToCurrentHost(); GFJGBasicAdapter.insertDefaultGemFireAttributes(((JGroupMember)ipAddr).getAddress()); this.name = n; this.uniqueTag = u; } /** * Create a InternalDistributedMember referring to the current host (as defined by the given * address).

* * * [bruce]THIS METHOD IS FOR TESTING ONLY. DO NOT USE IT TO CREATE IDs FOR * USE IN THE PRODUCT. IT DOES NOT PROPERLY INITIALIZE ATTRIBUTES NEEDED * FOR P2P FUNCTIONALITY. * * * * @param i * the hostname, must be for the current host * @param p * the membership listening port */ public InternalDistributedMember(InetAddress i, int p) { ipAddr = MemberFactory.newNetMember(i, p); defaultToCurrentHost(); } /** * Create a InternalDistributedMember as defined by the given address. *

* * * [bruce]THIS METHOD IS FOR TESTING ONLY. DO NOT USE IT TO CREATE IDs FOR * USE IN THE PRODUCT. IT DOES NOT PROPERLY INITIALIZE ATTRIBUTES NEEDED * FOR P2P FUNCTIONALITY. * * * @param addr * address of the server * @param p * the listening port of the server * @param isCurrentHost * true if the given host refers to the current host (bridge and * gateway use false to create a temporary id for the OTHER side of a * connection) */ public InternalDistributedMember(InetAddress addr, int p, boolean isCurrentHost) { ipAddr = MemberFactory.newNetMember(addr, p); if (isCurrentHost) { defaultToCurrentHost(); } } /** * Return the underlying host address * * @return the underlying host address */ public final InetAddress getIpAddress() { return ipAddr.getIpAddress(); } public NetMember getNetMember() { return ipAddr; } /** * Return the underlying port (membership port) * @return the underlying membership port */ public final int getPort() { return ipAddr.getPort(); } /** * Returns the port on which the direct channel runs */ public int getDirectChannelPort() { assert !this.isPartial; return dcPort; } /** * [GemStone] Returns the kind of VM that hosts the distribution manager with * this address. * * @see com.gemstone.gemfire.distributed.internal.DistributionManager#getDistributionManagerType * @see com.gemstone.gemfire.distributed.internal.DistributionManager#NORMAL_DM_TYPE */ public int getVmKind() { return vmKind; } /** * Returns the membership view ID that this member was born in. For * backward compatibility reasons this is limited to 16 bits. */ public int getVmViewId() { return this.vmViewId; } /** * Returns an unmodifiable Set of this member's Roles. */ public Set getRoles() { Set tmpRolesSet = this.rolesSet; if (tmpRolesSet != null) { return tmpRolesSet; } assert !this.isPartial; synchronized (this.rolesLock) { tmpRolesSet = this.rolesSet; if (tmpRolesSet == null) { final String[] tmpRoles = this.groups; // convert array of string role names to array of Roles... if (tmpRoles.length == 0) { tmpRolesSet = Collections.emptySet(); } else { tmpRolesSet = new HashSet(tmpRoles.length); for (int i = 0; i < tmpRoles.length; i++) { tmpRolesSet.add(InternalRole.getRole(tmpRoles[i])); } tmpRolesSet = Collections.unmodifiableSet(tmpRolesSet); } this.rolesSet = tmpRolesSet; } } Assert.assertTrue(tmpRolesSet != null); return tmpRolesSet; } public List getGroups() { return Collections.unmodifiableList(Arrays.asList(this.groups)); } public void setGroups(String[] newGroups) { assert !this.isPartial; assert newGroups != null; synchronized (this.rolesLock) { this.groups = newGroups; synchPayload(); this.rolesSet = null; this.cachedToString = null; } } private void synchPayload() { ipAddr.setAttributes(new MemberAttributes(dcPort, vmPid, vmKind, vmViewId, name, groups, durableClientAttributes)); } public void setVmKind(int p) { vmKind = p; synchPayload(); cachedToString = null; essentialData = null; } public void setVmViewId(int p) { this.vmViewId = p; synchPayload(); cachedToString = null; essentialData = null; } /** * [GemStone] Returns the process id of the VM that hosts the distribution * manager with this address. * * @since 4.0 */ public int getVmPid() { return vmPid; } /** * [GemStone] Sets the process id of the VM that hosts the distribution * manager with this address. * * @since 4.0 */ public void setVmPid(int p) { this.vmPid = p; synchPayload(); cachedToString = null; } /** * Returns the name of this member's distributed system connection or null * if no name was specified. * @see com.gemstone.gemfire.distributed.DistributedSystem#getName */ public String getName() { String result = this.name; if (result == null) { result = ""; } return result; } /** * Returns this member's unique tag (such as randomly generated bytes) or * null if no unique tag was created. */ public String getUniqueTag() { return this.uniqueTag; } /** * Returns this client member's durable attributes or null if no durable * attributes were created. */ public DurableClientAttributes getDurableClientAttributes() { assert !this.isPartial; return this.durableClientAttributes; } /** * implements the java.lang.Comparable interface * * @see java.lang.Comparable * @param o - * the Object to be compared * @return a negative integer, zero, or a positive integer as this object is * less than, equal to, or greater than the specified object. * @exception java.lang.ClassCastException - * if the specified object's type prevents it from being compared * to this Object. */ public int compareTo(DistributedMember o) { if (this == o) { return 0; } // obligatory type check if ((o == null) || !(o instanceof InternalDistributedMember)) throw new ClassCastException(LocalizedStrings.InternalDistributedMember_INTERNALDISTRIBUTEDMEMBERCOMPARETO_COMPARISON_BETWEEN_DIFFERENT_CLASSES.toLocalizedString()); InternalDistributedMember other = (InternalDistributedMember)o; int myPort = getPort(); int otherPort = other.getPort(); if (myPort < otherPort) return -1; if (myPort > otherPort) return 1; InetAddress myAddr = getIpAddress(); InetAddress otherAddr = other.getIpAddress(); // Discard null cases if (myAddr == null && otherAddr == null) { if (myPort < otherPort) return -1; else if (myPort > otherPort) return 1; else return 0; } else if (myAddr == null) { return -1; } else if (otherAddr == null) return 1; byte[] myBytes = myAddr.getAddress(); byte[] otherBytes = otherAddr.getAddress(); if (myBytes != otherBytes) { for (int i = 0; i < myBytes.length; i++) { if (i >= otherBytes.length) return -1; // same as far as they go, but shorter... if (myBytes[i] < otherBytes[i]) return -1; if (myBytes[i] > otherBytes[i]) return 1; } if (myBytes.length > otherBytes.length) return 1; // same as far as they go, but longer... } // [bruce] names are no longer transmitted in writeEssentialData and // so cannot be used in comparing IDs // if (this.name == null && other.name == null) { // // do nothing // } else if (this.name == null) { // return -1; // } // else if (other.name == null) { // return 1; // } // else { // int i = this.name.compareTo(other.name); // if (i != 0) { // return i; // } // } if (this.uniqueTag == null && other.uniqueTag == null) { // not loners, so look at P2P view ID if (this.vmViewId < other.vmViewId) { return -1; } else if (this.vmViewId > other.vmViewId) { return 1; } // else they're the same, so continue } else if (this.uniqueTag == null) { return -1; } else if (other.uniqueTag == null) { return 1; } else { int i = this.uniqueTag.compareTo(other.uniqueTag); if (i != 0) { return i; } } // purposely avoid comparing roles // @todo Add durableClientAttributes to compare return 0; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } // GemStone fix for 29125 if ((obj == null) || !(obj instanceof InternalDistributedMember)) { return false; } return equals((InternalDistributedMember)obj); } public final boolean equals(InternalDistributedMember m) { if (this == m) { return true; } if (m == null) { return false; } if (getPort() != m.getPort()) { return false; } final InetAddress myAddr = getIpAddress(); final InetAddress otherAddr = m.getIpAddress(); // Discard null cases if (myAddr == null && otherAddr == null) { return true; } else if (myAddr == null || otherAddr == null) { return false; } if(!myAddr.equals(otherAddr)) { return false; } // [bruce] names are no longer transmitted in writeEssentialData and // so cannot be used in comparing IDs // if (this.name == null && other.name == null) { // // do nothing // } else if (this.name == null) { // return -1; // } // else if (other.name == null) { // return 1; // } // else { // int i = this.name.compareTo(other.name); // if (i != 0) { // return i; // } // } if (this.uniqueTag == null && m.uniqueTag == null) { // not loners, so look at P2P view ID if (this.vmViewId != m.vmViewId) { return false; } // else they're the same, so continue } else if (this.uniqueTag == null || m.uniqueTag == null) { return false; } else if (!this.uniqueTag.equals(m.uniqueTag) ){ return false; } // purposely avoid comparing roles // @todo Add durableClientAttributes to compare return true; } @Override public int hashCode() { int result = 0; result = result + ipAddr.getIpAddress().hashCode(); result = result + getPort(); return result; } private String shortName(String hostname) { if (hostname == null) return ""; int index = hostname.indexOf('.'); if (index > 0 && !Character.isDigit(hostname.charAt(0))) return hostname.substring(0, index); else return hostname; } /** the cached string description of this object */ private transient String cachedToString; @Override public String toString() { return toString(null); } public String toString(final String vmKindStr) { String result = cachedToString; if (result == null || vmKindStr != null) { String host; InetAddress add = getIpAddress(); if (add.isMulticastAddress()) host = add.getHostAddress(); else { // host = shortName(add.getHostName()); host = SocketCreator.resolve_dns? shortName(this.hostName) : this.hostName; } final StringBuilder sb = new StringBuilder(); sb.append(host); String myName = getName(); if (vmPid > 0 || vmKind != DistributionManager.NORMAL_DM_TYPE || vmKindStr != null || !"".equals(myName)) { sb.append("("); if (!"".equals(myName)) { sb.append(myName); if (vmPid > 0) { sb.append(':'); } } if (vmPid > 0) sb.append(Integer.toString(vmPid)); String vmStr = ""; switch (vmKind) { case DistributionManager.NORMAL_DM_TYPE: // vmStr = ":local"; // let this be silent break; case DistributionManager.LOCATOR_DM_TYPE: vmStr = ":locator"; break; case DistributionManager.ADMIN_ONLY_DM_TYPE: vmStr = ":admin"; break; case DistributionManager.LONER_DM_TYPE: vmStr = ":loner"; break; default: vmStr = ":"; break; } if (vmKindStr != null) { sb.append(vmKindStr); } else { sb.append(vmStr); } // for split-brain and security debugging we need to know if the // member has the "can't be coordinator" bit set // JGroupMember jgm = (JGroupMember)ipAddr; // if (!jgm.getAddress().canBeCoordinator()) { // sb.append("

"); // } sb.append(")"); } if (ipAddr.splitBrainEnabled()) { if (ipAddr.canBeCoordinator()) { sb.append(""); } } if (this.vmViewId >= 0) { sb.append(""); } sb.append(":"); sb.append(getPort()); // if (dcPort > 0 && vmKind != DistributionManager.LONER_DM_TYPE) { // sb.append("/"); // sb.append(Integer.toString(dcPort)); // } if (vmKind == DistributionManager.LONER_DM_TYPE) { // add some more info that was added in 4.2.1 for loner bridge clients // impact on non-bridge loners is ok if (this.uniqueTag != null && this.uniqueTag.length() != 0) { sb.append(":").append(this.uniqueTag); } if (this.name != null && this.name.length() != 0) { sb.append(":").append(this.name); } } // add version if not current if (this.version != Version.CURRENT.ordinal()) { sb.append("(version:").append(Version.toString(this.version)) .append(')'); } // leave out Roles on purpose result = sb.toString(); if (vmKindStr == null) { cachedToString = result; } } return result; } private void readVersion(int flags, DataInput in) throws IOException { if ((flags & VERSION_MASK) != 0) { this.version = Version.readOrdinal(in); // assume compatibility with CURRENT; if not then remote peer will // reject us eventually at JGroups or Connection handshake layer this.versionObj = Version.fromOrdinalOrCurrent(this.version); } } /** * For Externalizable * * @see Externalizable */ public void writeExternal(ObjectOutput out) throws IOException { Assert.assertTrue(vmKind > 0); // [sumedh] loner VMs will have port as zero if no GFE client is connected // e.g. with GFXD clients Assert.assertTrue(vmKind == DistributionManager.LONER_DM_TYPE || getPort() > 0); // do it the way we like byte[] address = getIpAddress().getAddress(); out.writeInt(address.length); // IPv6 compatible out.write(address); out.writeInt(getPort()); DataSerializer.writeString(this.hostName, out); int flags = 0; if (ipAddr.splitBrainEnabled()) flags |= SB_ENABLED_MASK; if (ipAddr.canBeCoordinator()) flags |= COORD_ENABLED_MASK; if (this.isPartial) flags |= PARTIAL_ID_MASK; // always write product version but enable reading from older versions // that do not have it flags |= VERSION_MASK; out.writeByte((byte)(flags & 0xff)); out.writeInt(dcPort); out.writeInt(vmPid); out.writeInt(vmKind); out.writeInt(vmViewId); DataSerializer.writeStringArray(this.groups, out); DataSerializer.writeString(this.name, out); DataSerializer.writeString(this.uniqueTag, out); DataSerializer.writeString(this.durableClientAttributes==null ? "" : this.durableClientAttributes.getId(), out); DataSerializer.writeInteger(Integer.valueOf(this.durableClientAttributes==null ? 300 : this.durableClientAttributes.getTimeout()), out); Version.writeOrdinal(out, this.version, true); } /** * For Externalizable * * @see Externalizable */ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // do it the way we like int len = in.readInt(); // IPv6 compatible byte addr[] = new byte[len]; in.readFully(addr); InetAddress inetAddr = InetAddress.getByAddress(addr); int port = in.readInt(); this.hostName = DataSerializer.readString(in); int flags = in.readUnsignedByte(); boolean sbEnabled = (flags & SB_ENABLED_MASK) != 0; boolean elCoord = (flags & COORD_ENABLED_MASK) != 0; this.isPartial = (flags & PARTIAL_ID_MASK) != 0; this.dcPort = in.readInt(); this.vmPid = in.readInt(); this.vmKind = in.readInt(); this.vmViewId = in.readInt(); this.groups = DataSerializer.readStringArray(in); this.name = DataSerializer.readString(in); this.uniqueTag = DataSerializer.readString(in); String durableId = DataSerializer.readString(in); int durableTimeout = DataSerializer.readInteger(in).intValue(); this.durableClientAttributes = new DurableClientAttributes(durableId, durableTimeout); readVersion(flags, in); ipAddr = MemberFactory.newNetMember(inetAddr, port, sbEnabled, elCoord, new MemberAttributes(dcPort, vmPid, vmKind, vmViewId, name, groups, durableClientAttributes)); ((JGroupMember)ipAddr).getAddress().setVersionOrdinal(this.version); Assert.assertTrue(this.vmKind > 0); // [sumedh] loner VMs will have port as zero if no GFE client is connected // e.g. with GFXD clients Assert.assertTrue(vmKind == DistributionManager.LONER_DM_TYPE || getPort() > 0); } public int getDSFID() { return DISTRIBUTED_MEMBER; } public void toData(DataOutput out) throws IOException { Assert.assertTrue(vmKind > 0); // [bruce] disabled to allow post-connect setting of the port for loner systems // Assert.assertTrue(getPort() > 0); // if (this.getPort() == 0) { // InternalDistributedSystem.getLoggerI18n().warning(LocalizedStrings.DEBUG, // "Serializing ID with zero port", new Exception("Stack trace")); // } // NOTE: If you change the serialized format of this class // then bump Connection.HANDSHAKE_VERSION since an // instance of this class is sent during Connection handshake. DataSerializer.writeInetAddress(getIpAddress(), out); out.writeInt(getPort()); DataSerializer.writeString(this.hostName, out); int flags = 0; if (ipAddr.splitBrainEnabled()) flags |= SB_ENABLED_MASK; if (ipAddr.canBeCoordinator()) flags |= COORD_ENABLED_MASK; if (this.isPartial) flags |= PARTIAL_ID_MASK; // always write product version but enable reading from older versions // that do not have it flags |= VERSION_MASK; out.writeByte((byte)(flags & 0xff)); out.writeInt(dcPort); out.writeInt(vmPid); out.writeByte(vmKind); DataSerializer.writeStringArray(this.groups, out); DataSerializer.writeString(this.name, out); if (this.vmKind == DistributionManager.LONER_DM_TYPE) { DataSerializer.writeString(this.uniqueTag, out); } else { // added in 6.5 for unique identifiers in P2P DataSerializer.writeString(String.valueOf(this.vmViewId), out); } DataSerializer.writeString(this.durableClientAttributes==null ? "" : this.durableClientAttributes.getId(), out); DataSerializer.writeInteger(Integer.valueOf(this.durableClientAttributes==null ? 300 : this.durableClientAttributes.getTimeout()), out); Version.writeOrdinal(out, this.version, true); } // public void toDataPre_GFE_7_1_0_0(DataOutput out) throws IOException { // Assert.assertTrue(vmKind > 0); // // [bruce] disabled to allow post-connect setting of the port for loner systems //// Assert.assertTrue(getPort() > 0); //// if (this.getPort() == 0) { //// InternalDistributedSystem.getLoggerI18n().warning(LocalizedStrings.DEBUG, //// "Serializing ID with zero port", new Exception("Stack trace")); //// } // // // NOTE: If you change the serialized format of this class // // then bump Connection.HANDSHAKE_VERSION since an // // instance of this class is sent during Connection handshake. // DataSerializer.writeInetAddress(getIpAddress(), out); // out.writeInt(getPort()); // // DataSerializer.writeString(this.hostName, out); // // int flags = 0; // if (ipAddr.splitBrainEnabled()) flags |= SB_ENABLED_MASK; // if (ipAddr.canBeCoordinator()) flags |= COORD_ENABLED_MASK; // if (this.isPartial) flags |= PARTIAL_ID_MASK; // out.writeByte((byte)(flags & 0xff)); // // out.writeInt(dcPort); // out.writeInt(vmPid); // out.writeByte(vmKind); // DataSerializer.writeStringArray(this.groups, out); // // DataSerializer.writeString(this.name, out); // if (this.vmKind == DistributionManager.LONER_DM_TYPE) { // DataSerializer.writeString(this.uniqueTag, out); // } else { // added in 6.5 for unique identifiers in P2P // DataSerializer.writeString(String.valueOf(this.vmViewId), out); // } // DataSerializer.writeString(this.durableClientAttributes==null ? "" : this.durableClientAttributes.getId(), out); // DataSerializer.writeInteger(Integer.valueOf(this.durableClientAttributes==null ? 300 : this.durableClientAttributes.getTimeout()), out); // // } public void fromData(DataInput in) throws IOException, ClassNotFoundException { // do it the way we like it. InetAddress inetAddr = DataSerializer.readInetAddress(in); int port = in.readInt(); this.hostName = DataSerializer.readString(in); this.hostName = SocketCreator.resolve_dns? SocketCreator.getCanonicalHostName(inetAddr, hostName) : inetAddr.getHostAddress(); int flags = in.readUnsignedByte(); boolean sbEnabled = (flags & SB_ENABLED_MASK) != 0; boolean elCoord = (flags & COORD_ENABLED_MASK) != 0; this.isPartial = (flags & PARTIAL_ID_MASK) != 0; this.dcPort = in.readInt(); this.vmPid = in.readInt(); this.vmKind = in.readUnsignedByte(); this.groups = DataSerializer.readStringArray(in); this.name = DataSerializer.readString(in); if (this.vmKind == DistributionManager.LONER_DM_TYPE) { this.uniqueTag = DataSerializer.readString(in); } else { String str = DataSerializer.readString(in); if (str != null) { // backward compatibility from earlier than 6.5 this.vmViewId = Integer.parseInt(str); } } String durableId = DataSerializer.readString(in); int durableTimeout = DataSerializer.readInteger(in).intValue(); this.durableClientAttributes = new DurableClientAttributes(durableId, durableTimeout); readVersion(flags, in); MemberAttributes attr = new MemberAttributes(this.dcPort, this.vmPid, this.vmKind, this.vmViewId, this.name, this.groups, this.durableClientAttributes); ipAddr = MemberFactory.newNetMember(inetAddr, port, sbEnabled, elCoord, attr); ((JGroupMember)ipAddr).getAddress().setVersionOrdinal(this.version); synchPayload(); Assert.assertTrue(this.vmKind > 0); // Assert.assertTrue(getPort() > 0); } // public void fromDataPre_GFE_7_1_0_0(DataInput in) throws IOException, ClassNotFoundException { // // do it the way we like it. // InetAddress inetAddr = DataSerializer.readInetAddress(in); // int port = in.readInt(); // // this.hostName = DataSerializer.readString(in); // this.hostName = SocketCreator.resolve_dns? SocketCreator.getCanonicalHostName(inetAddr, hostName) : inetAddr.getHostAddress(); // // int flags = in.readUnsignedByte(); // boolean sbEnabled = (flags & SB_ENABLED_MASK) != 0; // boolean elCoord = (flags & COORD_ENABLED_MASK) != 0; // this.isPartial = (flags & PARTIAL_ID_MASK) != 0; // // this.dcPort = in.readInt(); // this.vmPid = in.readInt(); // this.vmKind = in.readUnsignedByte(); // this.groups = DataSerializer.readStringArray(in); // // this.name = DataSerializer.readString(in); // if (this.vmKind == DistributionManager.LONER_DM_TYPE) { // this.uniqueTag = DataSerializer.readString(in); // } else { // String str = DataSerializer.readString(in); // if (str != null) { // backward compatibility from earlier than 6.5 // this.vmViewId = Integer.parseInt(str); // } // } // // String durableId = DataSerializer.readString(in); // int durableTimeout = DataSerializer.readInteger(in).intValue(); // this.durableClientAttributes = new DurableClientAttributes(durableId, durableTimeout); // // MemberAttributes attr = new MemberAttributes(this.dcPort, this.vmPid, // this.vmKind, this.vmViewId, this.name, this.groups, this.durableClientAttributes); // ipAddr = MemberFactory.newNetMember(inetAddr, port, sbEnabled, elCoord, attr); // // synchPayload(); // // Assert.assertTrue(this.vmKind > 0); // } /** this writes just the parts of the ID that are needed for comparisons and communications */ public static InternalDistributedMember readEssentialData(DataInput in) throws IOException, ClassNotFoundException { final InternalDistributedMember mbr = new InternalDistributedMember(); mbr._readEssentialData(in); return mbr; } private void _readEssentialData(DataInput in) throws IOException, ClassNotFoundException { this.isPartial = true; InetAddress inetAddr = DataSerializer.readInetAddress(in); int port = in.readInt(); this.hostName = SocketCreator.resolve_dns? SocketCreator.getHostName(inetAddr) : inetAddr.getHostAddress(); int flags = in.readUnsignedByte(); boolean sbEnabled = (flags & SB_ENABLED_MASK) != 0; boolean elCoord = (flags & COORD_ENABLED_MASK) != 0; this.vmKind = in.readUnsignedByte(); if (this.vmKind == DistributionManager.LONER_DM_TYPE) { this.uniqueTag = DataSerializer.readString(in); } else { String str = DataSerializer.readString(in); if (str != null) { // backward compatibility from earlier than 6.5 this.vmViewId = Integer.parseInt(str); } } /*this.name =*/ DataSerializer.readString(in); MemberAttributes attr = new MemberAttributes(this.dcPort, this.vmPid, this.vmKind, this.vmViewId, this.name, this.groups, this.durableClientAttributes); ipAddr = MemberFactory.newNetMember(inetAddr, port, sbEnabled, elCoord, attr); synchPayload(); } /** * NOTE: the data the method serializes is read by old clients in CacheClientUpdater. * So if you add data here add it to the end so the old client can still read it. * See bug 45160. */ @Override public void writeEssentialData(DataOutput dout) throws IOException { byte[] ed = this.essentialData; Version targetVersion = InternalDataSerializer.getVersionForDataStream(dout); boolean isOldServer = (targetVersion.compareTo(Version.GFE_75) < 0); if (ed == null || isOldServer) { HeapDataOutputStream out = new HeapDataOutputStream(20, Version.CURRENT); Assert.assertTrue(vmKind > 0); DataSerializer.writeInetAddress(getIpAddress(), out); out.writeInt(getPort()); int flags = 0; if (ipAddr.splitBrainEnabled()) flags |= SB_ENABLED_MASK; if (ipAddr.canBeCoordinator()) flags |= COORD_ENABLED_MASK; flags |= PARTIAL_ID_MASK; out.writeByte((byte)(flags & 0xff)); // out.writeInt(dcPort); out.writeByte(vmKind); if (this.vmKind == DistributionManager.LONER_DM_TYPE) { DataSerializer.writeString(this.uniqueTag, out); } else { // added in 6.5 for unique identifiers in P2P DataSerializer.writeString(String.valueOf(this.vmViewId), out); } // write name last to fix bug 45160 if (isOldServer) { DataSerializer.writeString(this.name, out); } else { // [bruce] we no longer write names with essential id info and // they are no longer used in ID comparison DataSerializer.writeString("", out); } ed = out.toByteArray(); if (!isOldServer) { // cache the current form for future use this.essentialData = ed; } } dout.write(ed); } /** * [GemStone] Set the direct channel port */ public void setDirectChannelPort(int p) { dcPort = p; synchPayload(); } /** * Set the membership port. This is done in loner systems using * client/server connection information to help form a unique ID */ public void setPort(int p) { assert this.vmKind == DistributionManager.LONER_DM_TYPE; this.ipAddr.setPort(p); synchPayload(); cachedToString = null; essentialData = null; } /** drop the cached toString rep of this ID */ public void dropCachedString() { this.cachedToString = null; } public String getHost() { return this.ipAddr.getIpAddress().getCanonicalHostName(); } public int getProcessId() { return this.vmPid; } public String getId() { return toString(); } /*if (this.ipAddr == null) { return ""; } else { StringBuffer sb = new StringBuffer(); InetAddress addr = this.ipAddr.getIpAddress(); if(addr.isMulticastAddress()) { sb.append(addr.getHostAddress()); } else { appendShortName(addr.getHostName(), sb); } if (this.vmPid != 0) { sb.append("("); sb.append(this.vmPid); sb.append(")"); } sb.append(":"); sb.append(this.ipAddr.getPort()); return sb.toString(); } } // Helper method for getId()... copied from IpAddress. private void appendShortName(String hostname, StringBuffer sb) { if (hostname == null) return; int index = hostname.indexOf('.'); if(index > 0 && !Character.isDigit(hostname.charAt(0))) { sb.append(hostname.substring(0, index)); } else { sb.append(hostname); } }*/ public final short getVersionOrdinal() { return this.version; } public final Version getVersionObject() { return this.versionObj; } @Override public Version[] getSerializationVersions() { return dsfidVersions; } @Override public int getSizeInBytes() { int size = 0; // ipaddr: 1 byte length + 4 bytes (IPv4) or 16 bytes (IPv6) if (ipAddr.getIpAddress() instanceof Inet4Address){ size += 5; } else { size += 17; } // port: 4 bytes // flags: 1 byte //vmKind: 1 byte size += 6; // viewID: String(1+1+numchars) size += (2+ String.valueOf(this.vmViewId).length()); // empty name: String(1+1) size += 2; return size; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy