/***************************************************************************
* Copyright (c) 2012-2013 VMware, Inc. All Rights Reserved.
* 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.
***************************************************************************/
package com.vmware.aurora.stats;
import java.util.concurrent.atomic.AtomicLong;
import com.vmware.vim.binding.vmodl.ManagedObjectReference;
/*
* To keep trace of causal relations between events,
* a STATS entry is contains a source stats type and a destination stats type.
* The source stats type defines the source or originator of the event.
* The destination stats type represents the resulting operation or request
* as a result of the source event.
* The IDs of the stats entry identifies other unique aspects.
*/
public class StatsEntry implements Comparable<StatsEntry> {
private final StatsType dest;
private final StatsType src;
private final String id;
private final int hashcode;
private volatile AtomicLong count; // current count
private long lastCount; // count obtained in the last interval
private int calcHashCode() {
final int prime = 31;
int result = 1;
result = prime * result + dest.hashCode();
result = prime * result + src.hashCode();
result = prime * result + id.hashCode();
return result;
}
private static final String objToString(Object o) {
if (o instanceof String) {
return (String)o;
} else if (o instanceof Enum<?>) {
return ((Enum<?>)o).toString();
} else if (o instanceof Class<?>) {
return ((Class<?>)o).getSimpleName();
} else if (o instanceof ManagedObjectReference) {
return ((ManagedObjectReference)o).getType();
} else {
return o.getClass().getSimpleName();
}
}
private static final String convertId(final Object[] objs) {
StringBuffer buf = new StringBuffer();
for (Object o : objs) {
buf.append('.').append(objToString(o));
}
return buf.toString();
}
/**
* @return a unique String representation of a STATS entry
*/
static final String getKey(final StatsType src, final StatsType dest,
final Object... objs) {
String srcName = ((src == null) ? StatsType.ROOT : src).name();
StringBuffer buf = new StringBuffer(srcName);
buf.append(dest.name()).append(convertId(objs));
return buf.toString();
}
StatsEntry(final StatsType src, final StatsType dest, final Object... objs) {
this.src = ((src == null) ? StatsType.ROOT : src);
this.dest = dest;
this.id = convertId(objs);
this.hashcode = calcHashCode();
this.count = new AtomicLong(1);
this.lastCount = 0;
}
final void inc() {
count.incrementAndGet();
}
final long getCount() {
return count.longValue();
}
/**
* Update the last count with new count.
* @param newCount
* @return the different from the last count.
*/
final long updateLastCount(long newCount) {
long diff = newCount - lastCount;
lastCount = newCount;
return diff;
}
final StatsType getSrc() {
return src;
}
final StatsType getDest() {
return dest;
}
@Override
public final int hashCode() {
return hashcode;
}
@Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof StatsEntry)) {
return false;
}
StatsEntry other = (StatsEntry) obj;
return (dest == other.dest &&
src == other.src &&
id.equals(other.id));
}
@Override
public final int compareTo(StatsEntry o) {
int val = dest.compareTo(o.dest);
if (val == 0) {
val = id.compareTo(o.id);
}
if (val == 0) {
val = src.compareTo(o.src);
}
return val;
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(dest.toString()).append(id)
.append('<').append(src.toString()).append('>');
return buf.toString();
}
}