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

com.sleepycat.je.rep.impl.RepNodeImpl Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.rep.impl;

import java.io.Serializable;
import java.net.InetSocketAddress;

import com.sleepycat.je.EnvironmentFailureException;
import com.sleepycat.je.JEVersion;
import com.sleepycat.je.rep.NodeType;
import com.sleepycat.je.rep.ReplicationConfig;
import com.sleepycat.je.rep.ReplicationNode;
import com.sleepycat.je.rep.impl.node.cbvlsn.CleanerBarrierState;
import com.sleepycat.je.rep.impl.node.NameIdPair;
import com.sleepycat.je.rep.stream.Protocol;
import com.sleepycat.je.rep.utilint.HostPortPair;
import com.sleepycat.je.utilint.VLSN;

/**
 * Describes a node that is a member of the replication group.
 */
public class RepNodeImpl implements ReplicationNode, Serializable {

    private static final long serialVersionUID = 1L;

    /* Identifies the node both by external name and internal node ID. */
    private final NameIdPair nameIdPair;

    /* The node type, electable, monitor, etc. */
    private final NodeType type;

    /*
     * True if the node was acknowledged by a quorum and its entry is therefore
     * considered durable.  SECONDARY and EXTERNAL nodes are always considered
     * acknowledged.
     */
    private boolean quorumAck;

    /*
     * True if the node has been removed and is no longer an active part of the
     * group
     */
    private boolean isRemoved;

    /* The hostname used for communications with the node. */
    private String hostName;

    /* The port used by a node. */
    private int port;

    /*
     * The CBVLSN Barrier state associated with the node. Is unused if the
     * GlobalCBVLSN is defunct. See GlobalCBVLSN.
     */
    private CleanerBarrierState barrierState;

    /*
     * This version is used in conjunction with the group level change
     * version to identify the incremental changes made to individual
     * changes made to a group.
     */
    private int changeVersion = NULL_CHANGE;

    private static final int NULL_CHANGE = -1;

    /**
     * The JE version most recently noted running on this node, or null if not
     * known.
     */
    private volatile JEVersion jeVersion;

    /**
     * @hidden
     *
     * Constructor used to de-serialize a Node. All other convenience
     * constructors funnel through this one so that argument checks can
     * be systematically enforced.
     */
    public RepNodeImpl(final NameIdPair nameIdPair,
                       final NodeType type,
                       final boolean quorumAck,
                       final boolean isRemoved,
                       final String hostName,
                       final int port,
                       final CleanerBarrierState barrierState,
                       final int changeVersion,
                       final JEVersion jeVersion) {

        if (nameIdPair.getName().equals(RepGroupDB.GROUP_KEY)) {
            throw EnvironmentFailureException.unexpectedState
            ("Member node ID is the reserved key value: " + nameIdPair);
        }

        if (hostName == null) {
            throw EnvironmentFailureException.unexpectedState
            ("The hostname argument must not be null");
        }

        if (type == null) {
            throw EnvironmentFailureException.unexpectedState
            ("The nodeType argument must not be null");
        }

        this.nameIdPair = nameIdPair;
        this.type = type;
        this.quorumAck = quorumAck || type.isSecondary() || type.isExternal();
        this.isRemoved = isRemoved;
        this.hostName = hostName;
        this.port = port;
        this.barrierState = barrierState;
        this.changeVersion = changeVersion;
        this.jeVersion = jeVersion;
    }

    /**
     * @hidden
     *
     * Convenience constructor for the above.
     */
    public RepNodeImpl(final NameIdPair nameIdPair,
                       final NodeType type,
                       final boolean quorumAck,
                       final boolean isRemoved,
                       final String hostName,
                       final int port,
                       final int changeVersion,
                       final JEVersion jeVersion) {
        this(nameIdPair, type, quorumAck, isRemoved, hostName, port,
             new CleanerBarrierState(VLSN.NULL_VLSN, System.currentTimeMillis()),
             changeVersion, jeVersion);
    }

    /**
     * @hidden
     * Convenience constructor for transient nodes
     */
    public RepNodeImpl(final NameIdPair nameIdPair,
                       final NodeType type,
                       final String hostName,
                       final int port,
                       final JEVersion jeVersion) {
        this(nameIdPair, type, false, false, hostName, port, NULL_CHANGE,
             jeVersion);
    }

    /**
     * @hidden
     * Convenience constructor for transient nodes during unit tests.
     */
    public RepNodeImpl(final ReplicationConfig repConfig) {
        this(new NameIdPair(repConfig.getNodeName(), NameIdPair.NULL_NODE_ID),
             repConfig.getNodeType(),
             repConfig.getNodeHostname(),
             repConfig.getNodePort(),
             JEVersion.CURRENT_VERSION);
    }

    /**
     * @hidden
     *
     * Convenience constructor for the above.
     */
    public RepNodeImpl(final String nodeName,
                       final String hostName,
                       final int port,
                       final JEVersion jeVersion) {
        this(new NameIdPair(nodeName, NameIdPair.NULL.getId()),
             NodeType.ELECTABLE, hostName, port, jeVersion);
    }

    /**
     * @hidden
     *
     * Convenience constructor for the above.
     */
    public RepNodeImpl(Protocol.NodeGroupInfo mi) {
        this(mi.getNameIdPair(),
             mi.getNodeType(),
             mi.getHostName(),
             mi.port(),
             mi.getJEVersion());
    }

    /* (non-Javadoc)
     * @see com.sleepycat.je.rep.ReplicationNode#getSocketAddress()
     */
    @Override
    public InetSocketAddress getSocketAddress() {
        return new InetSocketAddress(hostName, port);
    }

    /**
     * Returns whether the node was acknowledged by a quorum and its entry is
     * therefore considered durable.  Secondary nodes are always considered
     * acknowledged.
     */
    public boolean isQuorumAck() {
        return quorumAck;
    }

    public boolean isRemoved() {
        assert !(isRemoved && type.hasTransientId())
            : "Nodes with transient IDs are never marked removed";
        return isRemoved;
    }

    public void setChangeVersion(int changeVersion) {
        this.changeVersion = changeVersion;
    }

    public int getChangeVersion() {
        return changeVersion;
    }

    public NameIdPair getNameIdPair() {
        return nameIdPair;
    }

    /* (non-Javadoc)
     * @see com.sleepycat.je.rep.ReplicationNode#getName()
     */
    @Override
    public String getName() {
        return nameIdPair.getName();
    }

    public int getNodeId() {
        return nameIdPair.getId();
    }

    /* (non-Javadoc)
     * @see com.sleepycat.je.rep.ReplicationNode#getNodeType()
     */
    @Override
    public NodeType getType() {
        return type;
    }

    /* (non-Javadoc)
     * @see com.sleepycat.je.rep.ReplicationNode#getHostName()
     */
    @Override
    public String getHostName() {
        return hostName;
    }

    public void setHostName(String hostName) {
        this.hostName = hostName;
    }

    /* (non-Javadoc)
     * @see com.sleepycat.je.rep.ReplicationNode#getPort()
     */
    @Override
    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getHostPortPair() {
        return HostPortPair.getString(hostName, port);
    }

    public CleanerBarrierState getBarrierState() {
        return barrierState;
    }

    public CleanerBarrierState setBarrierState(CleanerBarrierState barrierState) {
        return this.barrierState = barrierState;
    }

    public void setQuorumAck(boolean quorumAck) {
        this.quorumAck = quorumAck;
    }

    public void setRemoved(boolean isRemoved) {
        this.isRemoved = isRemoved;
    }

    /**
     * Returns the JE Version most recently noted running on this node, or
     * {@code null} if not known.
     */
    public JEVersion getJEVersion() {
        return jeVersion;
    }

    /**
     * Updates the JE version most recently known running on this node to match
     * the version specified.  Does nothing if the argument is null.
     *
     * @param otherJEVersion the version or {@code null}
     */
    public void updateJEVersion(final JEVersion otherJEVersion) {
        if (otherJEVersion != null) {
            jeVersion = otherJEVersion;
        }
    }

    @Override
    public String toString() {

        String acked = " (is member)";

        if (!quorumAck) {
            acked = " (not yet a durable member)";
        }

        if (isRemoved) {
            acked = " (is removed)";
        }

        String info =
            String.format("Node:%s %s:%d%s%s changeVersion:%d %s%s\n",
                          getName(), getHostName(), getPort(),
                          acked,
                          (!type.isElectable() ? " " + type : ""),
                          getChangeVersion(),
                          barrierState,
                          ((jeVersion != null) ?
                           " jeVersion:" + jeVersion :
                           ""));
        return info;

    }

    /**
     * Checks if the argument represents the same node, ignoring fields that
     * might legitimately vary over time.  Like the equals method, considers
     * all fields, except ignores the quorumAck field (which may change
     * temporarily), the nodeId (since it may not have been resolved as yet),
     * and the isRemoved, barrierState, changeVersion, and jeVersion fields
     * (which can change over time).
     *
     * @param mi the other object in the comparison
     *
     * @return true if the two are equivalent
     */
    public boolean equivalent(RepNodeImpl mi) {
        if (this == mi) {
            return true;
        }

        if (mi == null) {
            return false;
        }

        if (port != mi.port) {
            return false;
        }

        if (hostName == null) {
            if (mi.hostName != null) {
                return false;
            }
        } else if (!hostName.equals(mi.hostName)) {
            return false;
        }

        /* Ignore the id. */
        if (!nameIdPair.getName().equals(mi.nameIdPair.getName())) {
            return false;
        }

        if (getType() != mi.getType()) {
            return false;
        }

        /*
         * Ignore quorumAck, isRemoved, barrierState, changeVersion, and
         * jeVersion
         */

        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((hostName == null) ? 0 : hostName.hashCode());
        result = prime * result + nameIdPair.hashCode();
        result = prime * result + port;
        result = prime * result + (isQuorumAck() ? 1231 : 1237);
        result = prime * result +
            (jeVersion == null ? 0 : jeVersion.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof RepNodeImpl)) {
            return false;
        }
        final RepNodeImpl other = (RepNodeImpl) obj;
        if (hostName == null) {
            if (other.hostName != null) {
                return false;
            }
        } else if (!hostName.equals(other.hostName)) {
            return false;
        }
        if (!nameIdPair.equals(other.nameIdPair)) {
            return false;
        }
        if (getType() != other.getType()) {
            return false;
        }
        if (port != other.port) {
            return false;
        }
        if (isQuorumAck() != other.isQuorumAck()) {
            return false;
        }
        if (jeVersion == null) {
            if (other.jeVersion != null) {
                return false;
            }
        } else if (!jeVersion.equals(other.getJEVersion())) {
            return false;
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy