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

com.sleepycat.je.rep.impl.node.ElectionQuorum 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.node;

import java.util.logging.Logger;

import com.sleepycat.je.rep.NodeType;
import com.sleepycat.je.rep.QuorumPolicy;
import com.sleepycat.je.rep.arbitration.Arbiter;
import com.sleepycat.je.rep.impl.RepImpl;
import com.sleepycat.je.rep.impl.RepParams;
import com.sleepycat.je.rep.stream.MasterStatus;
import com.sleepycat.je.utilint.LoggerUtils;

/**
 * ElectionQuorum centralizes decision making about what constitutes a
 * successful election quorum and the definition of an authoritative master.
 */
public class ElectionQuorum {

    private final RepImpl repImpl;
    private final Logger logger;

    /*
     * If non-zero use this value to override the normal group size
     * calculations.
     */
    private volatile int electableGroupSizeOverride;

    public ElectionQuorum(RepImpl repImpl) {

        this.repImpl = repImpl;
        logger = LoggerUtils.getLogger(getClass());

        electableGroupSizeOverride = repImpl.getConfigManager().
            getInt(RepParams.ELECTABLE_GROUP_SIZE_OVERRIDE);
        if (electableGroupSizeOverride > 0) {
            LoggerUtils.warning(logger, repImpl,
                                "Electable group size override set to:" +
                                electableGroupSizeOverride);
        }
    }

    /** For unit testing */
    public ElectionQuorum() {
        repImpl = null;
        logger = null;
    }

    /*
     * Sets the override value for the Electable Group size.
     */
    public void setElectableGroupSizeOverride(int override) {
        if (electableGroupSizeOverride != override) {
            LoggerUtils.warning(logger, repImpl,
                                "Electable group size override changed to:" +
                                override);
        }
        this.electableGroupSizeOverride = override;
    }

    public int getElectableGroupSizeOverride() {
        return electableGroupSizeOverride;
    }

    /**
     * Predicate to determine whether we have a quorum based upon the quorum
     * policy.
     */
    public boolean haveQuorum(QuorumPolicy quorumPolicy, int votes) {
        return votes >= getElectionQuorumSize(quorumPolicy);
    }

    /**
     * Returns a definitive answer to whether this node is currently the master
     * by checking both its status as a master and that a sufficient number
     * of nodes agree that it's the master based on the number of feeder
     * connections to it. Currently, the sufficient number is just a simple
     * majority. Such an authoritative answer is needed in a network partition
     * situation to detect a master that may be isolated on the minority side
     * of a network partition.
     *
     * @return true if the node is definitely the master. False if it's not or
     * we cannot be sure.
     */
    boolean isAuthoritativeMaster(MasterStatus masterStatus,
                                  FeederManager feederManager) {
        if (!masterStatus.isGroupMaster()) {
            return false;
        }

        return (feederManager.activeReplicaCount() + 1) >=
            getElectionQuorumSize(QuorumPolicy.SIMPLE_MAJORITY);
    }

    /**
     * Return the number of nodes that are required to achieve consensus on the
     * election. Over time, this may evolve to be a more detailed description
     * than simply the size of the quorum. Instead, it may return the set of
     * possible voters.
     *
     * Special situations, like an active designated primary or an election
     * group override will change the default quorum size.
     *
     * @param quorumPolicy
     * @return the number of nodes required for a quorum
     */
    private int getElectionQuorumSize(QuorumPolicy quorumPolicy) {
        if (electableGroupSizeOverride > 0) {
            return quorumPolicy.quorumSize(electableGroupSizeOverride);
        }

        /*
         * If arbitration is active, check whether arbitration determines the
         * election group size.
         */
        RepNode repNode = repImpl.getRepNode();
        Arbiter arbiter = repNode.getArbiter();
        if (arbiter.isApplicable(quorumPolicy)) {
            return arbiter.getElectionQuorumSize(quorumPolicy);
        }

        return quorumPolicy.quorumSize
            (repNode.getGroup().getElectableGroupSize());
    }

    /**
     * Return whether nodes of the specified type should participate in
     * elections.
     *
     * @param nodeType the node type
     * @return whether nodes of that type should participate in elections
     */
    public boolean nodeTypeParticipates(final NodeType nodeType) {

        /* Only electable nodes participate in elections */
        return nodeType.isElectable();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy