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
.linuxtools
.internal
.tmf
.core
.statesystem
.backends
;
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
.linuxtools
.tmf
.core
.exceptions
.AttributeNotFoundException
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.ITmfStateInterval
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.interval
.TmfStateInterval
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.statevalue
.ITmfStateValue
;
32 * State history back-end that stores its intervals in RAM only. It cannot be
33 * saved to disk, which means we need to rebuild it every time we re-open a
34 * trace. But it's relatively quick to build, so this shouldn't be a problem in
37 * This should only be used with very small state histories (and/or, very small
38 * traces). Since it's stored in standard Collections, it's limited to 2^31
41 * @author Alexandre Montplaisir
43 public class InMemoryBackend
implements IStateHistoryBackend
{
46 * We need to compare the end time and the attribute, because we can have 2
47 * intervals with the same end time (for different attributes). And TreeSet
48 * needs a unique "key" per element.
50 private static final Comparator
<ITmfStateInterval
> END_COMPARATOR
=
51 new Comparator
<ITmfStateInterval
>() {
53 public int compare(ITmfStateInterval o1
, ITmfStateInterval o2
) {
54 final long e1
= o1
.getEndTime();
55 final long e2
= o2
.getEndTime();
56 final int a1
= o1
.getAttribute();
57 final int a2
= o2
.getAttribute();
73 private final TreeSet
<ITmfStateInterval
> intervals
;
74 private final long startTime
;
75 private volatile long latestTime
;
81 * The start time of this interval store
83 public InMemoryBackend(long startTime
) {
84 this.startTime
= startTime
;
85 this.latestTime
= startTime
;
86 this.intervals
= new TreeSet
<>(END_COMPARATOR
);
90 public long getStartTime() {
95 public long getEndTime() {
100 public void insertPastState(long stateStartTime
, long stateEndTime
,
101 int quark
, ITmfStateValue value
) throws TimeRangeException
{
102 /* Make sure the passed start/end times make sense */
103 if (stateStartTime
> stateEndTime
|| stateStartTime
< startTime
) {
104 throw new TimeRangeException();
107 ITmfStateInterval interval
= new TmfStateInterval(stateStartTime
, stateEndTime
, quark
, value
);
109 /* Add the interval into the tree */
110 synchronized (intervals
) {
111 intervals
.add(interval
);
114 /* Update the "latest seen time" */
115 if (stateEndTime
> latestTime
) {
116 latestTime
= stateEndTime
;
121 public void doQuery(List
<ITmfStateInterval
> currentStateInfo
, long t
)
122 throws TimeRangeException
{
123 if (!checkValidTime(t
)) {
124 throw new TimeRangeException();
128 * The intervals are sorted by end time, so we can binary search to get
129 * the first possible interval, then only compare their start times.
131 synchronized (intervals
) {
132 Iterator
<ITmfStateInterval
> iter
= serachforEndTime(intervals
, t
);
133 for (int modCount
= 0; iter
.hasNext() && modCount
< currentStateInfo
.size();) {
134 ITmfStateInterval entry
= iter
.next();
135 final long entryStartTime
= entry
.getStartTime();
136 if (entryStartTime
<= t
) {
137 /* Add this interval to the returned values */
138 currentStateInfo
.set(entry
.getAttribute(), entry
);
146 public ITmfStateInterval
doSingularQuery(long t
, int attributeQuark
)
147 throws TimeRangeException
, AttributeNotFoundException
{
148 if (!checkValidTime(t
)) {
149 throw new TimeRangeException();
153 * The intervals are sorted by end time, so we can binary search to get
154 * the first possible interval, then only compare their start times.
156 synchronized (intervals
) {
157 Iterator
<ITmfStateInterval
> iter
= serachforEndTime(intervals
, t
);
158 while (iter
.hasNext()) {
159 ITmfStateInterval entry
= iter
.next();
160 final boolean attributeMatches
= (entry
.getAttribute() == attributeQuark
);
161 final long entryStartTime
= entry
.getStartTime();
162 if (attributeMatches
) {
163 if (entryStartTime
<= t
) {
164 /* This is the droid we are looking for */
170 throw new AttributeNotFoundException();
174 public boolean checkValidTime(long t
) {
175 if (t
>= startTime
&& t
<= latestTime
) {
182 public void finishedBuilding(long endTime
) throws TimeRangeException
{
187 public FileInputStream
supplyAttributeTreeReader() {
188 /* Saving to disk not supported */
193 public File
supplyAttributeTreeWriterFile() {
194 /* Saving to disk not supported */
199 public long supplyAttributeTreeWriterFilePosition() {
200 /* Saving to disk not supported */
205 public void removeFiles() {
210 public void dispose() {
215 public void debugPrint(PrintWriter writer
) {
216 synchronized (intervals
) {
217 writer
.println(intervals
.toString());
221 private static Iterator
<ITmfStateInterval
> serachforEndTime(TreeSet
<ITmfStateInterval
> tree
, long time
) {
222 ITmfStateInterval dummyInterval
= new TmfStateInterval(-1, time
, -1, null);
223 ITmfStateInterval myInterval
= tree
.lower(dummyInterval
);
224 if (myInterval
== null) {
225 return tree
.iterator();
227 final SortedSet
<ITmfStateInterval
> tailSet
= tree
.tailSet(myInterval
);
228 Iterator
<ITmfStateInterval
> retVal
= tailSet
.iterator();