Package com.sleepycat.je.rep.util

Source Code of com.sleepycat.je.rep.util.ReplicationGroupAdmin

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2010 Oracle.  All rights reserved.
*
*/
package com.sleepycat.je.rep.util;

import java.net.InetSocketAddress;
import java.util.Set;
import java.util.logging.Formatter;
import java.util.logging.Logger;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.EnvironmentFailureException;
import com.sleepycat.je.rep.MasterStateException;
import com.sleepycat.je.rep.MemberNotFoundException;
import com.sleepycat.je.rep.NodeType;
import com.sleepycat.je.rep.ReplicationGroup;
import com.sleepycat.je.rep.ReplicationNode;
import com.sleepycat.je.rep.UnknownMasterException;
import com.sleepycat.je.rep.elections.Learner;
import com.sleepycat.je.rep.elections.MasterValue;
import com.sleepycat.je.rep.elections.Protocol;
import com.sleepycat.je.rep.elections.TimebasedProposalGenerator;
import com.sleepycat.je.rep.impl.GroupService;
import com.sleepycat.je.rep.impl.RepGroupProtocol;
import com.sleepycat.je.rep.impl.RepNodeImpl;
import com.sleepycat.je.rep.impl.RepGroupProtocol.EnsureOK;
import com.sleepycat.je.rep.impl.RepGroupProtocol.Fail;
import com.sleepycat.je.rep.impl.RepGroupProtocol.GroupResponse;
import com.sleepycat.je.rep.impl.TextProtocol.MessageExchange;
import com.sleepycat.je.rep.impl.TextProtocol.OK;
import com.sleepycat.je.rep.impl.TextProtocol.ProtocolError;
import com.sleepycat.je.rep.impl.TextProtocol.ResponseMessage;
import com.sleepycat.je.rep.impl.node.NameIdPair;
import com.sleepycat.je.rep.utilint.ReplicationFormatter;
import com.sleepycat.je.utilint.LoggerUtils;

/**
* Administrative APIs for use by applications which do not have direct access
* to a replicated environment. The class supplies methods that can be
* used to list group members, remove members, and find the current master.
* The information is found by querying nodes in the group. Because of that,
* ReplicationGroupAdmin can only obtain information when there is at least
* one node alive in the replication group.
*/
public class ReplicationGroupAdmin {

    private final String groupName;
    private final Set<InetSocketAddress> helperSockets;
    private final Protocol electionsProtocol;
    private final RepGroupProtocol groupProtocol;
    private final Logger logger;
    private final Formatter formatter;

    /**
     * Constructs a group admin object.
     *
     * @param groupName the name of the group to be administered
     * @param helperSockets the sockets on which it can contact helper nodes
     * in the replication group to carry out admin services.
     */
    public ReplicationGroupAdmin(String groupName,
                                 Set<InetSocketAddress> helperSockets) {
        this.groupName = groupName;
        this.helperSockets = helperSockets;

        electionsProtocol =
            new Protocol(TimebasedProposalGenerator.getParser(),
                         MasterValue.getParser(),
                         groupName,
                         NameIdPair.NOCHECK,
                         null /* repImpl */);
        groupProtocol =
            new RepGroupProtocol(groupName, NameIdPair.NOCHECK, null);
        logger = LoggerUtils.getLoggerFixedPrefix
            (getClass(), NameIdPair.NOCHECK.toString());
        formatter = new ReplicationFormatter(NameIdPair.NOCHECK);
    }

    /**
     * Returns the helper sockets being used to contact a replication group
     * member, in order to query for the information.
     *
     * @return the set of helper sockets.
     */
    public Set<InetSocketAddress> getHelperSockets() {
        return helperSockets;
    }

    /**
     * Returns the name of the replication group.
     *
     * @return the group name.
     */
    public String getGroupName() {
        return groupName;
    }

    /**
     * Returns the socket address associated with the node that's currently
     * the master.
     *
     * @return the socket address associated with the master
     *
     * @throws UnknownMasterException if the master was not found
     *
     * @throws EnvironmentFailureException if an unexpected, internal or
     * environment-wide failure occurs.
     */
    private InetSocketAddress getMasterSocket()
        throws UnknownMasterException,
               EnvironmentFailureException {

        MasterValue masterValue = Learner.findMaster(electionsProtocol,
                                                     helperSockets,
                                                     logger,
                                                     null,
                                                     formatter);
        return new InetSocketAddress(masterValue.getHostName(),
                                     masterValue.getPort());
    }

    /**
     * Returns the node name associated with the master
     *
     * @return the master node id
     *
     * @throws UnknownMasterException if the master was not found
     *
     * @throws EnvironmentFailureException if an unexpected, internal or
     * environment-wide failure occurs.
     */
    public String getMasterNodeName()
        throws UnknownMasterException,
               EnvironmentFailureException {
        MasterValue masterValue = Learner.findMaster(electionsProtocol,
                                                     helperSockets,
                                                     logger,
                                                     null,
                                                     formatter);
        return masterValue.getNodeName();
    }

    /**
     * @hidden
     * Internal implementation class.
     *
     * Ensures that this monitor node is a member of the replication group,
     * adding it to the group if it isn't already.
     *
     * @param monitor the monitor node
     *
     * @return the master node that was contacted to ensure the monitor
     *
     * @throws UnknownMasterException if the master was not found
     *
     * @throws EnvironmentFailureException if an unexpected, internal or
     * environment-wide failure occurs.
     */
    public ReplicationNode ensureMonitor(RepNodeImpl monitor)
        throws UnknownMasterException,
               EnvironmentFailureException  {

        if (monitor.getType() != NodeType.MONITOR) {
            throw EnvironmentFailureException.unexpectedState
                ("Node type must be Monitor not: " + monitor.getType());
        }

        MasterValue masterValue = Learner.findMaster(electionsProtocol,
                                                     helperSockets,
                                                     logger,
                                                     null,
                                                     formatter);

        InetSocketAddress masterAddress =
            new InetSocketAddress(masterValue.getHostName(),
                                  masterValue.getPort());
        MessageExchange me = groupProtocol.new MessageExchange
            (masterAddress,
             GroupService.SERVICE_NAME,
             groupProtocol.new EnsureNode(monitor));
        me.run();
        ResponseMessage resp = me.getResponseMessage();
        if (resp instanceof EnsureOK) {
            EnsureOK okResp = (EnsureOK) resp;
            monitor.getNameIdPair().update(okResp.getNameIdPair());
            return new RepNodeImpl(new NameIdPair(masterValue.getNodeName()),
                                   NodeType.ELECTABLE,
                                   masterValue.getHostName(),
                                   masterValue.getPort());
        }
        throw getException(resp);
    }


    /**
     * Removes this node from the group, so that it is no longer a member of
     * the group. When removed, it will no longer be able to connect to a
     * master, nor can it participate in elections. If the node is a {@link
     * com.sleepycat.je.rep.monitor.Monitor} it will no longer be informed of
     * election results. Once removed, a node cannot be added again to the
     * group under the same node name.
     * <p>
     * Ideally, the node being removed should be shut down before this call is
     * issued.
     * <p>
     * If the node is an active <code>Replica</code> the master will terminate
     * its connection with the node and will not allow the replica to reconnect
     * with the group, since it's no longer a member of the group. If the node
     * wishes to re-join it should do so with a different node name.
     * <p>
     * An active Master cannot be removed. It must first be shutdown, or
     * transition to the <code>Replica</code> state before it can be removed
     * from the group.
     * <p>
     * @param nodeName identifies the node being removed from the group
     *
     * @throws UnknownMasterException if the master was not found
     *
     * @throws MemberNotFoundException if the node denoted by
     * <code>nodeName</code> is not a member of the replication group
     *
     * @throws MasterStateException if the member being removed is currently
     * the Master
     *
     * @throws EnvironmentFailureException if an unexpected, internal or
     * environment-wide failure occurs.
     * @see <a
     * href="{@docRoot}/../ReplicationGuide/utilities.html#node-addremove"
     * target="_top">Adding and Removing Nodes From the Group</a>
     */
    public void removeMember(String nodeName)
        throws UnknownMasterException,
               MemberNotFoundException,
               MasterStateException,
               EnvironmentFailureException {

        final ReplicationGroup group = getGroup();
        final RepNodeImpl node = (RepNodeImpl) group.getMember(nodeName);

        if (node == null) {
            throw new MemberNotFoundException("Node:" + nodeName +
                                              "is not a member of the group:" +
                                              groupName);
        }
        if (node.isRemoved() && node.isQuorumAck()) {
            throw new MemberNotFoundException("Node:" + nodeName +
                                              "is not currently a member of " +
                                              "the group:" + groupName +
                                              " It had been removed.");
        }
        final InetSocketAddress masterAddress= getMasterSocket();
        /* Check if the node is itself the master. */
        if (masterAddress.equals(node.getSocketAddress())) {
            throw new MasterStateException("Cannot remove an active master");
        }
        final MessageExchange me = groupProtocol.new MessageExchange
            (masterAddress,
             GroupService.SERVICE_NAME,
             groupProtocol.new RemoveMember(nodeName));
        me.run();
        ResponseMessage resp = me.getResponseMessage();
        if (resp instanceof OK) {
            return;
        }
        throw getException(resp);
    }

    /**
     * Returns the current composition of the group from the Master.
     *
     * @return the group description
     *
     * @throws UnknownMasterException if the master was not found
     *
     * @throws EnvironmentFailureException if an unexpected, internal or
     * environment-wide failure occurs
     */
    public ReplicationGroup getGroup()
        throws UnknownMasterException,
               EnvironmentFailureException {

        InetSocketAddress masterSocket = getMasterSocket();

        MessageExchange me = groupProtocol.new MessageExchange
        (masterSocket,
         GroupService.SERVICE_NAME,
         groupProtocol.new GroupRequest());
        me.run();
        ResponseMessage resp = me.getResponseMessage();
        if (resp instanceof GroupResponse) {
            return new ReplicationGroup(((GroupResponse)resp).getGroup());
        }
        throw getException(resp);
    }

    /**
     * Examines the response and generates a meaningful error exception.
     */
    private DatabaseException getException(ResponseMessage resp) {

        if (resp == null) {
            return EnvironmentFailureException.unexpectedState
                ("No response to request");
        }
        if (resp instanceof Fail) {
            Fail fail = (Fail)resp;
            switch (fail.getReason()) {
                case MEMBER_NOT_FOUND:
                    return new MemberNotFoundException(fail.getMessage());

                case IS_MASTER:
                    return new MasterStateException(fail.getMessage());

                default:
                    EnvironmentFailureException.
                        unexpectedState(fail.getMessage());
            }
        }
        if (resp instanceof ProtocolError) {
            return EnvironmentFailureException.unexpectedState
                (((ProtocolError)resp).getMessage());
        }
        return EnvironmentFailureException.unexpectedState
            ("Response not recognized: " + resp);
    }
}
TOP

Related Classes of com.sleepycat.je.rep.util.ReplicationGroupAdmin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.