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

com.sleepycat.je.rep.util.DbGroupAdmin 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.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;

import com.sleepycat.je.rep.NodeType;
import com.sleepycat.je.rep.ReplicatedEnvironment;
import com.sleepycat.je.rep.ReplicationNetworkConfig;
import com.sleepycat.je.rep.impl.RepGroupImpl;
import com.sleepycat.je.rep.impl.RepNodeImpl;
import com.sleepycat.je.rep.net.DataChannelFactory;
import com.sleepycat.je.rep.utilint.HostPortPair;
import com.sleepycat.je.rep.utilint.net.DataChannelFactoryBuilder;
import com.sleepycat.je.utilint.CmdUtil;
import com.sleepycat.je.utilint.PropUtil;

/**
 * DbGroupAdmin supplies the functionality of the administrative class {@link
 * ReplicationGroupAdmin} in a convenient command line utility. For example, it
 * can be used to display replication group information, or to remove a node
 * from the replication group.
 * 

* Note: This utility does not handle security and authorization. It is left * to the user to ensure that the utility is invoked with proper authorization. *

* See {@link DbGroupAdmin#main} for a full description of the command line * arguments. */ /* * SSL deferred * See {@link ReplicationConfig} for descriptions of the parameters that * control replication service access. */ public class DbGroupAdmin { enum Command { DUMP, REMOVE, TRANSFER_MASTER, UPDATE_ADDRESS, DELETE }; private String groupName; private Set helperSockets; private String nodeName; private String newHostName; private int newPort; private String timeout; private boolean forceFlag; private DataChannelFactory channelFactory; private ReplicationGroupAdmin groupAdmin; private final ArrayList actions = new ArrayList(); private static final String undocumentedUsageString = " -netProps # name of a property file containing\n" + " # properties needed for replication\n" + " # service access\n"; private static final String usageString = "Usage: " + CmdUtil.getJavaCommand(DbGroupAdmin.class) + "\n" + " -groupName # name of replication group\n" + " -helperHosts # identifier for one or more members\n" + " # of the replication group which can\n"+ " # be contacted for group information,\n"+ " # in this format:\n" + " # hostname[:port][,hostname[:port]]\n" + " -dumpGroup # dump group information\n" + " -removeMember # node to be removed\n" + " -updateAddress \n" + " # update the network address for a\n" + " # specified node. The node should not\n" + " # be alive when updating the address\n" + " -transferMaster [-force] \n" + " # transfer master role to one of the\n" + " # specified nodes."; /* Undocumented options for main() * -netProps <propFile> # (optional) * # name of a property file containing * # properties needed for replication * # service access * -deleteMember # Deletes the node from the group, doesn't * # just mark it removed */ /** * Usage: *

     * java {com.sleepycat.je.rep.util.DbGroupAdmin |
     *       -jar je-<version>.jar DbGroupAdmin}
     *   -groupName <group name>  # name of replication group
     *   -helperHosts <host:port> # identifier for one or more members
     *                            # of the replication group which can be
     *                            # contacted for group information, in
     *                            # this format:
     *                            # hostname[:port][,hostname[:port]]*
     *   -dumpGroup               # dump group information
     *   -removeMember <node name># node to be removed
     *   -updateAddress <node name> <new host:port>
     *                            # update the network address for a specified
     *                            # node. The node should not be alive when
     *                            # updating address
     *   -transferMaster [-force] <node1,node2,...> <timeout>
     *                            # transfer master role to one of the
     *                            # specified nodes.
     * 
*/ public static void main(String... args) throws Exception { DbGroupAdmin admin = new DbGroupAdmin(); admin.parseArgs(args); admin.run(); } /** * Print usage information for this utility. * * @param msg */ private void printUsage(String msg) { if (msg != null) { System.out.println(msg); } System.out.println(usageString); System.exit(-1); } /** * Parse the command line parameters. * * @param argv Input command line parameters. */ private void parseArgs(String argv[]) { int argc = 0; int nArgs = argv.length; String netPropsName = null; if (nArgs == 0) { printUsage(null); System.exit(0); } while (argc < nArgs) { String thisArg = argv[argc++]; if (thisArg.equals("-groupName")) { if (argc < nArgs) { groupName = argv[argc++]; } else { printUsage("-groupName requires an argument"); } } else if (thisArg.equals("-helperHosts")) { if (argc < nArgs) { helperSockets = HostPortPair.getSockets(argv[argc++]); } else { printUsage("-helperHosts requires an argument"); } } else if (thisArg.equals("-dumpGroup")) { actions.add(Command.DUMP); } else if (thisArg.equals("-removeMember")) { if (argc < nArgs) { nodeName = argv[argc++]; actions.add(Command.REMOVE); } else { printUsage("-removeMember requires an argument"); } } else if (thisArg.equals("-updateAddress")) { if (argc < nArgs) { nodeName = argv[argc++]; if (argc < nArgs) { String hostPort = argv[argc++]; int index = hostPort.lastIndexOf(":"); if (index < 0) { printUsage("Host port pair format must be " + ":"); } newHostName = hostPort.substring(0, index); newPort = Integer.parseInt (hostPort.substring(index + 1, hostPort.length())); } else { printUsage("-updateAddress requires a " + ": argument"); } actions.add(Command.UPDATE_ADDRESS); } else { printUsage ("-updateAddress requires the node name argument"); } } else if (thisArg.equals("-transferMaster")) { // TODO: it wouldn't be too hard to allow "-force" as a // node name. // if (argc < nArgs && "-force".equals(argv[argc])) { forceFlag = true; argc++; } if (argc + 1 < nArgs) { nodeName = argv[argc++]; /* * Allow either * -transferMaster mercury,venus 900 ms * or * -transferMaster mercury,venus "900 ms" */ if (argc + 1 < nArgs && argv[argc + 1].charAt(0) != '-') { timeout = argv[argc] + " " + argv[argc + 1]; argc += 2; } else { timeout = argv[argc++]; } actions.add(Command.TRANSFER_MASTER); } else { printUsage ("-transferMaster requires at least two arguments"); } } else if (thisArg.equals("-netProps")) { if (argc < nArgs) { netPropsName = argv[argc++]; } else { printUsage("-netProps requires an argument"); } } else if (thisArg.equals("-deleteMember")) { if (argc < nArgs) { nodeName = argv[argc++]; actions.add(Command.DELETE); } else { printUsage("-deleteMember requires an argument"); } } else { printUsage(thisArg + " is not a valid argument"); } } ReplicationNetworkConfig repNetConfig = ReplicationNetworkConfig.createDefault(); if (netPropsName != null) { try { repNetConfig = ReplicationNetworkConfig.create(new File(netPropsName)); } catch (FileNotFoundException fnfe) { printUsage("The net properties file " + netPropsName + " does not exist: " + fnfe.getMessage()); } catch (IllegalArgumentException iae) { printUsage("The net properties file " + netPropsName + " is not valid: " + iae.getMessage()); } } this.channelFactory = initializeFactory(repNetConfig, groupName); } /* Execute commands */ private void run() throws Exception { createGroupAdmin(); if (actions.size() == 0) { return; } for (Command action : actions) { switch (action) { /* Dump the group information. */ case DUMP: dumpGroup(); break; /* Remove a member. */ case REMOVE: removeMember(nodeName); break; /* Transfer the current mastership to a specified node. */ case TRANSFER_MASTER: transferMaster(nodeName, timeout); break; /* Update the network address of a specified node. */ case UPDATE_ADDRESS: updateAddress(nodeName, newHostName, newPort); break; /* Delete a member */ case DELETE: deleteMember(nodeName); break; default: throw new AssertionError(); } } } private DbGroupAdmin() { } /** * Create a DbGroupAdmin instance for programmatic use. * * @param groupName replication group name * @param helperSockets set of host and port pairs for group members which * can be queried to obtain group information. */ /* * SSL deferred * This constructor does not support non-default service net properties. * See the other constructor forms which allow setting of net properties. */ public DbGroupAdmin(String groupName, Set helperSockets) { this(groupName, helperSockets, (ReplicationNetworkConfig)null); } /** * @hidden SSL deferred * Create a DbGroupAdmin instance for programmatic use. * * @param groupName replication group name * @param helperSockets set of host and port pairs for group members which * can be queried to obtain group information. * @param netPropsFile a File containing replication net property * settings. This parameter is ignored if null. * @throws FileNotFoundException if the netPropsFile does not exist * @throws IllegalArgumentException if the netPropsFile contains * invalid settings. */ public DbGroupAdmin(String groupName, Set helperSockets, File netPropsFile) throws FileNotFoundException { this(groupName, helperSockets, makeRepNetConfig(netPropsFile)); } /** * @hidden SSL deferred * Create a DbGroupAdmin instance for programmatic use. * * @param groupName replication group name * @param helperSockets set of host and port pairs for group members which * can be queried to obtain group information. * @param netConfig replication net configuration - null allowable * This parameter is ignored if null. * @throws IllegalArgumentException if the netProps contains * invalid settings. */ public DbGroupAdmin(String groupName, Set helperSockets, ReplicationNetworkConfig netConfig) { this.groupName = groupName; this.helperSockets = helperSockets; this.channelFactory = initializeFactory(netConfig, groupName); createGroupAdmin(); } /* Create the ReplicationGroupAdmin object. */ private void createGroupAdmin() { if (groupName == null) { printUsage("Group name must be specified"); } if ((helperSockets == null) || (helperSockets.size() == 0)) { printUsage("Host and ports of helper nodes must be specified"); } groupAdmin = new ReplicationGroupAdmin( groupName, helperSockets, channelFactory); } /** * Display group information. Lists all members and the group master. Can * be used when reviewing the group configuration. */ public void dumpGroup() { System.out.println(getFormattedOutput()); } /** * Remove a node from the replication group. Once removed, a * node cannot be added again to the group under the same node name. * *

{@link NodeType#SECONDARY Secondary} nodes cannot be removed; they * automatically leave the group when they are shut down or become * disconnected from the master. * * @param name name of the node to be removed * * @see ReplicationGroupAdmin#removeMember */ /* * TODO: EXTERNAL is hidden for now. The doc need updated to include * EXTERNAL when it becomes public. */ public void removeMember(String name) { if (name == null) { printUsage("Node name must be specified"); } groupAdmin.removeMember(name); } /** * @hidden internal, for use in disaster recovery [#23447] * * Deletes a node from the replication group, which allows the node to be * added to the group again under the same name. * *

{@link NodeType#SECONDARY Secondary} and {@link NodeType#EXTERNAL * External} nodes cannot be deleted; they automatically leave the group * when they are shut down or become disconnected from the master. * * @param name name of the node to be deleted * * @see ReplicationGroupAdmin#deleteMember */ public void deleteMember(String name) { if (name == null) { printUsage("Node name must be specified"); } groupAdmin.deleteMember(name); } /** * Update the network address for a specified node. When updating the * address of a node, the node cannot be alive. See {@link * ReplicationGroupAdmin#updateAddress} for more information. * *

The address of a {@link NodeType#SECONDARY} node cannot be updated * with this method, since nodes must be members but not alive to be * updated, and secondary nodes are not members when they are not alive. * To change the address of a secondary node, restart the node with the * updated address. * * @param nodeName the name of the node whose address will be updated * @param newHostName the new host name of the node * @param newPort the new port number of the node */ @SuppressWarnings("hiding") public void updateAddress(String nodeName, String newHostName, int newPort) { if (nodeName == null || newHostName == null) { printUsage("Node name and new host name must be specified"); } if (newPort <= 0) { printUsage("Port of the new network address must be specified"); } groupAdmin.updateAddress(nodeName, newHostName, newPort); } /** * Transfers the master role from the current master to one of the * electable replicas specified in the argument list. * * @param nodeList comma-separated list of nodes * @param timeout in * same form as accepted by duration config params * * @see ReplicatedEnvironment#transferMaster */ @SuppressWarnings("hiding") public void transferMaster(String nodeList, String timeout) { String result = groupAdmin.transferMaster(parseNodes(nodeList), PropUtil.parseDuration(timeout), TimeUnit.MILLISECONDS, forceFlag); System.out.println("The new master is: " + result); } private Set parseNodes(String nodes) { if (nodes == null) { throw new IllegalArgumentException("node list may not be null"); } StringTokenizer st = new StringTokenizer(nodes, ","); Set set = new HashSet(); while (st.hasMoreElements()) { set.add(st.nextToken()); } return set; } /* * This method presents group information in a user friendly way. Internal * fields are hidden. */ private String getFormattedOutput() { StringBuilder sb = new StringBuilder(); RepGroupImpl repGroupImpl = groupAdmin.getGroup().getRepGroupImpl(); /* Get the master node name. */ String masterName = groupAdmin.getMasterNodeName(); /* Get the electable nodes information. */ sb.append("\nGroup: " + repGroupImpl.getName() + "\n"); sb.append("Electable Members:\n"); Set nodes = repGroupImpl.getElectableMembers(); if (nodes.size() == 0) { sb.append(" No electable members\n"); } else { for (RepNodeImpl node : nodes) { String type = masterName.equals(node.getName()) ? "master, " : ""; sb.append(" " + node.getName() + " (" + type + node.getHostName() + ":" + node.getPort() + ", " + node.getBarrierState() + ")\n"); } } /* Get the monitors information. */ sb.append("\nMonitor Members:\n"); nodes = repGroupImpl.getMonitorMembers(); if (nodes.size() == 0) { sb.append(" No monitors\n"); } else { for (RepNodeImpl node : nodes) { sb.append(" " + node.getName() + " (" + node.getHostName() + ":" + node.getPort() + ")\n"); } } /* Get information about secondary nodes */ sb.append("\nSecondary Members:\n"); nodes = repGroupImpl.getSecondaryMembers(); if (nodes.isEmpty()) { sb.append(" No secondary members\n"); } else { for (final RepNodeImpl node : nodes) { sb.append(" " + node.getName() + " (" + node.getHostName() + ":" + node.getPort() + ", " + node.getBarrierState() + ")\n"); } } /* Get information about external nodes */ sb.append("\nExternal Members:\n"); nodes = repGroupImpl.getExternalMembers(); if (nodes.isEmpty()) { sb.append(" No external members\n"); } else { for (final RepNodeImpl node : nodes) { sb.append(" " + node.getName() + " (" + node.getHostName() + ":" + node.getPort() + ", " + node.getBarrierState() + ")\n"); } } return sb.toString(); } private static ReplicationNetworkConfig makeRepNetConfig(File propFile) throws FileNotFoundException { if (propFile == null) { return ReplicationNetworkConfig.createDefault(); } return ReplicationNetworkConfig.create(propFile); } private static DataChannelFactory initializeFactory( ReplicationNetworkConfig repNetConfig, String logContext) { if (repNetConfig == null) { repNetConfig = ReplicationNetworkConfig.createDefault(); } return DataChannelFactoryBuilder.construct(repNetConfig, logContext); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy