Package edu.brown.workload

Source Code of edu.brown.workload.AbstractTraceElement

/***************************************************************************
*   Copyright (C) 2009 by H-Store Project                                 *
*   Brown University                                                      *
*   Massachusetts Institute of Technology                                 *
*   Yale University                                                       *
*                                                                         *
*   Permission is hereby granted, free of charge, to any person obtaining *
*   a copy of this software and associated documentation files (the       *
*   "Software"), to deal in the Software without restriction, including   *
*   without limitation the rights to use, copy, modify, merge, publish,   *
*   distribute, sublicense, and/or sell copies of the Software, and to    *
*   permit persons to whom the Software is furnished to do so, subject to *
*   the following conditions:                                             *
*                                                                         *
*   The above copyright notice and this permission notice shall be        *
*   included in all copies or substantial portions of the Software.       *
*                                                                         *
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
*   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
*   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
*   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
*   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
*   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
*   OTHER DEALINGS IN THE SOFTWARE.                                       *
***************************************************************************/
package edu.brown.workload;

import java.text.ParseException;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONStringer;
import org.voltdb.VoltTable;
import org.voltdb.VoltTableRow;
import org.voltdb.VoltType;
import org.voltdb.catalog.CatalogMap;
import org.voltdb.catalog.CatalogType;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Statement;
import org.voltdb.utils.VoltTypeUtil;

import edu.brown.catalog.CatalogUtil;

/**
*
* @author Andy Pavlo <pavlo@cs.brown.edu>
*
*/
public abstract class AbstractTraceElement<T extends CatalogType> implements JSONString, Cloneable {
    /** java.util.logging logger. */
    protected static final Logger LOG = Logger.getLogger(AbstractTraceElement.class);
   
    public enum Members {
        // Catalog Name
        NAME,
        // Start Time (relative to start of trace)
        START,
        // Stop Time (relative to start of trace)
        STOP,
        // Element Parameters
        PARAMS,
        // Aborted (true/false)
        ABORTED,
        // Output (optional)
        OUTPUT,
        // Weight (optional)
        WEIGHT,
    };
   
    protected Long start_timestamp;
    protected Long stop_timestamp;
    protected Object params[];
    protected String catalog_item_name;
    protected boolean aborted = false;
    protected Object output[][][];
    protected VoltType output_types[][];
    protected short weight = 1;
   
    public AbstractTraceElement() {
        // Nothing to do...
    }
   
    public AbstractTraceElement(String catalog_item_name, Object params[]) {
        this.params = params;
        this.catalog_item_name = catalog_item_name;
        this.start_timestamp = System.nanoTime();
        //this.stop_timestamp = -1l;
    }
   
    public AbstractTraceElement(T catalog_item, Object params[]) {
        this(catalog_item.getName(), params);
    }
   
    @Override
    public AbstractTraceElement<T> clone() {
        AbstractTraceElement<T> clone = this.cloneImpl();
        clone.start_timestamp = this.start_timestamp;
        clone.stop_timestamp = this.stop_timestamp;
        clone.aborted = this.aborted;
        clone.output = this.output;
        clone.output_types = this.output_types;
        clone.weight = this.weight;
        return (clone);
    }
   
    protected abstract <X> X cloneImpl();
   
    public void setWeight(int weight) {
        this.weight = (short)weight;
    }
    public void incrementWeight(int delta) {
        this.weight += delta;
    }
    public int getWeight() {
        return (this.weight);
    }
   
    @Override
    public String toString() {
        return (this.getClass().getSimpleName() + "[" + this.catalog_item_name + "]");
    }
   
    public void stop() {
        this.stop_timestamp = System.nanoTime();
    }
   
    public void abort() {
        this.stop();
        this.aborted = true;
    }
   
    public boolean isStopped() {
        return (this.stop_timestamp != null);
    }
   
    public boolean isAborted() {
        return (this.aborted);
    }
   
    public void setTimestamps(Long start, Long stop) {
        this.start_timestamp = start;
        this.stop_timestamp = stop;
    }
   
    /**
     * @return the start_timestamp
     */
    public Long getStartTimestamp() {
        return this.start_timestamp;
    }

    /**
     * @return the stop_timestamp
     */
    public Long getStopTimestamp() {
        return this.stop_timestamp;
    }
   
    public String getCatalogItemName() {
        return this.catalog_item_name;
    }
   
    public abstract T getCatalogItem(Database catalog_db);
   
    public Boolean getAborted() {
        return aborted;
    }
   
    /**
     * Get the number of parameters that this trace element has
     * @return
     */
    public int getParamCount() {
        return (this.params.length);
    }
   
    /**
     * Get the parameters object array for this trace element
     * @return
     */
    public Object[] getParams() {
        return this.params;
    }

    /**
     * @return the params
     */
    @SuppressWarnings("unchecked")
    public <U> U getParam(int i) {
        return (U)this.params[i];
    }
   
    public void setParam(int i, Object value) {
        this.params[i] = value;
    }
   
    public boolean hasOutput() {
        return (this.output != null);
    }
    public void setOutput(Object[][]...output) {
        if (output == null || output.length == 0) return;
        this.output = output;
       
        // Build Output Types
        this.output_types = new VoltType[this.output.length][];
        for (int i = 0; i < this.output.length; i++) {
            Object data[][] = this.output[i];
            if (data == null) continue;
            Integer missing = null;
            for (int j = 0; j < data.length; j++) {
                Object row[] = data[j];
                if (row == null) continue;
                if (missing == null) {
                    missing = row.length;
                    this.output_types[i] = new VoltType[row.length];
                }
                assert(missing != null);
                for (int k = 0; k < row.length; k++) {
                    if (this.output_types[i][k] != null) continue;
                    Object val = row[k];
                    if (val == null) continue;
                    this.output_types[i][k] = VoltType.typeFromClass(val.getClass());
                    missing--;
                } // FOR (columns)
                if (missing == 0) break;
            } // FOR (rows)
        } // FOR
    }
    public void setOutput(VoltTable...output) {
        if (output == null || output.length == 0) return;
        this.output = new Object[output.length][][];
       
        this.output_types = new VoltType[output.length][];
        for (int i = 0; i < this.output.length; i++) {
            VoltTable vt = output[i];
            if (vt == null) continue;
           
            // TYPES
            this.output_types[i] = new VoltType[vt.getColumnCount()];
            for (int k = 0; k < this.output_types[i].length; k++) {
                this.output_types[i][k] = vt.getColumnType(k);
            } // FOR
           
            // DATA
            this.output[i] = new Object[vt.getRowCount()][vt.getColumnCount()];
            int j = 0;
            while (vt.advanceRow()) {
                VoltTableRow row = vt.getRow();
                for (int k = 0; k < this.output[i][j].length; k++) {
                    this.output[i][j][k] = row.get(k);
                } // FOR (columns)
                j++;
            } // WHILE (rows)
        } // FOR (tables)
    }
       
    public Object[][][] getOutput() {
        return (this.output);
    }
    public Object[][] getOutput(int idx) {
        return (this.output[idx]);
    }
    public VoltType[] getOutputTypes(int idx) {
        return (this.output_types[idx]);
    }

   
    /**
     *
     * @param catalog_db
     * @return
     */
    public abstract String debug(Database catalog_db);

    @Override
    public String toJSONString() {
        assert(false);
        // Can't be implemented since we always need to have a Database catalog object
        return null;
    }
   
    public String toJSONString(Database catalog_db) {
        JSONStringer stringer = new JSONStringer();
        try {
            stringer.object();
            this.toJSONString(stringer, catalog_db);
            stringer.endObject();
        } catch (JSONException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        return stringer.toString();
    }
   
    public void toJSONString(JSONStringer stringer, Database catalog_db) throws JSONException {
        stringer.key(Members.NAME.name()).value(this.catalog_item_name);
        stringer.key(Members.START.name()).value(this.start_timestamp);
        stringer.key(Members.STOP.name()).value(this.stop_timestamp);
        stringer.key(Members.ABORTED.name()).value(this.aborted);
       
        // WEIGHT
        if (this.weight > 1) {
            stringer.key(Members.WEIGHT.name()).value(this.weight);
        }
         
        // Output Tables
        stringer.key(Members.OUTPUT.name()).array();
        if (this.output != null) {
            for (int i = 0; i < this.output.length; i++) {
                stringer.object();
               
                // COLUMN TYPES
                stringer.key("TYPES").array();
                VoltType types[] = this.output_types[i];
                if (types != null) {
                    for (int j = 0; j < types.length; j++) {
                        stringer.value((types[j] == null ? VoltType.NULL : types[j]).name());
                    } // FOR
                }
                stringer.endArray();
               
                // DATA
                stringer.key("DATA").array();
                Object data[][] = this.output[i];
                if (data != null) {
                    for (int j = 0; j < data.length; j++) {
                        Object row[] = data[j];
                        stringer.array();
                        for (int k = 0; k < row.length; k++) {
                            stringer.value(data[j][k]);
                        } // FOR
                        stringer.endArray();
                    } // FOR
                }
                stringer.endArray();
               
                stringer.endObject();
            } // FOR
        }
        stringer.endArray();
       
        // This doesn't work because CatalogType doesn't have have we need
        //assert(this.catalog_item.getField("parameters") != null);
        //CatalogMap<CatalogType> param_map = (CatalogMap<CatalogType>)this.catalog_item.getField("parameters");
        CatalogMap<? extends CatalogType> param_map = null;
        T catalog_item = this.getCatalogItem(catalog_db);
        if (catalog_item instanceof Procedure) {
            param_map = (CatalogMap<? extends CatalogType>)((Procedure)catalog_item).getParameters();
        } else {
            param_map = (CatalogMap<? extends CatalogType>)((Statement)catalog_item).getParameters();
        }
        stringer.key(Members.PARAMS.name()).array();
        for (int i = 0; i < this.params.length; i++) {
            CatalogType catalog_param = param_map.get(i);
            Object param_isarray = catalog_param.getField("isarray");
            if (param_isarray != null && (Boolean)param_isarray) {
                stringer.array();
                Class<?> type = params[i].getClass();
                assert(type.isArray());
                Class<?> dataType = type.getComponentType();
               
                // I couldn't think of a better way to do this dynamically..
                // It's not trivial to go from primitive arrays to object arrays
                if (dataType == Long.TYPE) {
                    for (Object value : (long[])this.params[i]) {
                        stringer.value(value);
                    } // FOR
                } else if (dataType == Integer.TYPE) {
                    for (Object value : (int[])this.params[i]) {
                        stringer.value(value);
                    } // FOR
                } else if (dataType == Short.TYPE) {
                    for (Object value : (short[])this.params[i]) {
                        stringer.value(value);
                    } // FOR
                } else if (dataType == Byte.TYPE) {
                    for (Object value : (byte[])this.params[i]) {
                        stringer.value(value);
                    } // FOR
                } else {
                    for (Object value : (Object[])this.params[i]) {
                        stringer.value(value);
                    } // FOR
                }
                stringer.endArray();
            } else {
                stringer.value(this.params[i]);
            }
        } // FOR
        stringer.endArray();
    }
   
    protected <U extends CatalogType> void paramsFromJSONObject(JSONObject object, CatalogMap<U> catalog_params, String param_field) throws Exception {
        assert(catalog_params != null);
        final Thread self = Thread.currentThread();
        JSONArray jsonParams = object.getJSONArray(Members.PARAMS.name());
        int num_params = catalog_params.size();
        this.params = new Object[num_params];
        for (int i = 0; i < num_params; i++) {
            // If we ran out of JSON parameters, then just throw in null
            if (i > jsonParams.length()) {
                this.params[i] = null;
                continue;
            }
           
            U catalog_param = catalog_params.get(i);
            VoltType param_type = VoltType.get(((Integer)catalog_param.getField(param_field)).byteValue());
            // if (param_type == VoltType.TINYINT) param_type = VoltType.INTEGER;
            if (param_type == null) {
                throw new Exception("Parameter type is null for " + catalog_param);
            }
            // We don't know whether we have a StmtParameter or a ProcParameter
            Object _isarray = catalog_param.getField("isarray");
            boolean param_isarray = (_isarray != null && (Boolean)_isarray);
           
            // HACK: If parameter says its an array, but JSON disagrees, then just
            // treat it is as a String. The Volt guys started using byte arrays instead of
            // strings but didn't add a byte VoltType
            JSONArray jsonInner = null;
            if (param_isarray) {
                if (jsonParams.isNull(i)) {
                    this.params[i] = new Object[0];
                    continue;
                } else {
                    try {
                        jsonInner = jsonParams.getJSONArray(i);
                    } catch (JSONException ex) {
                        if (param_type == VoltType.TINYINT) {
                            param_isarray = false;
                            param_type = VoltType.STRING;
                        } else {
                            LOG.error("Failed to deserialize " + CatalogUtil.getDisplayName(catalog_param) + " [type=" + param_type + ", isarray=" + param_isarray + "]", ex);
                            throw ex;       
                        }
                    }
                }
            }
            if (param_isarray) {
                Object inner[] = new Object[jsonInner.length()];
                for (int j = 0; j < jsonInner.length(); j++) {
                    inner[j] = VoltTypeUtil.getObjectFromString(param_type, jsonInner.getString(j), self);
                    if (inner[j] == null) {
                        throw new RuntimeException("Array parameter " + j + " for " + catalog_param + " is null");
                    }
                } // FOR
                this.params[i] = VoltTypeUtil.getPrimitiveArray(param_type, inner);
            } else if (jsonParams.isNull(i)) {
                this.params[i] = null;
            } else {
                //System.err.println("[" + i + "] " + jsonParams.getString(i) + " (" + param_type + ")");
                try {
                    this.params[i] = VoltTypeUtil.getObjectFromString(param_type, jsonParams.getString(i), self);
                    if (this.params[i] == null) {
                        throw new Exception(catalog_param + " is null [" + param_type + "]");
                    }
                } catch (Exception ex) {
                    LOG.fatal("Failed to convert param '" + jsonParams.getString(i) + "' to " + param_type + " for " + catalog_param + " in " + CatalogUtil.getDisplayName(catalog_param.getParent()), ex);
                    throw ex;
                }
            }
        } // FOR
    }
   
    protected void fromJSONObject(JSONObject object, Database db) throws JSONException {
        this.start_timestamp = object.getLong(Members.START.name());
        if (!object.isNull(Members.STOP.name())) {
            this.stop_timestamp = object.getLong(Members.STOP.name());
        }
        this.catalog_item_name = object.getString(Members.NAME.name());
        this.aborted = object.getBoolean(Members.ABORTED.name());
       
        // WEIGHT
        if (object.has(Members.WEIGHT.name())) {
            this.weight = (short)object.getInt(Members.WEIGHT.name());
        }
       
        // OUTPUT
        JSONArray output_arr = null;
        try {
            output_arr = object.getJSONArray(Members.OUTPUT.name());
        } catch (JSONException ex) {
            // IGNORE
        }
        if (output_arr != null) {
            for (int i = 0, cnt = output_arr.length(); i < cnt; i++) {
                if (i == 0) {
                    this.output = new Object[cnt][][];
                    this.output_types = new VoltType[cnt][];
                }
                JSONObject inner = output_arr.getJSONObject(i);
                assert(inner != null);

                // TYPES
                JSONArray types_arr = inner.getJSONArray("TYPES");
                this.output_types[i] = new VoltType[types_arr.length()];
                for (int j = 0; j < this.output_types[i].length; j++) {
                    this.output_types[i][j] = VoltType.typeFromString(types_arr.getString(j));
                } // FOR
               
                // DATA
                JSONArray data_arr = inner.getJSONArray("DATA");
                this.output[i] = new Object[data_arr.length()][this.output_types[i].length];
                for (int j = 0; j < this.output[i].length; j++) {
                    JSONArray row_arr = data_arr.getJSONArray(j);
                    if (row_arr == null) continue;
                    for (int k = 0; k < this.output[i][j].length; k++) {
                        String val_str = row_arr.getString(k);
                        try {
                            this.output[i][j][k] = VoltTypeUtil.getObjectFromString(this.output_types[i][k], val_str);
                        } catch (ParseException ex) {
                            throw new RuntimeException(String.format("Failed to deserialize output %s [%d][%d][%d]", i, j, k));
                        }
                    } // FOR (columns)
                } // FOR (rows)
            } // FOR ( tables)
        }
    }
}
TOP

Related Classes of edu.brown.workload.AbstractTraceElement

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.