blob: d9eef317c57df077cb8270172d6246437a1d5c8f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.callgraph;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.util.Comparator;
import java.util.Objects;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.incubator.analysis.core.model.IHostModel;
import org.eclipse.tracecompass.incubator.callstack.core.callgraph.SymbolAspect;
import org.eclipse.tracecompass.incubator.callstack.core.instrumented.ICalledFunction;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
import com.google.common.collect.Ordering;
/**
* Called Functuon common class, defines the start, end, depth, parent and
* children. Does not define the symbol
*
* @author Matthew Khouzam
* @author Sonia Farrah
*/
abstract class AbstractCalledFunction implements ICalledFunction {
static final Comparator<ISegment> COMPARATOR;
static {
/*
* checkNotNull() has to be called separately, or else it breaks the
* type inference.
*/
Comparator<ISegment> comp = Ordering.from(SegmentComparators.INTERVAL_START_COMPARATOR).compound(SegmentComparators.INTERVAL_END_COMPARATOR);
COMPARATOR = checkNotNull(comp);
}
/**
* Serial Version UID
*/
private static final long serialVersionUID = 7992199223906717340L;
protected final long fStart;
protected final long fEnd;
private final @Nullable ICalledFunction fParent;
protected long fSelfTime = 0;
private final int fProcessId;
private final int fThreadId;
private final transient IHostModel fModel;
private transient long fCpuTime = Long.MIN_VALUE;
public AbstractCalledFunction(long start, long end, int processId, int threadId, @Nullable ICalledFunction parent, IHostModel model) {
if (start > end) {
throw new IllegalArgumentException(Messages.TimeError + "[" + start + "," + end + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
fStart = start;
fEnd = end;
fParent = parent;
// It'll be modified once we add a child to it
fSelfTime = fEnd - fStart;
fProcessId = processId;
fThreadId = threadId;
if (parent instanceof AbstractCalledFunction) {
((AbstractCalledFunction) parent).addChild(this);
}
fModel = model;
}
@Override
public long getStart() {
return fStart;
}
@Override
public long getEnd() {
return fEnd;
}
@Override
public @Nullable ICalledFunction getParent() {
return fParent;
}
@Override
public String getName() {
return NonNullUtils.nullToEmptyString(SymbolAspect.SYMBOL_ASPECT.resolve(this));
}
/**
* Add the child to the segment's children, and subtract the child's
* duration to the duration of the segment so we can calculate its self
* time.
*
* @param child
* The child to add to the segment's children
*/
protected void addChild(ICalledFunction child) {
if (child.getParent() != this) {
throw new IllegalArgumentException("Child parent not the same as child being added to."); //$NON-NLS-1$
}
substractChildDuration(child.getEnd() - child.getStart());
}
/**
* Subtract the child's duration to the duration of the segment.
*
* @param childDuration
* The child's duration
*/
private void substractChildDuration(long childDuration) {
fSelfTime -= childDuration;
}
@Override
public long getSelfTime() {
return fSelfTime;
}
@Override
public long getCpuTime() {
long cpuTime = fCpuTime;
if (cpuTime == Long.MIN_VALUE) {
cpuTime = fModel.getCpuTime(fThreadId, fStart, fEnd);
fCpuTime = cpuTime;
}
return cpuTime;
}
@Override
public int getProcessId() {
return fProcessId;
}
@Override
public int getThreadId() {
return fThreadId;
}
@Override
public int compareTo(@Nullable ISegment o) {
if (o == null) {
throw new IllegalArgumentException();
}
return COMPARATOR.compare(this, o);
}
@Override
public String toString() {
return '[' + String.valueOf(fStart) + ", " + String.valueOf(fEnd) + ']' + " Duration: " + getLength() + ", Self Time: " + fSelfTime; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@Override
public int hashCode() {
return Objects.hash(fEnd, fParent, fSelfTime, fStart, getSymbol());
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
AbstractCalledFunction other = (AbstractCalledFunction) obj;
return (fEnd == other.fEnd &&
fSelfTime == other.fSelfTime &&
fStart == other.fStart &&
Objects.equals(fParent, other.getParent()) &&
Objects.equals(getSymbol(), other.getSymbol()));
}
}