cdc.perfs.core.impl.AbstractContext Maven / Gradle / Ivy
package cdc.perfs.core.impl;
import java.util.ArrayList;
import java.util.List;
import cdc.perfs.core.Context;
import cdc.perfs.core.Measure;
import cdc.perfs.core.Position;
import cdc.util.time.TimeMeasureMode;
/**
* Base implementation of Context.
*
* @author Damien Carbonne
*
*/
public abstract class AbstractContext implements Context {
/**
* Environment to which this context is attached.
*/
final AbstractEnvironment environment;
/** Id of the context. */
private final int id;
/** Context name. */
private final String name;
/** List of root measures. */
final List roots = new ArrayList<>();
/** Number of measures in this context. */
private int measuresCount = 0;
void incrementMeasuresCount() {
measuresCount++;
environment.fireContextChanged(this);
}
protected AbstractContext(AbstractEnvironment environment,
int id,
String name) {
this.environment = environment;
this.id = id;
this.name = name;
}
@Override
public AbstractEnvironment getEnvironment() {
return environment;
}
@Override
public final int getId() {
return id;
}
@Override
public final String getName() {
return name;
}
@Override
public final int getRootMeasuresCount() {
return roots.size();
}
@Override
public final Measure getRootMeasure(int index) {
return roots.get(index);
}
@Override
public final Measure getMeasure(long time,
TimeMeasureMode mode,
long epsilon,
int depth) {
if (epsilon < 0) {
throw new IllegalArgumentException("Negative epsilon");
}
// Do all computations using absolute times
final long atime = environment.toAbsolute(time, mode);
// Lower time bound
final long inf = atime - epsilon;
// Higher time bound
final long sup = atime + epsilon;
final int index = getRootMeasureIndex(atime, TimeMeasureMode.ABSOLUTE, Position.EQUAL);
final Measure root;
if (index >= 0) {
// An exact matching root (level = 0) measure has been found
root = getRootMeasure(index);
} else {
// No exact matching root measure was found
// Try to use tolerance
final int first = getRootMeasureIndex(inf, TimeMeasureMode.ABSOLUTE, Position.GREATER_OR_EQUAL);
final int last = getRootMeasureIndex(sup, TimeMeasureMode.ABSOLUTE, Position.LESS_OR_EQUAL);
if (first <= last) {
// Choose the measure that is approximatively in the middle
// This may not be the best choice, but it should suffice
root = getRootMeasure((first + last) / 2);
} else {
root = null;
}
}
if (root == null) {
return null;
} else {
Measure sub = root.getFirstSubChild(depth, inf, sup);
if (sub == null) {
return null;
} else {
while (sub != null) {
if (sub.getAbsoluteBeginNanos() <= sup && sub.getAbsoluteEndOrCurrentNanos() >= inf) {
return sub;
}
sub = sub.getNextSibling();
}
return null;
}
}
}
@Override
public final int getRootMeasureIndex(long time,
TimeMeasureMode mode,
Position position) {
int low = 0;
int high = roots.size() - 1;
while (low <= high) {
final int mid = (low + high) >>> 1;
final AbstractMeasure measure = roots.get(mid);
final int compare = measure.compareToAbsolute(environment.toAbsolute(time, mode));
if (compare < 0) {
low = mid + 1;
} else if (compare > 0) {
high = mid - 1;
} else {
return mid; // Found a matching root
}
}
// No root was found
switch (position) {
case GREATER_OR_EQUAL:
return roots.isEmpty() ? -1 : low;
case LESS_OR_EQUAL:
return high;
case EQUAL:
default:
return -1;
}
}
@Override
public final int getMeasuresCount() {
return measuresCount;
}
@Override
public final long getMinRelativeBeginNanosOrCurrent() {
if (measuresCount > 0) {
return getRootMeasure(0).getRelativeBeginNanos();
} else {
return getEnvironment().getElapsedNanos();
}
}
@Override
public final long getMaxRelativeEndNanosOrCurrent() {
if (measuresCount > 0) {
final int rootIndex = roots.size() - 1;
final Measure measure = getRootMeasure(rootIndex);
return measure.getRelativeEndOrCurrentNanos();
} else {
return getEnvironment().getElapsedNanos();
}
}
@Override
public String toString() {
return getClass().getSimpleName() + "-" + getId();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy