1 /*******************************************************************************
2 * Copyright (c) 2013, 2014 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 ******************************************************************************/
14 package org
.eclipse
.tracecompass
.statesystem
.core
.backend
;
17 import java
.io
.FileInputStream
;
18 import java
.io
.PrintWriter
;
19 import java
.util
.Comparator
;
20 import java
.util
.Iterator
;
21 import java
.util
.List
;
22 import java
.util
.SortedSet
;
23 import java
.util
.TreeSet
;
25 import org
.eclipse
.jdt
.annotation
.NonNull
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.TmfStateInterval
;
30 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
33 * State history back-end that stores its intervals in RAM only. It cannot be
34 * saved to disk, which means we need to rebuild it every time we re-open a
35 * trace. But it's relatively quick to build, so this shouldn't be a problem in
38 * This should only be used with very small state histories (and/or, very small
39 * traces). Since it's stored in standard Collections, it's limited to 2^31
42 * @author Alexandre Montplaisir
45 public class InMemoryBackend
implements IStateHistoryBackend
{
48 * We need to compare the end time and the attribute, because we can have 2
49 * intervals with the same end time (for different attributes). And TreeSet
50 * needs a unique "key" per element.
52 private static final Comparator
<ITmfStateInterval
> END_COMPARATOR
=
53 new Comparator
<ITmfStateInterval
>() {
55 public int compare(ITmfStateInterval o1
, ITmfStateInterval o2
) {
56 final long e1
= o1
.getEndTime();
57 final long e2
= o2
.getEndTime();
58 final int a1
= o1
.getAttribute();
59 final int a2
= o2
.getAttribute();
75 private final @NonNull String ssid
;
76 private final TreeSet
<ITmfStateInterval
> intervals
;
77 private final long startTime
;
79 private volatile long latestTime
;
85 * The state system's ID
87 * The start time of this interval store
89 public InMemoryBackend(@NonNull String ssid
, long startTime
) {
91 this.startTime
= startTime
;
92 this.latestTime
= startTime
;
93 this.intervals
= new TreeSet
<>(END_COMPARATOR
);
97 public String
getSSID() {
102 public long getStartTime() {
107 public long getEndTime() {
112 public void insertPastState(long stateStartTime
, long stateEndTime
,
113 int quark
, ITmfStateValue value
) throws TimeRangeException
{
114 /* Make sure the passed start/end times make sense */
115 if (stateStartTime
> stateEndTime
|| stateStartTime
< startTime
) {
116 throw new TimeRangeException();
119 ITmfStateInterval interval
= new TmfStateInterval(stateStartTime
, stateEndTime
, quark
, value
);
121 /* Add the interval into the tree */
122 synchronized (intervals
) {
123 intervals
.add(interval
);
126 /* Update the "latest seen time" */
127 if (stateEndTime
> latestTime
) {
128 latestTime
= stateEndTime
;
133 public void doQuery(List
<ITmfStateInterval
> currentStateInfo
, long t
)
134 throws TimeRangeException
{
135 if (!checkValidTime(t
)) {
136 throw new TimeRangeException();
140 * The intervals are sorted by end time, so we can binary search to get
141 * the first possible interval, then only compare their start times.
143 synchronized (intervals
) {
144 Iterator
<ITmfStateInterval
> iter
= serachforEndTime(intervals
, t
);
145 for (int modCount
= 0; iter
.hasNext() && modCount
< currentStateInfo
.size();) {
146 ITmfStateInterval entry
= iter
.next();
147 final long entryStartTime
= entry
.getStartTime();
148 if (entryStartTime
<= t
) {
149 /* Add this interval to the returned values */
150 currentStateInfo
.set(entry
.getAttribute(), entry
);
158 public ITmfStateInterval
doSingularQuery(long t
, int attributeQuark
)
159 throws TimeRangeException
, AttributeNotFoundException
{
160 if (!checkValidTime(t
)) {
161 throw new TimeRangeException();
165 * The intervals are sorted by end time, so we can binary search to get
166 * the first possible interval, then only compare their start times.
168 synchronized (intervals
) {
169 Iterator
<ITmfStateInterval
> iter
= serachforEndTime(intervals
, t
);
170 while (iter
.hasNext()) {
171 ITmfStateInterval entry
= iter
.next();
172 final boolean attributeMatches
= (entry
.getAttribute() == attributeQuark
);
173 final long entryStartTime
= entry
.getStartTime();
174 if (attributeMatches
) {
175 if (entryStartTime
<= t
) {
176 /* This is the droid we are looking for */
182 throw new AttributeNotFoundException();
185 private boolean checkValidTime(long t
) {
186 if (t
>= startTime
&& t
<= latestTime
) {
193 public void finishedBuilding(long endTime
) throws TimeRangeException
{
198 public FileInputStream
supplyAttributeTreeReader() {
199 /* Saving to disk not supported */
204 public File
supplyAttributeTreeWriterFile() {
205 /* Saving to disk not supported */
210 public long supplyAttributeTreeWriterFilePosition() {
211 /* Saving to disk not supported */
216 public void removeFiles() {
221 public void dispose() {
226 public void debugPrint(PrintWriter writer
) {
227 synchronized (intervals
) {
228 writer
.println(intervals
.toString());
232 private static Iterator
<ITmfStateInterval
> serachforEndTime(TreeSet
<ITmfStateInterval
> tree
, long time
) {
233 ITmfStateInterval dummyInterval
= new TmfStateInterval(-1, time
, -1, null);
234 ITmfStateInterval myInterval
= tree
.lower(dummyInterval
);
235 if (myInterval
== null) {
236 return tree
.iterator();
238 final SortedSet
<ITmfStateInterval
> tailSet
= tree
.tailSet(myInterval
);
239 Iterator
<ITmfStateInterval
> retVal
= tailSet
.iterator();