| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite.visor.commands.open |
| |
| import java.net.URL |
| import java.util.logging.{ConsoleHandler, Level, Logger} |
| |
| import org.apache.ignite.IgniteSystemProperties._ |
| import org.apache.ignite.configuration.IgniteConfiguration |
| import org.apache.ignite.internal.IgniteComponentType._ |
| import org.apache.ignite.internal.IgniteEx |
| import org.apache.ignite.internal.util.scala.impl |
| import org.apache.ignite.internal.util.spring.IgniteSpringHelper |
| import org.apache.ignite.internal.util.{IgniteUtils => U} |
| import org.apache.ignite.logger.NullLogger |
| import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi |
| import org.apache.ignite.visor.commands.common.{VisorConsoleCommand, VisorTextTable} |
| import org.apache.ignite.visor.visor._ |
| import org.apache.ignite.visor.{VisorTag, visor} |
| import org.apache.ignite.{IgniteException, IgniteSystemProperties, Ignition} |
| |
| import scala.language.{implicitConversions, reflectiveCalls} |
| |
| /** |
| * ==Overview== |
| * Contains Visor command `node` implementation. |
| * |
| * ==Help== |
| * {{{ |
| * +--------------------------------+ |
| * | node | Prints node statistics. | |
| * +--------------------------------+ |
| * }}} |
| * |
| * ====Specification==== |
| * {{{ |
| * node "{-id8=<node-id8>|-id=<node-id>} {-a}" |
| * node |
| * }}} |
| * |
| * ====Arguments==== |
| * {{{ |
| * -id8=<node-id8> |
| * ID8 of node. Either '-id8' or '-id' can be specified. |
| * If neither specified - command starts in interactive mode. |
| * -id=<node-id> |
| * Full ID of node. Either '-id8' or '-id' can be specified. |
| * If neither specified - command starts in interactive mode. |
| * -a |
| * Print extended information. |
| * By default - only abbreviated statistics is printed. |
| * }}} |
| * |
| * ====Examples==== |
| * {{{ |
| * node |
| * Starts command in interactive mode. |
| * node "-id8=12345678" |
| * Prints statistics for specified node. |
| * node "-id8=12345678 -a" |
| * Prints full statistics for specified node. |
| * }}} |
| */ |
| class VisorOpenCommand extends VisorConsoleCommand { |
| @impl protected val name = "open" |
| |
| /** Default configuration path relative to Ignite home. */ |
| private final val DFLT_CFG = "config/default-config.xml" |
| |
| /** |
| * ==Command== |
| * Connects Visor console to the default grid. |
| * |
| * ==Example== |
| * <ex>open</ex> |
| * Connects to the default grid. |
| */ |
| def open() { |
| open("") |
| } |
| |
| /** |
| * ==Command== |
| * Connects Visor console to default or named grid. |
| * |
| * ==Examples== |
| * <ex>open -g=mygrid</ex> |
| * Connects to 'mygrid' grid. |
| * |
| * @param args Command arguments. |
| */ |
| def open(args: String) { |
| assert(args != null) |
| |
| if (isConnected) { |
| warn("Visor is already connected. Disconnect first.") |
| |
| return |
| } |
| |
| try { |
| def configuration(path: String): IgniteConfiguration = { |
| assert(path != null) |
| |
| val url = |
| try |
| new URL(path) |
| catch { |
| case e: Exception => |
| val url = U.resolveIgniteUrl(path) |
| |
| if (url == null) |
| throw new IgniteException("Ignite configuration path is invalid: " + path, e) |
| |
| url |
| } |
| |
| if (visor.quiet) { |
| val springLog = Logger.getLogger("org.springframework") |
| |
| if (springLog != null) |
| springLog.setLevel(Level.WARNING) |
| } |
| |
| val spring: IgniteSpringHelper = SPRING.create(false) |
| |
| val cfgs = |
| // Cache, indexing SPI configurations should be excluded from daemon node config. |
| spring.loadConfigurations(url, "cacheConfiguration", "lifecycleBeans", "indexingSpi").get1() |
| |
| if (cfgs == null || cfgs.isEmpty) |
| throw new IgniteException("Can't find grid configuration in: " + url) |
| |
| if (cfgs.size > 1) |
| throw new IgniteException("More than one grid configuration found in: " + url) |
| |
| val cfg = cfgs.iterator().next() |
| |
| if (visor.quiet) |
| cfg.setGridLogger(new NullLogger) |
| else { |
| if (classOf[Ignition].getClassLoader.getResource("org/apache/logging/log4j/core/Appender.class") != null) |
| System.setProperty(IgniteSystemProperties.IGNITE_CONSOLE_APPENDER, "false") |
| else |
| Logger.getGlobal.getHandlers.foreach({ |
| case handler: ConsoleHandler => Logger.getGlobal.removeHandler(handler) |
| }) |
| } |
| |
| // Setting up 'Config URL' for properly print in console. |
| System.setProperty(IgniteSystemProperties.IGNITE_CONFIG_URL, url.getPath) |
| |
| cfg.setConnectorConfiguration(null) |
| |
| var ioSpi = cfg.getCommunicationSpi |
| |
| if (ioSpi == null) |
| ioSpi = new TcpCommunicationSpi() |
| |
| cfg |
| } |
| |
| val argLst = parseArgs(args) |
| |
| val path = argValue("cpath", argLst) |
| val dflt = hasArgFlag("d", argLst) |
| |
| val (cfg, cfgPath) = |
| if (path.isDefined) |
| (configuration(path.get), path.get) |
| else if (dflt) |
| (configuration(DFLT_CFG), "<default>") |
| else { |
| // If configuration file is not defined in arguments, |
| // ask to choose from the list |
| askConfigFile() match { |
| case Some(p) => |
| nl() |
| |
| (VisorTextTable() +=("Using configuration", p)) render() |
| |
| nl() |
| |
| (configuration(p), p) |
| case None => |
| return |
| } |
| } |
| |
| open(cfg, cfgPath) |
| } |
| catch { |
| case e: IgniteException => |
| warn("Type 'help open' to see how to use this command.") |
| |
| status("q") |
| |
| throw e; |
| } |
| } |
| |
| /** |
| * Connects Visor console to configuration with path. |
| * |
| * @param cfg Configuration. |
| * @param cfgPath Configuration path. |
| */ |
| def open(cfg: IgniteConfiguration, cfgPath: String) = { |
| val daemon = Ignition.isDaemon |
| |
| val shutdownHook = IgniteSystemProperties.getString(IGNITE_NO_SHUTDOWN_HOOK, "false") |
| |
| // Make sure Visor console starts as daemon node. |
| Ignition.setDaemon(true) |
| |
| // Make sure visor starts without shutdown hook. |
| System.setProperty(IGNITE_NO_SHUTDOWN_HOOK, "true") |
| |
| ignite = try { |
| // We need to stop previous daemon node before to start new one. |
| prevIgnite.foreach(g => Ignition.stop(g.name(), true)) |
| |
| Ignition.start(cfg).asInstanceOf[IgniteEx] |
| } |
| finally { |
| Ignition.setDaemon(daemon) |
| |
| System.setProperty(IGNITE_NO_SHUTDOWN_HOOK, shutdownHook) |
| } |
| |
| prevIgnite = Some(ignite) |
| |
| visor.open(ignite.name(), cfgPath) |
| } |
| } |
| |
| /** |
| * Companion object that does initialization of the command. |
| */ |
| object VisorOpenCommand { |
| /** Singleton command. */ |
| private val cmd = new VisorOpenCommand |
| |
| // Adds command's help to visor. |
| addHelp( |
| name = "open", |
| shortInfo = "Connects Visor console to the grid.", |
| longInfo = Seq( |
| "Connects Visor console to the grid. Note that P2P class loading", |
| "should be enabled on all nodes.", |
| " ", |
| "If neither '-cpath' or '-d' are provided, command will ask", |
| "user to select Ignite configuration file in interactive mode." |
| ), |
| spec = Seq( |
| "open -cpath=<path>", |
| "open -d" |
| ), |
| args = Seq( |
| "-cpath=<path>" -> Seq( |
| "Ignite configuration path.", |
| "Can be absolute, relative to Ignite home folder or any well formed URL." |
| ), |
| "-d" -> Seq( |
| "Flag forces the command to connect to grid using default Ignite configuration file.", |
| "without interactive mode." |
| ) |
| ), |
| examples = Seq( |
| "open" -> |
| "Prompts user to select Ignite configuration file in interactive mode.", |
| "open -d" -> |
| "Connects Visor console to grid using default Ignite configuration file.", |
| "open -cpath=/gg/config/mycfg.xml" -> |
| "Connects Visor console to grid using Ignite configuration from provided file." |
| ), |
| emptyArgs = cmd.open, |
| withArgs = cmd.open |
| ) |
| |
| /** |
| * Singleton. |
| */ |
| def apply() = cmd |
| |
| /** |
| * Implicit converter from visor to commands "pimp". |
| * |
| * @param vs Visor tagging trait. |
| */ |
| implicit def fromNode2Visor(vs: VisorTag): VisorOpenCommand = cmd |
| } |