Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: d9eef317c57df077cb8270172d6246437a1d5c8f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*******************************************************************************
 * 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()));
    }

}

Back to the top