Package com.sun.faban.driver.engine

Source Code of com.sun.faban.driver.engine.FlatMix$Selector

/* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.sun.com/cddl/cddl.html or
* install_dir/legal/LICENSE
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at install_dir/legal/LICENSE.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id$
*
* Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved
*/
package com.sun.faban.driver.engine;

import com.sun.faban.driver.ConfigurationException;
import com.sun.faban.driver.DefinitionException;
import com.sun.faban.driver.util.Random;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.util.HashMap;
import java.util.Iterator;
import java.lang.annotation.Annotation;

/**
* The implementation of the flat mix annotation.
*
* @author Akara Sucharitakul
*/
public class FlatMix extends Mix {

  private static final long serialVersionUID = 1L;

  double[] mix;

    /**
     * Initializes this mix according to the annotation.
     *
     * @param driverClass The driver class annotating this mix
     * @param a           The annotation
     * @throws DefinitionException If there is an error in the annotation
     */
  public void init(Class<?> driverClass, Annotation a)
            throws DefinitionException {
        com.sun.faban.driver.FlatMix flatMix =
                (com.sun.faban.driver.FlatMix) a;
        operations = BenchmarkDefinition.getOperations(driverClass,
                flatMix.operations());
        mix = flatMix.mix();
        deviation = flatMix.deviation();
        validate();
    }

    /**
     * Initializes the default FlatMix without an annotation.
     * @param driverClass The driver class in question
     * @throws DefinitionException
     */
    public void init(Class<?> driverClass) throws DefinitionException {
        operations = BenchmarkDefinition.getOperations(driverClass);
        mix = new double[operations.length];
        for (int i = 0; i < mix.length; i++) {
      mix[i] = 1d;
    }
        deviation = 2d; // Default allowed deviation is 2%
    }

    /**
     * Creates and returns a copy of this object.  The precise meaning
     * of "copy" may depend on the class of the object. The general
     * intent is that, for any object <tt>x</tt>, the expression:
     * <blockquote>
     * <pre>
     * x.clone() != x</pre></blockquote>
     * will be true, and that the expression:
     * <blockquote>
     * <pre>
     * x.clone().getClass() == x.getClass()</pre></blockquote>
     * will be <tt>true</tt>, but these are not absolute requirements.
     * While it is typically the case that:
     * <blockquote>
     * <pre>
     * x.clone().equals(x)</pre></blockquote>
     * will be <tt>true</tt>, this is not an absolute requirement.
     * <p/>
     * By convention, the returned object should be obtained by calling
     * <tt>super.clone</tt>.  If a class and all of its superclasses (except
     * <tt>Object</tt>) obey this convention, it will be the case that
     * <tt>x.clone().getClass() == x.getClass()</tt>.
     * <p/>
     * By convention, the object returned by this method should be independent
     * of this object (which is being cloned).  To achieve this independence,
     * it may be necessary to modify one or more fields of the object returned
     * by <tt>super.clone</tt> before returning it.  Typically, this means
     * copying any mutable objects that comprise the internal "deep structure"
     * of the object being cloned and replacing the references to these
     * objects with references to the copies.  If a class contains only
     * primitive fields or references to immutable objects, then it is usually
     * the case that no fields in the object returned by <tt>super.clone</tt>
     * need to be modified.
     * <p/>
     * The method <tt>clone</tt> for class <tt>Object</tt> performs a
     * specific cloning operation. First, if the class of this object does
     * not implement the interface <tt>Cloneable</tt>, then a
     * <tt>CloneNotSupportedException</tt> is thrown. Note that all arrays
     * are considered to implement the interface <tt>Cloneable</tt>.
     * Otherwise, this method creates a new instance of the class of this
     * object and initializes all its fields with exactly the contents of
     * the corresponding fields of this object, as if by assignment; the
     * contents of the fields are not themselves cloned. Thus, this method
     * performs a "shallow copy" of this object, not a "deep copy" operation.
     * <p/>
     * The class <tt>Object</tt> does not itself implement the interface
     * <tt>Cloneable</tt>, so calling the <tt>clone</tt> method on an object
     * whose class is <tt>Object</tt> will result in throwing an
     * exception at run time.
     *
     * @return a clone of this instance.
     * @see Cloneable
     */
    @Override
  public Object clone() {
        FlatMix clone = (FlatMix) super.clone();
        clone.mix = new double[mix.length];
        System.arraycopy(mix, 0, clone.mix, 0, mix.length);
        return clone;
    }

    /**
     * Configures the flat mix based on the ratios given in the
     * configuration file.
     * @param driverConfigNode The DOM node holding the driver config
     * @throws ConfigurationException   If the configuration is invalid
     *                                  for the mix
     */
  public void configure(Element driverConfigNode)
            throws ConfigurationException {
        /* The format is as follows:
        <operationMix>
            <name>operationF</name><r>40</r>
        </operationMix>
        <operationMix>
            <name>operationG</name><r>30</r>
        </operationMix>
        <operationMix>
            <name>operationH</name><r>30</r>
        </operationMix>
        */

        HashMap<String, Double> ratioMap =
                new HashMap<String, Double>(operations.length);
        NodeList operationList = driverConfigNode.
                getElementsByTagNameNS(RunInfo.DRIVERURI, "operationMix");
        int size0 = operationList.getLength();
        for (int i = 0; i < size0; i++) {
            Element opMix = (Element) operationList.item(i);
            NodeList nl = opMix.getElementsByTagNameNS(
                                                    RunInfo.DRIVERURI, "name");
            if (nl.getLength() > 1) {
                String msg = "Only one operation name allowed in each " +
                        "operation mix.";
                getLogger().severe(msg);
                ConfigurationException e = new ConfigurationException(msg);
                getLogger().throwing(className, "configure", e);
                throw e;
            }
            String name = nl.item(0).getFirstChild().getNodeValue();
            nl = opMix.getElementsByTagNameNS(RunInfo.DRIVERURI, "r");
            if (nl.getLength() > 1) {
                String msg = "Only one ratio allowed for @FlatMix";
                getLogger().severe(msg);
                ConfigurationException e = new ConfigurationException(msg);
                getLogger().throwing(className, "configure", e);
                throw e;
            }
            Double ratio = new Double(nl.item(0).getFirstChild().
                    getNodeValue());
            ratioMap.put(name, ratio);
        }

        if (ratioMap.size() <= 0) {
      return;
    }

        for (int i = 0; i < operations.length; i++) {
            Double value = ratioMap.remove(operations[i].name);
            if (value == null) {
                String msg = "Configured ratio for operation " +
                        operations[i].name + " not found";
                getLogger().severe(msg);
                ConfigurationException e = new ConfigurationException(msg);
                getLogger().throwing(className, "configure", e);
                throw e;
            }
            mix[i] = value.doubleValue();
        }

        // By now, the map should be empty
        if (ratioMap.size() > 0) {
            String msg = "";
            for (Iterator<String> i = ratioMap.keySet().iterator();
                 i.hasNext();) {
                if (msg.length() > 0) {
          msg += ", ";
        }
                msg += i.next();
            }
            msg = "Invalid operation name(s) in operationMix " +
                    "configuration: " + msg + '.';
            getLogger().severe(msg);
            ConfigurationException e = new ConfigurationException(msg);
            getLogger().throwing(className, "configure", e);
            throw e;
        }
    }

    /**
     * Validates the mix spec in the benchmark definitions to ensure all
     * the rows and columns are valid.
     * @throws DefinitionException Found missing or
     *                                                  invalid row/column
     */
    public void validate() throws DefinitionException {
        if (mix.length != operations.length) {
            String msg = "Mix ratios must be " + operations.length +
                    "(#ops) in size!\nFound " + mix.length + ".";
            getLogger().severe(msg);
            DefinitionException e = new DefinitionException(msg);
            getLogger().throwing(className, "validate", e);
            throw e;
        }
    }

    /**
     * Normalizes the mix so each row will have a sum of 1.0d. This is
     * important as we do not require the spec input to sum to this
     * amount but the selector (doMenu) will base the random number
     * generator to 1.
     */
  public void normalize() {
        // if (logger.isLoggable(Level.FINEST))
            getLogger().finest("normalize - before\n" + toString());

        double rowTotal = 0d;
        for (int i = 0; i < mix.length; i++) {
      rowTotal += mix[i];
    }
        for (int i = 0; i < mix.length; i++) {
      mix[i] /= rowTotal;
    }

        // if (logger.isLoggable(Level.FINEST))
            getLogger().finest("normalize - after\n" + toString());
    }

    /**
     * Returns the flat mix representation of this mix. This is used for
     * consistent reporting.
     *
     * @return The flat mix representation.
     */
  public FlatMix flatMix() {
        return this;
    }

    /**
     * Provides a string representation of this FlatMix.
     * @return The string representation
     * @see java.lang.Object#toString()
     */
    @Override
  public String toString() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("FlatMix\n");
        buffer.append("operations: ");
        buffer.append(operations[0].name);
        for (int i = 1; i < operations.length; i++) {
            buffer.append(", ");
            buffer.append(operations[i].name);
        }
        buffer.append("\nmix: ");
        buffer.append(mix[0]);
        for (int i = 1; i < mix.length; i++) {
            buffer.append(", ");
            buffer.append(mix[i]);
        }
        buffer.append("\ndeviation :");
        buffer.append(deviation);
        buffer.append('\n');

        return buffer.toString();
    }

    /**
     * Obtains the per-thread and per-driver instance selector.
     *
     * @param random The per-thread random value generator
     * @return The selector to be used by the driver
     */
  public Selector selector(Random random) {
        return new Selector(random, mix);
    }

    /**
     * The selector implementation for the FlatMix.
     */
    public static class Selector extends Mix.Selector {

        private Random random;
        private double[] selectMix;

        Selector(Random random, double[] mix) {
            this.random = random;
            selectMix = new double[mix.length];
            selectMix[0] = mix[0];
            for (int i = 1; i < selectMix.length; i++) {
                selectMix[i] = mix[i] + selectMix[i - 1];
            }
        }

        /**
         * The select method selects the operation to run next.
         *
         * @return The operation index selected to run next
         */
    public int select() {
            double val = random.drandom(0, 1);
            for (int i = 0; i < selectMix.length; i++) {
        if (val <= selectMix[i]) {
          return i;
        }
      }
            return -1;
        }

        /**
         * Resets the selector's state to start at the first op,
         * if applicable.
         */
    public void reset() {
            // Noop... there's nothing to reset in a flatmix as it does
            // not contain any state.
        }
    }
}
TOP

Related Classes of com.sun.faban.driver.engine.FlatMix$Selector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.