/***************************************************************************
* 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.statistics;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import org.apache.commons.collections15.map.ListOrderedMap;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;
import org.json.JSONStringer;
import org.voltdb.catalog.CatalogType;
import org.voltdb.catalog.Database;
import edu.brown.catalog.CatalogKey;
import edu.brown.utils.StringUtil;
import edu.brown.workload.TransactionTrace;
/**
* @author pavlo
* @param <T>
*/
public abstract class AbstractStatistics<T extends CatalogType> implements JSONString {
protected static final Logger LOG = Logger.getLogger(AbstractStatistics.class);
protected static final String DEBUG_SPACER = " ";
protected final String catalog_key;
protected boolean has_preprocessed = false;
/**
* Constructor
*
* @param catalog_key
*/
public AbstractStatistics(String catalog_key) {
this.catalog_key = catalog_key;
}
/**
* Constructor
*
* @param catalog_item
*/
public AbstractStatistics(T catalog_item) {
this.catalog_key = CatalogKey.createKey(catalog_item);
}
/**
* Returns the Catalog key of the stats object
*
* @return
*/
public final String getCatalogKey() {
return (this.catalog_key);
}
/**
* @param catalog_db
* @return
*/
public abstract T getCatalogItem(Database catalog_db);
/**
*
*/
public abstract void preprocess(Database catalog_db);
/**
* @param xact
* @throws Exception
*/
public abstract void process(Database catalog_db, TransactionTrace xact) throws Exception;
/**
* @throws Exception
*/
public abstract void postprocess(Database catalog_db) throws Exception;
/**
* Returns debugging information about this object
*
* @return
*/
public abstract String debug(Database catalog_db);
protected String debug(Database catalog_db, Enum<?> elements[]) {
Map<String, Object> m = new ListOrderedMap<String, Object>();
try {
Class<?> statsClass = this.getClass();
for (Enum<?> element : elements) {
Field field = statsClass.getDeclaredField(element.toString().toLowerCase());
Object value = field.get(this);
if (field.getClass().isAssignableFrom(SortedMap.class)) {
SortedMap<?, ?> orig_value = (SortedMap<?, ?>) value;
Map<String, Object> inner_m = new ListOrderedMap<String, Object>();
for (Object inner_key : orig_value.keySet()) {
Object inner_val = orig_value.get(inner_key);
if (inner_val instanceof AbstractStatistics<?>) {
inner_val = ((AbstractStatistics<?>) inner_val).debug(catalog_db);
}
inner_m.put(inner_key.toString(), inner_val);
} // FOR
value = StringUtil.formatMaps(inner_m);
}
m.put(element.toString(), value);
} // FOR
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
return (String.format("%s\n%s", this.getCatalogItem(catalog_db), StringUtil.prefix(StringUtil.formatMaps(m), DEBUG_SPACER)));
}
/**
*
*/
@Override
public String toJSONString() {
JSONStringer stringer = new JSONStringer();
try {
stringer.object();
this.toJSONString(stringer);
stringer.endObject();
} catch (JSONException e) {
e.printStackTrace();
System.exit(-1);
}
return stringer.toString();
}
/**
* @param stringer
* @throws JSONException
*/
public abstract void toJSONString(JSONStringer stringer) throws JSONException;
/**
* @param object
* @throws JSONException
*/
public abstract void fromJSONObject(JSONObject object, Database catalog_db) throws JSONException;
/**
* @param <T>
* @param map
* @param name
* @param stringer
* @throws JSONException
*/
protected <U> void writeMap(SortedMap<U, ?> map, String name, JSONStringer stringer) throws JSONException {
stringer.key(name).object();
for (U key : map.keySet()) {
String key_name = key.toString();
if (key instanceof CatalogType) {
key_name = ((CatalogType) key).getName();
}
stringer.key(key_name).value(map.get(key));
} // FOR
stringer.endObject();
}
/**
* Reads a stored mapped from the JSON object and populates the data
* structure
*
* @param <U>
* @param <V>
* @param map
* @param name
* @param key_map
* @param object
* @throws JSONException
*/
@SuppressWarnings("unchecked")
protected <U, V> void readMap(SortedMap<U, V> map, String name, Map<String, U> key_map, Class<?> value_class, JSONObject object) throws JSONException {
map.clear();
JSONObject jsonObject = object.getJSONObject(name);
Iterator<String> keys = jsonObject.keys();
boolean first = true;
while (keys.hasNext()) {
String key_name = keys.next();
U key_object = null;
V value = null;
if (value_class.equals(Long.class)) {
value = (V) new Long(jsonObject.getLong(key_name));
} else {
value = (V) jsonObject.get(key_name);
}
key_object = key_map.get(key_name);
if (key_object == null) {
LOG.warn("Failed to retrieve key object '" + key_name + "' for " + name);
if (LOG.isDebugEnabled() && first) {
LOG.warn(jsonObject.toString(2));
}
first = false;
continue;
}
map.put(key_object, value);
} // FOR
LOG.debug("Added " + map.size() + " values to " + name);
return;
}
}