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

com.orientechnologies.orient.stresstest.OStressTesterCommandLineParser Maven / Gradle / Ivy

The newest version!
/*
 *
 *  *  Copyright 2010-2016 OrientDB LTD (http://orientdb.com)
 *  *
 *  *  Licensed 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.
 *  *
 *  * For more information: http://orientdb.com
 *
 */
package com.orientechnologies.orient.stresstest;

import com.orientechnologies.orient.client.remote.OStorageRemote;
import com.orientechnologies.orient.stresstest.workload.OWorkload;
import java.io.Console;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * This is the parser of the command line arguments passed with the invocation of OStressTester. It
 * contains a static method that - given the arguments - returns a OStressTester object.
 *
 * @author Andrea Iacono
 */
public class OStressTesterCommandLineParser {
  public static final String TEMP_DATABASE_NAME = "stress-test-db-";
  public static final String CONSOLE_REMOTE_PASSWORD_PROMPT =
      "OrientDB Server (%s:%d) - Please insert the root password to create the test database: ";

  public static final String OPTION_CONCURRENCY = "c";
  public static final String OPTION_MODE = "m";
  public static final String OPTION_WORKLOAD = "w";
  public static final String OPTION_TRANSACTIONS = "tx";
  public static final String OPTION_DELAY = "delay";
  public static final String OPTION_KEEP_DATABASE_AFTER_TEST = "k";
  public static final String OPTION_OUTPUT_FILE = "o";
  public static final String OPTION_PLOCAL_PATH = "d";
  public static final String OPTION_LOAD_BALANCING = "lb";
  public static final String OPTION_DBNAME = "db";
  public static final String OPTION_CHECK_DATABASE = "chk";
  public static final String OPTION_ROOT_PASSWORD = "root-password";
  public static final String ERROR_OPENING_CONSOLE =
      "An error has occurred opening the console. Please supply the root password as the -"
          + OPTION_ROOT_PASSWORD
          + " parameter.";
  public static final String OPTION_REMOTE_IP = "remote-ip";
  public static final String OPTION_HA_METRICS = "ha-metrics";
  public static final String COMMAND_LINE_PARSER_MISSING_REMOTE_IP =
      "The mode is ["
          + OStressTester.OMode.REMOTE
          + "] but the param --"
          + OPTION_REMOTE_IP
          + " wasn't passed.";
  public static final String OPTION_REMOTE_PORT = "remote-port";

  public static final String MAIN_OPTIONS =
      OPTION_MODE
          + OPTION_CONCURRENCY
          + OPTION_WORKLOAD
          + OPTION_TRANSACTIONS
          + OPTION_DELAY
          + OPTION_OUTPUT_FILE
          + OPTION_PLOCAL_PATH
          + OPTION_KEEP_DATABASE_AFTER_TEST
          + OPTION_CHECK_DATABASE
          + OPTION_LOAD_BALANCING
          + OPTION_DBNAME;

  public static final String SYNTAX =
      "StressTester "
          + "\n\t-m mode (can be any of these: [plocal|memory|remote|distributed] )"
          + "\n\t-w workloads"
          + "\n\t-c concurrency-level"
          + "\n\t-x operations-per-transaction"
          + "\n\t-o result-output-file"
          + "\n\t-d database-directory"
          + "\n\t-k true|false"
          + "\n\t-chk true|false"
          + "\n\t--root-password rootPassword"
          + "\n\t--remote-ip ipOrHostname"
          + "\n\t--remote-port portNumber"
          + "\n\t-lb load-balancing-strategy"
          + "\n\t-db db-name"
          + "\n";

  static final String COMMAND_LINE_PARSER_INVALID_NUMBER = "Invalid %s number [%s].";
  static final String COMMAND_LINE_PARSER_LESSER_THAN_ZERO_NUMBER =
      "The %s value must be greater than 0.";
  static final String COMMAND_LINE_PARSER_INVALID_MODE = "Invalid mode [%s].";
  static final String COMMAND_LINE_PARSER_INVALID_OPTION = "Invalid option [%s]";
  static final String COMMAND_LINE_PARSER_EXPECTED_VALUE = "Expected value after argument [%s]";
  static final String COMMAND_LINE_PARSER_INVALID_REMOTE_PORT_NUMBER =
      "Invalid remote port [%d]. The port number has to be lesser than 65536.";
  static final String COMMAND_LINE_PARSER_MODE_PARAM_MANDATORY =
      "The mode param [-m] is mandatory.";
  static final String COMMAND_LINE_PARSER_NOT_EXISTING_OUTPUT_DIRECTORY =
      "The directory where to write the resultOutputFile [%s] doesn't exist.";
  static final String COMMAND_LINE_PARSER_NOT_EXISTING_PLOCAL_PATH =
      "The plocal directory (param -d) doesn't exist [%s].";
  static final String COMMAND_LINE_PARSER_NO_WRITE_PERMISSION_OUTPUT_FILE =
      "You don't have the permissions for writing on directory [%s] the resultOutputFile.";
  static final String COMMAND_LINE_PARSER_NO_WRITE_PERMISSION_PLOCAL_PATH =
      "You don't have the permissions for writing on plocal directory [%s].";
  static final String COMMAND_LINE_PARSER_PLOCAL_PATH_IS_NOT_DIRECTORY =
      "The plocal path [%s] is not a directory.";

  /**
   * builds a StressTester object using the command line arguments
   *
   * @param args
   * @return
   * @throws Exception
   */
  public static OStressTester getStressTester(String[] args) throws Exception {

    final Map options = checkOptions(readOptions(args));

    final OStressTesterSettings settings = new OStressTesterSettings();

    settings.dbName =
        TEMP_DATABASE_NAME + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    if (options.get(OPTION_DBNAME) != null) settings.dbName = options.get(OPTION_DBNAME);

    settings.mode =
        OStressTester.OMode.valueOf(options.get(OPTION_MODE).toUpperCase(Locale.ENGLISH));
    settings.rootPassword = options.get(OPTION_ROOT_PASSWORD);
    settings.resultOutputFile = options.get(OPTION_OUTPUT_FILE);
    settings.plocalPath = options.get(OPTION_PLOCAL_PATH);
    settings.operationsPerTransaction = getNumber(options.get(OPTION_TRANSACTIONS), "transactions");
    settings.delay = getNumber(options.get(OPTION_DELAY), "delay");
    settings.concurrencyLevel = getNumber(options.get(OPTION_CONCURRENCY), "concurrency");
    settings.remoteIp = options.get(OPTION_REMOTE_IP);
    settings.haMetrics =
        options.get(OPTION_HA_METRICS) != null
            ? Boolean.parseBoolean(options.get(OPTION_HA_METRICS))
            : false;
    settings.workloadCfg = options.get(OPTION_WORKLOAD);
    if (options.get(OPTION_KEEP_DATABASE_AFTER_TEST) != null) {
      settings.keepDatabaseAfterTest =
          Boolean.parseBoolean(options.get(OPTION_KEEP_DATABASE_AFTER_TEST));
    } else {
      settings.keepDatabaseAfterTest = false;
    }
    settings.remotePort = 2424;
    settings.checkDatabase = Boolean.parseBoolean(options.get(OPTION_CHECK_DATABASE));
    if (options.get(OPTION_LOAD_BALANCING) != null)
      settings.loadBalancing =
          OStorageRemote.CONNECTION_STRATEGY.valueOf(
              options.get(OPTION_LOAD_BALANCING).toUpperCase(Locale.ENGLISH));

    if (settings.plocalPath != null) {
      if (settings.plocalPath.endsWith(File.separator)) {
        settings.plocalPath =
            settings.plocalPath.substring(
                0, settings.plocalPath.length() - File.separator.length());
      }
      File plocalFile = new File(settings.plocalPath);
      if (!plocalFile.exists()) {
        throw new IllegalArgumentException(
            String.format(COMMAND_LINE_PARSER_NOT_EXISTING_PLOCAL_PATH, settings.plocalPath));
      }
      if (!plocalFile.canWrite()) {
        throw new IllegalArgumentException(
            String.format(
                COMMAND_LINE_PARSER_NO_WRITE_PERMISSION_PLOCAL_PATH, settings.plocalPath));
      }
      if (!plocalFile.isDirectory()) {
        throw new IllegalArgumentException(
            String.format(COMMAND_LINE_PARSER_PLOCAL_PATH_IS_NOT_DIRECTORY, settings.plocalPath));
      }
    }

    if (settings.resultOutputFile != null) {

      File outputFile = new File(settings.resultOutputFile);
      if (outputFile.exists()) {
        outputFile.delete();
      }

      File parentFile = outputFile.getParentFile();

      // if the filename does not contain a path (both relative and absolute)
      if (parentFile == null) {
        parentFile = new File(".");
      }

      if (!parentFile.exists()) {
        throw new IllegalArgumentException(
            String.format(
                COMMAND_LINE_PARSER_NOT_EXISTING_OUTPUT_DIRECTORY, parentFile.getAbsoluteFile()));
      }
      if (!parentFile.canWrite()) {
        throw new IllegalArgumentException(
            String.format(
                COMMAND_LINE_PARSER_NO_WRITE_PERMISSION_OUTPUT_FILE, parentFile.getAbsoluteFile()));
      }
    }

    if (options.get(OPTION_REMOTE_PORT) != null) {
      settings.remotePort = getNumber(options.get(OPTION_REMOTE_PORT), "remotePort");
      if (settings.remotePort > 65535) {
        throw new IllegalArgumentException(
            String.format(COMMAND_LINE_PARSER_INVALID_REMOTE_PORT_NUMBER, settings.remotePort));
      }
    }

    if (settings.mode == OStressTester.OMode.DISTRIBUTED) {
      throw new IllegalArgumentException(
          String.format("OMode [%s] not yet supported.", settings.mode));
    }

    if (settings.mode == OStressTester.OMode.REMOTE && settings.remoteIp == null) {
      throw new IllegalArgumentException(COMMAND_LINE_PARSER_MISSING_REMOTE_IP);
    }

    if (settings.rootPassword == null && settings.mode == OStressTester.OMode.REMOTE) {
      Console console = System.console();
      if (console != null) {
        settings.rootPassword =
            String.valueOf(
                console.readPassword(
                    String.format(
                        CONSOLE_REMOTE_PASSWORD_PROMPT, settings.remoteIp, settings.remotePort)));
      } else {
        throw new Exception(ERROR_OPENING_CONSOLE);
      }
    }

    final List workloads = parseWorkloads(settings.workloadCfg);

    final ODatabaseIdentifier databaseIdentifier = new ODatabaseIdentifier(settings);

    return new OStressTester(workloads, databaseIdentifier, settings);
  }

  private static List parseWorkloads(final String workloadConfig) {
    if (workloadConfig == null || workloadConfig.isEmpty())
      throw new IllegalArgumentException(
          "Workload parameter is mandatory. Syntax: ");

    final List result = new ArrayList();

    final String[] parts = workloadConfig.split(",");
    for (String part : parts) {
      String workloadName;
      String workloadParams;

      final int pos = part.indexOf(":");
      if (pos > -1) {
        workloadName = part.substring(0, pos);
        workloadParams = part.substring(pos + 1);
      } else {
        workloadName = part;
        workloadParams = null;
      }

      final OWorkload workload = OStressTester.getWorkloadFactory().get(workloadName);
      if (workload == null)
        throw new IllegalArgumentException(
            "Workload '"
                + workloadName
                + "' is not configured. Use one of the following: "
                + OStressTester.getWorkloadFactory().getRegistered());
      workload.parseParameters(workloadParams);

      result.add(workload);
    }

    return result;
  }

  private static int getNumber(final String value, final String option)
      throws IllegalArgumentException {
    if (value == null) return 0;

    try {
      int val = Integer.parseInt(value);
      if (val < 0) {
        throw new IllegalArgumentException(
            String.format(COMMAND_LINE_PARSER_LESSER_THAN_ZERO_NUMBER, option));
      }
      return val;
    } catch (NumberFormatException ex) {
      throw new IllegalArgumentException(
          String.format(COMMAND_LINE_PARSER_INVALID_NUMBER, option, value), ex);
    }
  }

  private static Map checkOptions(Map options)
      throws IllegalArgumentException {

    if (options.get(OPTION_MODE) == null) {
      throw new IllegalArgumentException(String.format(COMMAND_LINE_PARSER_MODE_PARAM_MANDATORY));
    }

    options = setDefaultIfNotPresent(options, OPTION_MODE, OStressTester.OMode.PLOCAL.name());
    options = setDefaultIfNotPresent(options, OPTION_CONCURRENCY, "4");
    options = setDefaultIfNotPresent(options, OPTION_TRANSACTIONS, "0");
    options = setDefaultIfNotPresent(options, OPTION_WORKLOAD, "CRUD:C25000R25000U25000D25000");

    try {
      OStressTester.OMode.valueOf(options.get(OPTION_MODE).toUpperCase(Locale.ENGLISH));
    } catch (IllegalArgumentException ex) {
      throw new IllegalArgumentException(
          String.format(COMMAND_LINE_PARSER_INVALID_MODE, options.get(OPTION_MODE)), ex);
    }

    return options;
  }

  private static Map setDefaultIfNotPresent(
      Map options, String option, String value) throws IllegalArgumentException {
    if (!options.containsKey(option)) {
      System.out.println(
          String.format("WARNING: '%s' option not found. Defaulting to %s.", option, value));
      options.put(option, value);
    }
    return options;
  }

  private static Map readOptions(final String[] args)
      throws IllegalArgumentException {

    final Map options = new HashMap();

    // reads arguments from command line
    for (int i = 0; i < args.length; i++) {

      // an argument cannot be shorter than one char
      if (args[i].length() < 2) {
        throw new IllegalArgumentException(
            String.format(COMMAND_LINE_PARSER_INVALID_OPTION, args[i]));
      }

      switch (args[i].charAt(0)) {
        case '-':
          if (args.length - 1 == i) {
            throw new IllegalArgumentException(
                (String.format(COMMAND_LINE_PARSER_EXPECTED_VALUE, args[i])));
          }

          String option = args[i].substring(1);
          if (option.startsWith("-")) {
            option = option.substring(1);
          } else {
            if (!MAIN_OPTIONS.contains(option)) {
              throw new IllegalArgumentException(
                  (String.format(COMMAND_LINE_PARSER_INVALID_OPTION, args[i])));
            }
          }
          options.put(option, args[i + 1]);

          // jumps to the next switch
          i++;

          break;
      }
    }

    return options;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy