blob: b37cd1f2c30aca5a6fff1ac50c0be14060a41670 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2014 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Francois Chouinard - Initial API and implementation
* Francois Chouinard - Put in shape for 1.0
* Patrick Tasse - Updated for removal of context clone
*******************************************************************************/
package org.eclipse.tracecompass.internal.tmf.core.trace.experiment;
import java.util.Arrays;
import java.util.PriorityQueue;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
import org.eclipse.tracecompass.tmf.core.trace.TmfContext;
import com.google.common.annotations.VisibleForTesting;
/**
* The experiment context in TMF.
* <p>
* The experiment keeps track of the next event from each of its traces so it
* can pick the next one in chronological order.
* <p>
* This implies that the "next" event from each trace has already been read and
* that we at least know its timestamp.
* <p>
* The last trace refers to the trace from which the last event was "consumed"
* at the experiment level.
*/
public final class TmfExperimentContext extends TmfContext {
/**
* Inline class describing the contexts, containing the index of the trace
* in the experiment, its content and current event.
*/
public class ContextTuple implements Comparable<ContextTuple>{
private final int fIndex;
private final @NonNull ITmfEvent fEvent;
private final @NonNull ITmfContext fContext;
private ContextTuple(int index, @NonNull ITmfEvent event, @NonNull ITmfContext context) {
fIndex = index;
fEvent = event;
fContext = context;
}
/**
* Getter for the experiment index.
*
* @return this ContextTuple's index in the enclosing experiment.
*/
public int getIndex() {
return fIndex;
}
/**
* Getter for the current event
*
* @return this ContextTuple's current event
*/
public @NonNull ITmfEvent getEvent() {
return fEvent;
}
/**
* Getter for the context
*
* @return this ContextTuple's context field
*/
public @NonNull ITmfContext getContext() {
return fContext;
}
@Override
public int compareTo(ContextTuple o) {
int timeStampComparison = fEvent.getTimestamp().compareTo(o.fEvent.getTimestamp());
if (timeStampComparison != 0) {
return timeStampComparison;
}
/**
* if two context tuple's events have the same timestamp, compare
* their index in the context to resolve indetermination.
*/
return Integer.compare(fIndex, o.fIndex);
}
}
// ------------------------------------------------------------------------
// Attributes
// ------------------------------------------------------------------------
private final ITmfContext[] fContexts;
/**
* fPriority is a PriorityQueue of initial capacity fContexts.length,
* ordered by increasing timestamps of the ContextTuple events.
*/
private final PriorityQueue<ContextTuple> fPriority;
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
/**
* Standard constructor
*
* @param nbTraces
* The number of traces in the experiment
*/
public TmfExperimentContext(int nbTraces) {
super();
if (nbTraces < 0) {
throw new IllegalArgumentException("TmfExperimentContext size cannot be negative"); //$NON-NLS-1$
}
fContexts = new ITmfContext[nbTraces];
fPriority = new PriorityQueue<>(Math.max(1, nbTraces), null);
}
@Override
public void dispose() {
for (ITmfContext context : fContexts) {
context.dispose();
}
super.dispose();
}
// ------------------------------------------------------------------------
// Accessors
// ------------------------------------------------------------------------
/**
* Set the context and event of a trace
*
* @param traceIndex
* The index of the trace in the experiment
* @param ctx
* The new context object for that trace
* @param event
* The event at the context in the trace
*/
public void setContent(int traceIndex, ITmfContext ctx, ITmfEvent event) {
fContexts[traceIndex] = ctx;
if (event != null && ctx != null) {
fPriority.add(new ContextTuple(traceIndex, event, ctx));
}
}
/**
* Get the tuple containing the index, context and event of the for the
* trace with the earliest event, and the trace with the lowest index in the
* Experiment in case of indetermination.
*
* @return The information concerning the next trace in the context's
* priority queue.
*/
public ContextTuple getNext() {
return fPriority.poll();
}
/**
* Getter for the sub contexts of this experiment context.
*
* @return a copy of the array of contexts
*/
@VisibleForTesting
public ITmfContext[] getContexts() {
return Arrays.copyOf(fContexts, fContexts.length);
}
// ------------------------------------------------------------------------
// Object
// ------------------------------------------------------------------------
@Override
public int hashCode() {
return Arrays.hashCode(fContexts);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!super.equals(other)) {
return false;
}
if (!(other instanceof TmfExperimentContext)) {
return false;
}
TmfExperimentContext o = (TmfExperimentContext) other;
return Arrays.equals(fContexts, o.fContexts);
}
@Override
@SuppressWarnings("nls")
public String toString() {
StringBuilder sb = new StringBuilder("TmfExperimentContext [\n");
sb.append("\tfLocation=" + getLocation() + ", fRank=" + getRank() + "\n");
sb.append("\tfContexts=[");
for (int i = 0; i < fContexts.length; i++) {
sb.append("(" + fContexts[i].getLocation() + "," + fContexts[i].getRank() + ((i < fContexts.length - 1) ? ")," : ")]\n"));
}
sb.append("]");
return sb.toString();
}
}