/*                          
 * mBench: The Open Source Micro Benchmark Tool 
 *                                             
 * Distributable under GPL license. 
 * See terms of license at gnu.org.
 *
 * Copyright (C) 2005 Sumisho Computer Systems Corp.
 */
package jp.co.scs.mbench;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 *      Main method class of mBench.
 * 
 *      @author Tetsuto Ikeda
 *      @author Masato Koga
 */
public class BenchmarkMain {
    /**
     *  benchmark manager instance
     */
    private static BenchmarkManager manager = null;
    
    /**
     *  text for threads number
     */
    public static final String THREAD_NUMBER = "threadNumber";
    
    /**
     *  text for repeat number
     */
    public static final String REPEAT_NUMBER = "repeatNumber";
    
    /**
     *  text for transaction number of all benchmark
     */
    public static final String TX_NUMBER = "transactionNumber";

    /**
     *  text for end time
     */
    public static final String END_TIME = "benchmarkEndTime";
    
    /**
     *  text for the flag which means using multiple clients
     */
    public static final String MULTI_CLIENT = "multi-client";

    /**
     *  set of option name
     */
    public static final Set optionSet = new HashSet();

    /**
     *  mapping table for short option name and long option name
     */
    public static final Map optionTable = new HashMap(); 
    
    static {
        optionSet.add(THREAD_NUMBER);
        optionSet.add(REPEAT_NUMBER);
        optionSet.add(TX_NUMBER);
        optionSet.add(END_TIME);
        optionSet.add(MULTI_CLIENT);
        
        optionTable.put("r", REPEAT_NUMBER);
        optionTable.put("t", THREAD_NUMBER);
        optionTable.put("T", TX_NUMBER);
        optionTable.put("e", END_TIME);
    }
    
    /**
     *  Gets the benchmark manager instance.
     * 
     *  @return benchmark manager instance
     */
    public static BenchmarkManager getManager() {
        return manager;
    }
    
    /**
     *  Sets the benchmark manager instance.
     * 
     *  @param manager benchmark manager instance
     */
    public static void setManager(BenchmarkManager manager) {
        BenchmarkMain.manager = manager;
    }
    
    /**
     *  Starts the benchmark. <br><br>
     *  
     *  <br>
     *    [number of containers(threads)]<br>
     *  　　-t20　　or　　--threadNumber=20<br>
     *    [number of iteration for each container]<br>
     *  　　-r10　　or　　--repeatNumber=10<br>
     *  　[number of all benchmark transaction]<br>
     *  　　-T20　　or　　--transactionNumber=20<br>
     *    [number of benchmark end time (second)]<br>
     *  　　-e10　　or　　--benchmarkEndTime=10<br>
     *    [name for using multiple clients]<br>
     *  　　--multi-clients=Primary_node<br>
     *  　[benchmark component name]<br>
     *  　　benchmark_name<br>
     *  <br><br>
     *  
     *  example:<br>
     *  　java BenchmarkMain -t30 -r10 sample-xsql-benchmark
     * 
     *  @param args command line arguments
     *  @throws Exception
     */
    public static void main(String[] args) throws Exception {
        String benchmarkName = null;
        Map optionMap = null;
        try {
            if (args != null && args.length > 0) {
                for (int i = 0; i < args.length; i++){
                    if (args[i].startsWith("-")){
                        if (optionMap == null) {
                            optionMap = new HashMap();
                        }
                        editOptionMap(args[i], optionMap);
                    } else {
                        benchmarkName = args[i];
                    }
                }
                if (manager == null) {
                    manager = new BenchmarkManager(benchmarkName);
                }
                
                if (benchmarkName != null) {
                    manager.setOptionMap(optionMap);
                    manager.start();
                } else {
                    printUsage();
                }
            } else {
                printUsage();
            }
        } catch (IllegalArgumentException ex) {
            printUsage();
        }
    }
    
    /**
     *  validates the option data and then puts them into map.
     * 
     *  @param option command line argument
     *  @param optionMap option map
     */
    private static void editOptionMap(String option, Map optionMap)
            throws IllegalArgumentException {
        String optionName = null;
        String optionValue = null;
        int equalIndex = option.indexOf('=');
        
        if (option.startsWith("--")) {
            if (equalIndex >= 0) {
                optionName = option.substring(2, equalIndex);
                optionValue = option.substring(equalIndex + 1);
                equalIndex = optionValue.indexOf("=");
            } else {
                optionName = option.substring(2);
            }
            if (optionSet.contains(optionName)) {
                if (equalIndex > 0) {
                    // --LongOptionName=OptionName2=OptionValue
                    Map optionValueMap = new HashMap();
                    optionValueMap.put(optionValue.substring(0, equalIndex),
                            optionValue.substring(equalIndex));
                    
                    optionMap.put(optionName, optionValueMap);
                } else {
                    // --LongOptionName=OptionValue
                    optionMap.put(optionName, optionValue);
                }
            } else {
                throw new IllegalArgumentException();
            }
        } else {
            // first letter must be "-"
            if (optionTable.containsKey(option.substring(1, 2))) {
                optionName = (String) (optionTable.get(option.substring(1, 2)));
                
                optionValue = option.substring(2);
                equalIndex = optionValue.indexOf("=");
                if (equalIndex > 0) {
                    // -ShortOptionNameOptionName2=OptionValue
                    Map optionValueMap = new HashMap();
                    optionValueMap.put(optionValue.substring(0, equalIndex),
                            optionValue.substring(equalIndex));
                    
                    optionMap.put(optionName, optionValueMap);
                } else {
                    // -ShortOptionNameOptionValue
                    optionMap.put(optionName, optionValue);
                }
            } else {
                throw new IllegalArgumentException();
            }
        }
    }
    
    /**
     *  Returns a usage message
     * 
     *  @return usage message
     */
    public static String getUsage() {
        return MessageResources.getMessage("BenchmarkMain.usage");
    }
    
    /**
     *  Displays a usage message.
     */
    private static void printUsage() {
        System.out.print(getUsage());
    }
}
