1 /*******************************************************************************
2 * Copyright (c) 2013, 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Alexandre Montplaisir - Initial API and implementation
11 * Matthew Khouzam - Modified to use a TreeSet
12 * Patrick Tasse - Add message to exceptions
13 ******************************************************************************/
15 package org
.eclipse
.tracecompass
.internal
.statesystem
.core
.backend
;
18 import java
.io
.FileInputStream
;
19 import java
.util
.Comparator
;
20 import java
.util
.Iterator
;
21 import java
.util
.List
;
22 import java
.util
.NavigableSet
;
23 import java
.util
.SortedSet
;
24 import java
.util
.TreeSet
;
26 import org
.eclipse
.jdt
.annotation
.NonNull
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.backend
.IStateHistoryBackend
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
30 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.TmfStateInterval
;
31 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
32 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
35 * State history back-end that stores its intervals in RAM only. It cannot be
36 * saved to disk, which means we need to rebuild it every time we re-open a
37 * trace. But it's relatively quick to build, so this shouldn't be a problem in
40 * This should only be used with very small state histories (and/or, very small
41 * traces). Since it's stored in standard Collections, it's limited to 2^31
44 * @author Alexandre Montplaisir
46 public class InMemoryBackend
implements IStateHistoryBackend
{
49 * We need to compare the end time and the attribute, because we can have 2
50 * intervals with the same end time (for different attributes). And TreeSet
51 * needs a unique "key" per element.
53 private static final Comparator
<ITmfStateInterval
> END_COMPARATOR
=
54 new Comparator
<ITmfStateInterval
>() {
56 public int compare(ITmfStateInterval o1
, ITmfStateInterval o2
) {
57 final long e1
= o1
.getEndTime();
58 final long e2
= o2
.getEndTime();
59 final int a1
= o1
.getAttribute();
60 final int a2
= o2
.getAttribute();
76 private final @NonNull String ssid
;
77 private final NavigableSet
<ITmfStateInterval
> intervals
;
78 private final long startTime
;
80 private volatile long latestTime
;
86 * The state system's ID
88 * The start time of this interval store
90 public InMemoryBackend(@NonNull String ssid
, long startTime
) {
92 this.startTime
= startTime
;
93 this.latestTime
= startTime
;
94 this.intervals
= new TreeSet
<>(END_COMPARATOR
);
98 public String
getSSID() {
103 public long getStartTime() {
108 public long getEndTime() {
113 public void insertPastState(long stateStartTime
, long stateEndTime
,
114 int quark
, ITmfStateValue value
) throws TimeRangeException
{
115 /* Make sure the passed start/end times make sense */
116 if (stateStartTime
> stateEndTime
|| stateStartTime
< startTime
) {
117 throw new TimeRangeException(ssid
+ " Interval Start:" + stateStartTime
+ ", Interval End:" + stateEndTime
+ ", Backend Start:" + startTime
); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
120 ITmfStateInterval interval
= new TmfStateInterval(stateStartTime
, stateEndTime
, quark
, value
);
122 /* Add the interval into the tree */
123 synchronized (intervals
) {
124 intervals
.add(interval
);
127 /* Update the "latest seen time" */
128 if (stateEndTime
> latestTime
) {
129 latestTime
= stateEndTime
;
134 public void doQuery(List
<ITmfStateInterval
> currentStateInfo
, long t
)
135 throws TimeRangeException
{
136 if (!checkValidTime(t
)) {
137 throw new TimeRangeException(ssid
+ " Time:" + t
+ ", Start:" + startTime
+ ", End:" + latestTime
); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
141 * The intervals are sorted by end time, so we can binary search to get
142 * the first possible interval, then only compare their start times.
144 synchronized (intervals
) {
145 Iterator
<ITmfStateInterval
> iter
= searchforEndTime(intervals
, t
);
146 for (int modCount
= 0; iter
.hasNext() && modCount
< currentStateInfo
.size();) {
147 ITmfStateInterval entry
= iter
.next();
148 final long entryStartTime
= entry
.getStartTime();
149 if (entryStartTime
<= t
) {
150 /* Add this interval to the returned values */
151 currentStateInfo
.set(entry
.getAttribute(), entry
);
159 public ITmfStateInterval
doSingularQuery(long t
, int attributeQuark
)
160 throws TimeRangeException
{
161 if (!checkValidTime(t
)) {
162 throw new TimeRangeException(ssid
+ " Time:" + t
+ ", Start:" + startTime
+ ", End:" + latestTime
); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
166 * The intervals are sorted by end time, so we can binary search to get
167 * the first possible interval, then only compare their start times.
169 synchronized (intervals
) {
170 Iterator
<ITmfStateInterval
> iter
= searchforEndTime(intervals
, t
);
171 while (iter
.hasNext()) {
172 ITmfStateInterval entry
= iter
.next();
173 final boolean attributeMatches
= (entry
.getAttribute() == attributeQuark
);
174 final long entryStartTime
= entry
.getStartTime();
175 if (attributeMatches
) {
176 if (entryStartTime
<= t
) {
177 /* This is the droid we are looking for */
186 private boolean checkValidTime(long t
) {
187 if (t
>= startTime
&& t
<= latestTime
) {
194 public void finishedBuilding(long endTime
) throws TimeRangeException
{
199 public FileInputStream
supplyAttributeTreeReader() {
200 /* Saving to disk not supported */
205 public File
supplyAttributeTreeWriterFile() {
206 /* Saving to disk not supported */
211 public long supplyAttributeTreeWriterFilePosition() {
212 /* Saving to disk not supported */
217 public void removeFiles() {
222 public void dispose() {
226 private static Iterator
<ITmfStateInterval
> searchforEndTime(NavigableSet
<ITmfStateInterval
> tree
, long time
) {
227 ITmfStateInterval dummyInterval
= new TmfStateInterval(-1, time
, -1, TmfStateValue
.nullValue());
228 ITmfStateInterval myInterval
= tree
.lower(dummyInterval
);
229 if (myInterval
== null) {
230 return tree
.iterator();
232 final SortedSet
<ITmfStateInterval
> tailSet
= tree
.tailSet(myInterval
);
233 Iterator
<ITmfStateInterval
> retVal
= tailSet
.iterator();