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

com.sleepycat.je.rep.stream.MasterStatus 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.stream;

import java.net.InetSocketAddress;

import com.sleepycat.je.rep.impl.node.NameIdPair;

/**
 * Class used by a node to track changes in Master Status. It's updated by
 * the Listener. It represents the abstract notion that the notion of the
 * current Replica Group is definitive and is always in advance of the notion
 * of a master at each node. A node is typically playing catch up as it tries
 * to bring its view in line with that of the group.
 */
public class MasterStatus implements Cloneable {

    /* This node's identity */
    private final NameIdPair nameIdPair;

    /* The current master resulting from election notifications */
    private String groupMasterHostName = null;
    private int groupMasterPort = 0;
    /* The node ID used to identify the master. */
    private NameIdPair groupMasterNameId = NameIdPair.NULL;

    /*
     * The Master as implemented by the Node. It can lag the groupMaster
     * as the node tries to catch up.
     */
    private String nodeMasterHostName = null;
    private int nodeMasterPort = 0;
    private NameIdPair nodeMasterNameId = NameIdPair.NULL;

    public MasterStatus(NameIdPair nameIdPair) {
        this.nameIdPair = nameIdPair;
    }

    /**
     * Returns a read-only snapshot of the object.
     */
    @Override
    public synchronized Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            assert(false);
        }
        return null;
    }

    /**
     * Returns true if it's the master from the Group's perspective
     */
    public synchronized boolean isGroupMaster() {
        final int id = nameIdPair.getId();
        return (id != NameIdPair.NULL_NODE_ID) &&
            (id == groupMasterNameId.getId());
    }

    /**
     * Returns true if it's the master from the node's localized perspective
     */
    public synchronized boolean isNodeMaster() {
        final int id = nameIdPair.getId();
        return (id != NameIdPair.NULL_NODE_ID) &&
            (id == nodeMasterNameId.getId());
    }

    public synchronized void setGroupMaster(String hostname,
                                            int port,
                                            NameIdPair newGroupMasterNameId) {
        groupMasterHostName = hostname;
        groupMasterPort = port;
        groupMasterNameId = newGroupMasterNameId;
    }

    /**
     * Predicate to determine whether the group and node have a consistent
     * notion of the Master.
     *
     * @return false if the node does not know of a Master, or the group Master
     * is different from the node's notion the master.
     */

    public synchronized boolean inSync() {
        return !nodeMasterNameId.hasNullId() &&
               (groupMasterNameId.getId() == nodeMasterNameId.getId());
    }

    public synchronized void unSync() {
        nodeMasterHostName = null;
        nodeMasterPort = 0;
        nodeMasterNameId = NameIdPair.NULL;
    }

    /**
     * An assertion form of the above. By combining the check and exception
     * generation in an atomic operation, it provides for an accurate exception
     * message.
     *
     * @throws MasterSyncException
     */
    public synchronized void assertSync()
        throws MasterSyncException {

        if (!inSync()) {
            throw new MasterSyncException();
        }
    }

    /**
     * Syncs to the group master
     */
    public synchronized void sync() {
        nodeMasterHostName = groupMasterHostName;
        nodeMasterPort = groupMasterPort;
        nodeMasterNameId = groupMasterNameId;
    }

    /**
     * Returns the Node's current idea of the Master. It may be "out of sync"
     * with the Group's notion of the Master
     */
    public synchronized InetSocketAddress getNodeMaster() {
        if (nodeMasterHostName == null) {
            return null;
        }
        return new InetSocketAddress(nodeMasterHostName, nodeMasterPort);
    }

    public synchronized NameIdPair getNodeMasterNameId() {
        return nodeMasterNameId;
    }

    /**
     * Returns a socket that can be used to communicate with the group master.
     * It can return null, if there is no current group master, that is,
     * groupMasterNameId is NULL.
     */
    public synchronized InetSocketAddress getGroupMaster() {
        if (groupMasterHostName == null) {
             return null;
        }
        return new InetSocketAddress(groupMasterHostName, groupMasterPort);
    }

    public synchronized NameIdPair getGroupMasterNameId() {
        return groupMasterNameId;
    }

    @SuppressWarnings("serial")
    public class MasterSyncException extends Exception {
        private final NameIdPair savedGroupMasterId;
        private final NameIdPair savedNodeMasterId;

        MasterSyncException () {
            savedGroupMasterId = MasterStatus.this.getGroupMasterNameId();
            savedNodeMasterId = MasterStatus.this.getNodeMasterNameId();
        }

        @Override
        public String getMessage() {
            return "Master change. Node master id: " + savedNodeMasterId +
            " Group master id: " + savedGroupMasterId;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy