ss: History trees can define their own node types
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core / src / org / eclipse / tracecompass / internal / statesystem / core / backend / InMemoryBackend.java
CommitLineData
f9a76cac 1/*******************************************************************************
ed48dc75 2 * Copyright (c) 2013, 2016 Ericsson
f9a76cac
AM
3 *
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
8 *
9 * Contributors:
10 * Alexandre Montplaisir - Initial API and implementation
f606c6fa 11 * Matthew Khouzam - Modified to use a TreeSet
e13bd4cd 12 * Patrick Tasse - Add message to exceptions
f9a76cac
AM
13 ******************************************************************************/
14
0306a843 15package org.eclipse.tracecompass.internal.statesystem.core.backend;
f9a76cac
AM
16
17import java.io.File;
18import java.io.FileInputStream;
f9a76cac 19import java.util.Comparator;
f606c6fa 20import java.util.Iterator;
f9a76cac 21import java.util.List;
866b9976 22import java.util.NavigableSet;
f606c6fa
MK
23import java.util.SortedSet;
24import java.util.TreeSet;
f9a76cac 25
b2f62cb5 26import org.eclipse.jdt.annotation.NonNull;
0306a843 27import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
e894a508
AM
28import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
29import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
30import org.eclipse.tracecompass.statesystem.core.interval.TmfStateInterval;
31import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
aa353506 32import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
f9a76cac
AM
33
34/**
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
38 * most cases.
39 *
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
42 * intervals.
43 *
44 * @author Alexandre Montplaisir
45 */
46public class InMemoryBackend implements IStateHistoryBackend {
47
f606c6fa
MK
48 /**
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.
52 */
cb42195c 53 private static final Comparator<ITmfStateInterval> END_COMPARATOR =
f606c6fa
MK
54 new Comparator<ITmfStateInterval>() {
55 @Override
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();
61 if (e1 < e2) {
62 return -1;
63 } else if (e1 > e2) {
64 return 1;
65 } else if (a1 < a2) {
66 return -1;
67 } else if (a1 > a2) {
68 return 1;
69 } else {
70 return 0;
71 }
72 }
f9a76cac 73
f606c6fa
MK
74 };
75
b2f62cb5 76 private final @NonNull String ssid;
866b9976 77 private final NavigableSet<ITmfStateInterval> intervals;
f9a76cac 78 private final long startTime;
b2f62cb5 79
eaf12e04 80 private volatile long latestTime;
f9a76cac
AM
81
82 /**
83 * Constructor
84 *
b2f62cb5
AM
85 * @param ssid
86 * The state system's ID
f9a76cac
AM
87 * @param startTime
88 * The start time of this interval store
89 */
b2f62cb5
AM
90 public InMemoryBackend(@NonNull String ssid, long startTime) {
91 this.ssid = ssid;
f9a76cac
AM
92 this.startTime = startTime;
93 this.latestTime = startTime;
a4524c1b 94 this.intervals = new TreeSet<>(END_COMPARATOR);
f9a76cac
AM
95 }
96
b2f62cb5
AM
97 @Override
98 public String getSSID() {
99 return ssid;
100 }
101
f9a76cac
AM
102 @Override
103 public long getStartTime() {
104 return startTime;
105 }
106
107 @Override
108 public long getEndTime() {
109 return latestTime;
110 }
111
112 @Override
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) {
e13bd4cd 117 throw new TimeRangeException(ssid + " Interval Start:" + stateStartTime + ", Interval End:" + stateEndTime + ", Backend Start:" + startTime); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
f9a76cac
AM
118 }
119
120 ITmfStateInterval interval = new TmfStateInterval(stateStartTime, stateEndTime, quark, value);
121
eaf12e04
AM
122 /* Add the interval into the tree */
123 synchronized (intervals) {
124 intervals.add(interval);
125 }
126
f9a76cac
AM
127 /* Update the "latest seen time" */
128 if (stateEndTime > latestTime) {
129 latestTime = stateEndTime;
130 }
f9a76cac
AM
131 }
132
f9a76cac
AM
133 @Override
134 public void doQuery(List<ITmfStateInterval> currentStateInfo, long t)
135 throws TimeRangeException {
136 if (!checkValidTime(t)) {
e13bd4cd 137 throw new TimeRangeException(ssid + " Time:" + t + ", Start:" + startTime + ", End:" + latestTime); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
f9a76cac
AM
138 }
139
140 /*
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.
143 */
eaf12e04 144 synchronized (intervals) {
866b9976 145 Iterator<ITmfStateInterval> iter = searchforEndTime(intervals, t);
eaf12e04
AM
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);
152 modCount++;
153 }
f9a76cac
AM
154 }
155 }
156 }
157
158 @Override
159 public ITmfStateInterval doSingularQuery(long t, int attributeQuark)
ed48dc75 160 throws TimeRangeException {
f9a76cac 161 if (!checkValidTime(t)) {
e13bd4cd 162 throw new TimeRangeException(ssid + " Time:" + t + ", Start:" + startTime + ", End:" + latestTime); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
f9a76cac
AM
163 }
164
165 /*
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.
168 */
eaf12e04 169 synchronized (intervals) {
866b9976 170 Iterator<ITmfStateInterval> iter = searchforEndTime(intervals, t);
eaf12e04
AM
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 */
178 return entry;
179 }
f9a76cac 180 }
f606c6fa 181 }
f9a76cac 182 }
ed48dc75 183 return null;
f9a76cac
AM
184 }
185
0d26a9d0 186 private boolean checkValidTime(long t) {
f9a76cac
AM
187 if (t >= startTime && t <= latestTime) {
188 return true;
189 }
190 return false;
191 }
192
193 @Override
194 public void finishedBuilding(long endTime) throws TimeRangeException {
195 /* Nothing to do */
196 }
197
198 @Override
199 public FileInputStream supplyAttributeTreeReader() {
200 /* Saving to disk not supported */
201 return null;
202 }
203
204 @Override
205 public File supplyAttributeTreeWriterFile() {
206 /* Saving to disk not supported */
207 return null;
208 }
209
210 @Override
211 public long supplyAttributeTreeWriterFilePosition() {
212 /* Saving to disk not supported */
213 return -1;
214 }
215
216 @Override
217 public void removeFiles() {
218 /* Nothing to do */
219 }
220
221 @Override
222 public void dispose() {
223 /* Nothing to do */
224 }
225
866b9976 226 private static Iterator<ITmfStateInterval> searchforEndTime(NavigableSet<ITmfStateInterval> tree, long time) {
aa353506 227 ITmfStateInterval dummyInterval = new TmfStateInterval(-1, time, -1, TmfStateValue.nullValue());
f606c6fa
MK
228 ITmfStateInterval myInterval = tree.lower(dummyInterval);
229 if (myInterval == null) {
230 return tree.iterator();
f9a76cac 231 }
f606c6fa
MK
232 final SortedSet<ITmfStateInterval> tailSet = tree.tailSet(myInterval);
233 Iterator<ITmfStateInterval> retVal = tailSet.iterator();
234 retVal.next();
235 return retVal;
f9a76cac
AM
236 }
237
238}
This page took 0.096649 seconds and 5 git commands to generate.