blob: a8de945b228ad0871c3d423c572171f10d853bfd [file] [log] [blame]
/*
* 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.startup;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.testframework.GridTestUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_UPDATE_NOTIFIER;
/**
* This class
*
*/
public final class GridVmNodesStarter {
/** Name of the system property defining name of command line program. */
private static final String IGNITE_PROG_NAME = "IGNITE_PROG_NAME";
/** */
private static final String IGNITE_INSTANCE_NAME_PREF = "gg-vm-grid-";
/** */
private static final int DFLT_NODES_COUNT = 20;
/** */
private static final String OPTION_CFG = "cfg";
/** */
private static final String OPTION_N = "n";
/** */
private static final AtomicInteger gridCnt = new AtomicInteger();
/**
* Enforces singleton.
*/
private GridVmNodesStarter() {
// No-op.
}
/**
* Echos the given messages.
*
* @param msg Message to echo.
*/
private static void echo(String msg) {
assert msg != null;
System.out.println(msg);
}
/**
* Echos exception stack trace.
*
* @param e Exception to print.
*/
private static void echo(IgniteCheckedException e) {
assert e != null;
System.err.println(e);
}
/**
* Exists with optional error message, usage show and exit code.
*
* @param errMsg Optional error message.
* @param options Command line options to show usage information.
* @param exitCode Exit code.
*/
private static void exit(String errMsg, Options options, int exitCode) {
if (errMsg != null)
echo("ERROR: " + errMsg);
String runner = System.getProperty(IGNITE_PROG_NAME, "randignite.{sh|bat}");
int space = runner.indexOf(' ');
runner = runner.substring(0, space == -1 ? runner.length() : space);
if (options != null) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(runner, options);
}
System.exit(exitCode);
}
/**
* Main entry point.
*
* @param args Command line arguments.
* @throws IgniteCheckedException If failed.
*/
public static void main(String[] args) throws IgniteCheckedException {
System.setProperty(IGNITE_UPDATE_NOTIFIER, "false");
Options options = createOptions();
// Create the command line parser.
CommandLineParser parser = new PosixParser();
String cfgPath = null;
Integer nodesCnt = null;
try {
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption(OPTION_CFG))
cfgPath = cmd.getOptionValue(OPTION_CFG);
if (cmd.hasOption(OPTION_N))
try {
nodesCnt = Integer.parseInt(cmd.getOptionValue(OPTION_N));
}
catch (NumberFormatException ignored) {
// No-op.
}
if (nodesCnt == null)
nodesCnt = DFLT_NODES_COUNT;
}
catch (ParseException e) {
exit(e.getMessage(), options, -1);
}
System.out.println();
System.out.println(">>> VM Nodes Starter parameters:");
System.out.println(" Nodes Count: " + nodesCnt);
System.out.println(" Config Path: " + cfgPath);
System.out.println();
final IgniteConfiguration[] cfgs = new IgniteConfiguration[nodesCnt];
for (int i = 0; i < nodesCnt; i++)
cfgs[i] = getConfigurations(cfgPath).iterator().next();
final AtomicInteger cfgIdx = new AtomicInteger(0);
GridTestUtils.runMultiThreadedAsync(new Callable<Object>() {
@Override public Object call() throws Exception {
G.start(cfgs[cfgIdx.getAndIncrement()]);
return null;
}
}, nodesCnt, "test-node-starter");
}
/**
* Initializes configurations.
*
*
* @param springCfgPath Configuration file path.
* @return List of configurations.
* @throws IgniteCheckedException If an error occurs.
*/
private static Iterable<IgniteConfiguration> getConfigurations(String springCfgPath)
throws IgniteCheckedException {
File path = GridTestUtils.resolveIgnitePath(springCfgPath);
if (path == null)
throw new IgniteCheckedException("Spring XML configuration file path is invalid: " + new File(springCfgPath) +
". Note that this path should be either absolute path or a relative path to IGNITE_HOME.");
if (!path.isFile())
throw new IgniteCheckedException("Provided file path is not a file: " + path);
ApplicationContext springCtx;
try {
springCtx = new FileSystemXmlApplicationContext(path.toURI().toURL().toString());
}
catch (BeansException | MalformedURLException e) {
throw new IgniteCheckedException("Failed to instantiate Spring XML application context: " + e.getMessage(), e);
}
Map cfgMap;
try {
// Note: Spring is not generics-friendly.
cfgMap = springCtx.getBeansOfType(IgniteConfiguration.class);
}
catch (BeansException e) {
throw new IgniteCheckedException("Failed to instantiate bean [type=" + IgniteConfiguration.class + ", err=" +
e.getMessage() + ']', e);
}
if (cfgMap == null)
throw new IgniteCheckedException("Failed to find a single grid factory configuration in: " + path);
if (cfgMap.isEmpty())
throw new IgniteCheckedException("Can't find grid factory configuration in: " + path);
Collection<IgniteConfiguration> res = new ArrayList<>();
for (IgniteConfiguration cfg : (Collection<IgniteConfiguration>)cfgMap.values()) {
res.add(cfg);
cfg.setIgniteInstanceName(IGNITE_INSTANCE_NAME_PREF + gridCnt.incrementAndGet());
}
return res;
}
/**
* Creates cli options.
*
* @return Command line options
*/
private static Options createOptions() {
Options options = new Options();
OptionGroup grp = new OptionGroup();
grp.setRequired(true);
Option cfg = new Option(OPTION_CFG, null, true, "path to Spring XML configuration file.");
cfg.setArgName("file");
Option n = new Option(null, OPTION_N, true, "nodes count.");
n.setValueSeparator('=');
n.setType(Integer.class);
grp.addOption(cfg);
grp.addOption(n);
options.addOptionGroup(grp);
return options;
}
}