Java tutorial
/************************************************************ * Copyright (c) 2015, Lawrence Livermore National Security, LLC. * Produced at the Lawrence Livermore National Laboratory. * Written by Timothy Meier, meier3@llnl.gov, All rights reserved. * LLNL-CODE-673346 * * This file is part of the OpenSM Monitoring Service (OMS) package. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (as published by * the Free Software Foundation) version 2.1 dated February 1999. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE * * Our Preamble Notice * * A. This notice is required to be provided under our contract with the U.S. * Department of Energy (DOE). This work was produced at the Lawrence Livermore * National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE. * * B. Neither the United States Government nor Lawrence Livermore National * Security, LLC nor any of their employees, makes any warranty, express or * implied, or assumes any liability or responsibility for the accuracy, * completeness, or usefulness of any information, apparatus, product, or * process disclosed, or represents that its use would not infringe privately- * owned rights. * * C. Also, reference herein to any specific commercial products, process, or * services by trade name, trademark, manufacturer or otherwise does not * necessarily constitute or imply its endorsement, recommendation, or favoring * by the United States Government or Lawrence Livermore National Security, * LLC. The views and opinions of authors expressed herein do not necessarily * state or reflect those of the United States Government or Lawrence Livermore * National Security, LLC, and shall not be used for advertising or product * endorsement purposes. * * file: SmtMulticast.java * * Created on: Aug 6, 2015 * Author: meier3 ********************************************************************/ package gov.llnl.lc.smt.command.route; import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import gov.llnl.lc.infiniband.core.IB_Address; import gov.llnl.lc.infiniband.core.IB_Guid; import gov.llnl.lc.infiniband.opensm.plugin.data.OSM_Fabric; import gov.llnl.lc.infiniband.opensm.plugin.data.OpenSmMonitorService; import gov.llnl.lc.infiniband.opensm.plugin.data.SBN_MulticastGroup; import gov.llnl.lc.infiniband.opensm.plugin.net.OsmServerStatus; import gov.llnl.lc.smt.SmtConstants; import gov.llnl.lc.smt.command.SmtCommand; import gov.llnl.lc.smt.command.config.SmtConfig; import gov.llnl.lc.smt.props.SmtProperty; /********************************************************************** * SmtMulticast provides primitive query operations for showing * one to many communication attributes. * * <p> * @see related classes and interfaces * * @author meier3 * * @version Sep 11, 2013 8:13:06 AM **********************************************************************/ public class SmtMulticast extends SmtCommand { private LinkedHashMap<String, SBN_MulticastGroup> McastGroups; /************************************************************ * Method Name: * doCommand **/ /** * Describe the method here * * @see gov.llnl.lc.smt.command.SmtCommand#doCommand(gov.llnl.lc.smt.command.config.SmtConfig) * * @param config * @return * @throws Exception ***********************************************************/ @Override public boolean doCommand(SmtConfig config) throws Exception { // this is a Link command, and it can take a subcommand and an argument String subCommand = null; Map<String, String> map = smtConfig.getConfigMap(); if (config != null) { //config.printConfig(); map = config.getConfigMap(); subCommand = map.get(SmtProperty.SMT_SUBCOMMAND.getName()); // check to see if the subCommand takes any arguments or values if (subCommand == null) { subCommand = SmtProperty.SMT_HELP.getName(); } } if (OMService == null) logger.severe("The service is null"); // this is the MULTICAST command, and it can take a subcommand and an argument McastGroups = preenMCastGroups(OMService); MulticastQuery qType = null; if (subCommand.equalsIgnoreCase(SmtProperty.SMT_QUERY_TYPE.getName())) qType = MulticastQuery.getByName(map.get(SmtProperty.SMT_QUERY_TYPE.getName())); // optional, only needed for some commands int mlid = getMLid(config, (MulticastQuery.MCAST_MLID.equals(qType))); IB_Guid guid = getGuid(config, (MulticastQuery.MCAST_MLID.equals(qType))); // there should only be one subcommand (use big if statement) if (qType != null) { switch (qType) { case MCAST_LIST: System.out.println(MulticastQuery.describeAllQueryTypes()); break; case MCAST_STATUS: System.out.println(SmtMulticast.getStatus(OMService)); break; case MCAST_MLID: if (mlid > 0) { showMulticastGroup(mlid); System.exit(0); } else { System.out.println("Supply a valid mlid (see -q groups)"); System.exit(0); } break; case MCAST_MEMBER: if (guid != null) { showGroupsWithMember(guid); System.exit(0); } else { System.out.println("Supply a valid node lid, guid, or name"); System.exit(0); } break; case MCAST_GROUPS: showGroups(); break; default: System.out.println("That's not an option"); break; } } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_STATUS.getName())) { System.out.println(SmtMulticast.getStatus(OMService)); } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_DUMP.getName())) { showAllMulticastInfo(); } else if (subCommand.equalsIgnoreCase(SmtProperty.SMT_LIST.getName())) { System.out.println(MulticastQuery.describeAllQueryTypes()); } else if (mlid > 0) { // handle short-cuts. showMulticastGroup(mlid); } else if (OMService != null) { System.out.println(SmtMulticast.getStatus(OMService)); } return false; } public static SBN_MulticastGroup[] preenMcastGroups(SBN_MulticastGroup[] MCGroups) { // the arrays seem to hold redundant junk, not sure why, but try to save // only unique entries LinkedHashMap<String, SBN_MulticastGroup> mcGroups = new LinkedHashMap<String, SBN_MulticastGroup>(500 + 1, .75F, false); if ((MCGroups != null) && (MCGroups.length > 0)) { for (SBN_MulticastGroup mg : MCGroups) { // add my mlid, they should be unique (this is a destructive write, later array entries win // only if they have non-zero members String key = Integer.toString(mg.mlid).trim(); if (!mcGroups.containsKey(key) || mg.port_guids.length > 0) mcGroups.put(key, mg); } } SBN_MulticastGroup list[] = new SBN_MulticastGroup[mcGroups.size()]; return mcGroups.values().toArray(list); } public static LinkedHashMap<String, SBN_MulticastGroup> preenMCastGroups(OpenSmMonitorService oms) { // the arrays seem to hold redundant junk, not sure why, but try to save // only unique entries LinkedHashMap<String, SBN_MulticastGroup> mcGroups = new LinkedHashMap<String, SBN_MulticastGroup>(500 + 1, .75F, false); if ((oms != null) && (oms.getFabric() != null) && (oms.getFabric().getOsmSubnet() != null)) { SBN_MulticastGroup[] MCGroups = preenMcastGroups(oms.getFabric().getOsmSubnet().MCGroups); if ((MCGroups != null) && (MCGroups.length > 0)) for (SBN_MulticastGroup mg : MCGroups) { String key = Integer.toString(mg.mlid).trim(); mcGroups.put(key, mg); } } return mcGroups; } /************************************************************ * Method Name: * init **/ /** * Describe the method here * * @see gov.llnl.lc.smt.command.SmtCommand#init() * * @return ***********************************************************/ @Override public boolean init() { USAGE = "[-h=<host url>] [-pn=<port num>] "; HEADER = "smt-multicast - examine one-to-many communication attributes"; EXAMPLE = "examples:" + SmtConstants.NEW_LINE + "> smt-multicast -pn 10011 -q status" + SmtConstants.NEW_LINE + "> smt-multicast -rH surface3h.his -q member 0xf452:1403:0034:2ea1" + SmtConstants.NEW_LINE + "."; // terminate with nl // create and initialize the common options for this command initCommonOptions(); // add non-common options // initialize the command specific options SmtProperty sp = SmtProperty.SMT_QUERY_TYPE; Option qType = OptionBuilder.hasArg(true).hasArgs(1).withArgName(sp.getArgName()).withValueSeparator('=') .withDescription(sp.getDescription()).withLongOpt(sp.getName()).create(sp.getShortName()); sp = SmtProperty.SMT_QUERY_LIST; Option qList = new Option(sp.getShortName(), sp.getName(), false, sp.getDescription()); sp = SmtProperty.SMT_STATUS; Option status = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName()) .create(sp.getShortName()); sp = SmtProperty.SMT_DUMP; Option dump = OptionBuilder.hasArg(false).withDescription(sp.getDescription()).withLongOpt(sp.getName()) .create(sp.getShortName()); options.addOption(qType); options.addOption(qList); options.addOption(status); options.addOption(dump); return true; } /************************************************************ * Method Name: * parseCommands **/ /** * Parse the command line options and set everything up for "doing the command" in doCommand(); * * @see gov.llnl.lc.smt.command.SmtCommand#parseCommands(java.util.Map, org.apache.commons.cli.CommandLine) * * @param config * @param line * @return ***********************************************************/ @Override public boolean parseCommands(Map<String, String> config, CommandLine line) { boolean status = true; // set the command, args, and sub-command config.put(SmtProperty.SMT_COMMAND.getName(), this.getClass().getName()); // hopefully the node description is here, so save it saveCommandArgs(line.getArgs(), config); SmtProperty sp = SmtProperty.SMT_READ_OMS_HISTORY; if (line.hasOption(sp.getName())) { status = putHistoryProperty(config, line.getOptionValue(sp.getName())); config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName()); } // parse (only) the command specific options sp = SmtProperty.SMT_QUERY_TYPE; if (line.hasOption(sp.getName())) { config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName()); config.put(sp.getName(), line.getOptionValue(sp.getName())); } sp = SmtProperty.SMT_QUERY_LIST; if (line.hasOption(sp.getName())) { config.put(SmtProperty.SMT_SUBCOMMAND.getName(), SmtProperty.SMT_QUERY_TYPE.getName()); config.put(SmtProperty.SMT_QUERY_TYPE.getName(), SmtProperty.SMT_LIST.getName()); } sp = SmtProperty.SMT_STATUS; if (line.hasOption(sp.getName())) { config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName()); config.put(sp.getName(), line.getOptionValue(sp.getName())); } sp = SmtProperty.SMT_DUMP; if (line.hasOption(sp.getName())) { config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName()); config.put(sp.getName(), line.getOptionValue(sp.getName())); } sp = SmtProperty.SMT_LIST; if (line.hasOption(sp.getName())) { config.put(sp.getName(), line.getOptionValue(sp.getName())); config.put(SmtProperty.SMT_SUBCOMMAND.getName(), sp.getName()); } return status; } private void showGroups() { SBN_MulticastGroup list[] = new SBN_MulticastGroup[McastGroups.size()]; SmtMulticast.showGroups(McastGroups.values().toArray(list)); } public static void showGroups(SBN_MulticastGroup[] mGroups) { int n = 1; for (SBN_MulticastGroup g : mGroups) System.out.println(toMulticastGroupString(g, String.format("%3d mlid: ", n++))); } private void showGroupsWithMember(IB_Guid guid) { SBN_MulticastGroup[] mGroups = getGroupsWithMember(McastGroups, guid); if (mGroups.length < 1) System.out.println("Guid " + guid.toColonString() + " was not found in any Multicast Groups"); else { System.out.println( "Guid " + guid.toColonString() + " was found in " + mGroups.length + " Multicast Groups"); SmtMulticast.showGroups(mGroups); } } public static String toMulticastGroupString(SBN_MulticastGroup mg, String prepend) { // a one liner StringBuffer buff = new StringBuffer(); String wk = mg.well_known ? "well known" : ""; String format = "%s%4d (0x%4s), %10s # members: %4d"; // not really a group, if there is only one (or fewer) members buff.append( String.format(format, prepend, mg.mlid, Integer.toHexString(mg.mlid), wk, mg.port_guids.length)); return buff.toString(); } public static SBN_MulticastGroup[] getGroupsWithMembers(LinkedHashMap<String, SBN_MulticastGroup> mcGroups, int minimumNumber) { java.util.ArrayList<SBN_MulticastGroup> gMems = new java.util.ArrayList<SBN_MulticastGroup>(); for (SBN_MulticastGroup g : mcGroups.values()) { // if this has the minimum number of members, then add it to the return list if (g.port_guids.length >= minimumNumber) gMems.add(g); } SBN_MulticastGroup list[] = new SBN_MulticastGroup[gMems.size()]; return gMems.toArray(list); } public static SBN_MulticastGroup[] getGroupsWithMember(LinkedHashMap<String, SBN_MulticastGroup> mcGroups, IB_Guid guid) { if (guid == null) return null; // look through the groups, and build a new list which contains this guid as a member java.util.ArrayList<SBN_MulticastGroup> gMems = new java.util.ArrayList<SBN_MulticastGroup>(); for (SBN_MulticastGroup g : mcGroups.values()) { // if this contains this guid, then add it to the return list if (g.isMember(guid.getGuid())) gMems.add(g); } SBN_MulticastGroup list[] = new SBN_MulticastGroup[gMems.size()]; return gMems.toArray(list); } public static SBN_MulticastGroup[] getWellKnownGroups(LinkedHashMap<String, SBN_MulticastGroup> mcGroups, boolean wellKnown) { // if wellKnown is true, only return the well_known groups // if wellKnown is false, only return the non-well_known groups java.util.ArrayList<SBN_MulticastGroup> gMems = new java.util.ArrayList<SBN_MulticastGroup>(); for (SBN_MulticastGroup g : mcGroups.values()) { // if this is a well known group, return it if (!(g.well_known ^ wellKnown)) gMems.add(g); } SBN_MulticastGroup list[] = new SBN_MulticastGroup[gMems.size()]; return gMems.toArray(list); } private void showAllMulticastInfo() { System.out.println(SmtMulticast.getStatus(OMService)); for (SBN_MulticastGroup mg : McastGroups.values()) showMulticastGroup(mg); } public static SBN_MulticastGroup getMulticastGroup(int mlid, SBN_MulticastGroup[] mGroups) { SBN_MulticastGroup[] MCGroups = preenMcastGroups(mGroups); for (SBN_MulticastGroup g : MCGroups) { // if the mlids match, return it if (mlid == g.mlid) return g; } return null; } private void showMulticastGroup(int mlid) { showMulticastGroup(McastGroups.get(Integer.toString(mlid).trim())); } private void showMulticastGroup(SBN_MulticastGroup mg) { if (mg != null) { System.out.println(mg.toMulticastGroupString()); System.out.println("----------------------------------------------------"); System.out.println(mg.toMulticastTableString(OMService.getFabric(), "")); } } public static String getStatus(OpenSmMonitorService OMService) { // return a string representation of the multicast statistics, similar to the smt-console if (OMService == null) { logger.severe("Can't get status from a null OMS object"); return "Can't get status from a null OMS object"; } OSM_Fabric Fabric = OMService.getFabric(); LinkedHashMap<String, SBN_MulticastGroup> mcGroups = preenMCastGroups(OMService); OsmServerStatus RStatus = OMService.getRemoteServerStatus(); StringBuffer buff = new StringBuffer(); buff.append(String.format(" Multicast Groups\n")); buff.append(SmtConstants.NEW_LINE); buff.append(String.format("Fabric Name: %20s\n", Fabric.getFabricName())); if (RStatus != null) buff.append( String.format("Up since: %20s\n", RStatus.Server.getStartTime().toString())); buff.append(String.format("timestamp: %20s\n", Fabric.getTimeStamp().toString())); buff.append(SmtConstants.NEW_LINE); int numGroups = mcGroups.size(); int numSingleGroups = getGroupsWithMembers(mcGroups, 1).length; int numActualGroups = getGroupsWithMembers(mcGroups, 2).length; int numEmptyGroups = numGroups - numSingleGroups; numSingleGroups -= numActualGroups; String format = "%38s: %4d" + SmtConstants.NEW_LINE; buff.append(String.format(format, "total multicast groups", numGroups)); buff.append(String.format(format, "empty multicast groups", numEmptyGroups)); buff.append(String.format(format, "multicast groups with a single member", numSingleGroups)); buff.append(String.format(format, "multicast groups with many members", numActualGroups)); buff.append( String.format(format, "well known multicast groups", getWellKnownGroups(mcGroups, true).length)); buff.append(String.format(format, "unknown multicast groups", getWellKnownGroups(mcGroups, false).length)); return buff.toString(); } /************************************************************ * Method Name: * main **/ /** * Describe the method here * * @see describe related java objects * * @param args ***********************************************************/ public static void main(String[] args) throws Exception { System.exit((new SmtMulticast().execute(args)) ? 0 : -1); } private void saveCommandArgs(String[] args, Map<String, String> config) { // stash the command line arguments away, because we will use them later // see getNodeGuid() if ((args != null && args.length > 0)) { // save all the arguments in a single parameter StringBuffer cmdArgs = new StringBuffer(); for (String arg : args) { cmdArgs.append(arg + " "); } config.put(SmtProperty.SMT_COMMAND_ARGS.getName(), cmdArgs.toString().trim()); } } private IB_Guid getGuid(SmtConfig config, boolean isMlidCmd) { // if there are any arguments, they normally reference a node identifier // return null, indicating couldn't be found, or nothing specified // // a node identifier is a name, guid, or lid if ((config != null) && (!isMlidCmd)) { Map<String, String> map = config.getConfigMap(); String nodeid = map.get(SmtProperty.SMT_COMMAND_ARGS.getName()); if (nodeid != null) { return getNodeGuid(nodeid); } } return null; } private int getMLid(SmtConfig config, boolean isMlidCmd) { // if there are any arguments, and the mlid flag is true, try // to decode the first argument as an mlid // // return -1, if the value could not be decoded, or if the mlid // is NOT in the table if (config != null) { Map<String, String> map = config.getConfigMap(); String cargs = map.get(SmtProperty.SMT_COMMAND_ARGS.getName()); if (cargs != null) { if (isMlidCmd) { // should be at least one word // if more than one, ignore the rest String[] args = cargs.split(" "); // should be a lid try { int mLid = IB_Address.toLidValue(args[0]); // check to see if this lid is in the table, if so return it if (McastGroups.containsKey(Integer.toString(mLid).trim())) return mLid; } catch (NumberFormatException nfe) { logger.severe("Couldn't convert (" + args[0] + ") to an mlid"); } } } } return -1; } }