1
/*******************************************************************************
2
* Copyright (c) 2012 Ericsson
3
* Copyright (c) 2010, 2011 École Polytechnique de Montréal
4
* Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
6
* All rights reserved. This program and the accompanying materials are
7
* made available under the terms of the Eclipse Public License v1.0 which
8
* accompanies this distribution, and is available at
9
* http://www.eclipse.org/legal/epl-v10.html
11
*******************************************************************************/
13
package org.eclipse.linuxtools.internal.tmf.core.statesystem;
16
import java.io.IOException;
17
import java.io.PrintWriter;
18
import java.util.ArrayList;
19
import java.util.List;
21
import org.eclipse.linuxtools.internal.tmf.core.Tracer;
22
import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
23
import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
24
import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
25
import org.eclipse.linuxtools.tmf.core.interval.TmfStateInterval;
26
import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemBuilder;
27
import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
30
* This is the extension of the StateSystem, which will save the state intervals
31
* that are created from the transient state (instead of discarding them, like a
32
* simple StateSystem would do).
34
* This allows the user to then run queries at past timestamps.
36
* DON'T FORGET to call .closeHistory() when you are done inserting intervals,
37
* or the storage backend will have no way of knowing it can close and write
38
* itself to disk, and its thread will keep running.
43
public class StateHistorySystem extends StateSystem implements
47
* In addition, a state "history" system has a storage back-end from which
48
* it can restore past states.
50
private final IStateHistoryBackend backend;
56
* The "state history storage" backend to use.
58
* Put true if this is a new history started from scratch. It is
59
* used to tell the state system where to get its attribute tree.
61
* If there was a problem creating the new history file
63
public StateHistorySystem(IStateHistoryBackend backend, boolean newFile)
65
this.backend = backend;
66
transState = new TransientState(backend);
69
attributeTree = new AttributeTree(this);
71
/* We're opening an existing file */
72
this.attributeTree = new AttributeTree(this, backend.supplyAttributeTreeReader());
73
transState.setInactive();
78
public long getStartTime() {
79
return backend.getStartTime();
83
public long getCurrentEndTime() {
84
return backend.getEndTime();
88
public void closeHistory(long endTime) throws TimeRangeException {
89
File attributeTreeFile;
90
long attributeTreeFilePos;
91
long realEndTime = endTime;
93
if (realEndTime < backend.getEndTime()) {
95
* This can happen (empty nodes pushing the border further, etc.)
96
* but shouldn't be too big of a deal.
98
realEndTime = backend.getEndTime();
100
transState.closeTransientState(realEndTime);
101
backend.finishedBuilding(realEndTime);
103
attributeTreeFile = backend.supplyAttributeTreeWriterFile();
104
attributeTreeFilePos = backend.supplyAttributeTreeWriterFilePosition();
105
if (attributeTreeFile != null) {
107
* If null was returned, we simply won't save the attribute tree,
110
attributeTree.writeSelf(attributeTreeFile, attributeTreeFilePos);
115
* @name External query methods
119
public synchronized List<ITmfStateInterval> queryFullState(long t)
120
throws TimeRangeException {
121
List<ITmfStateInterval> stateInfo = new ArrayList<ITmfStateInterval>(
122
attributeTree.getNbAttributes());
124
/* Bring the size of the array to the current number of attributes */
125
for (int i = 0; i < attributeTree.getNbAttributes(); i++) {
129
/* Query the storage backend */
130
backend.doQuery(stateInfo, t);
133
* If we are currently building the history, also query the "ongoing"
134
* states for stuff that might not yet be written to the history.
136
if (transState.isActive()) {
137
transState.doQuery(stateInfo, t);
141
* We should have previously inserted an interval for every attribute.
142
* If we do happen do see a 'null' object here, just replace it with a a
143
* dummy internal with a null value, to avoid NPE's further up.
145
for (int i = 0; i < stateInfo.size(); i++) {
146
if (stateInfo.get(i) == null) {
147
//logMissingInterval(i, t);
148
stateInfo.set(i, new TmfStateInterval(t, t, i, TmfStateValue.nullValue()));
155
public ITmfStateInterval querySingleState(long t, int attributeQuark)
156
throws AttributeNotFoundException, TimeRangeException {
157
ITmfStateInterval ret;
159
if (transState.hasInfoAboutStateOf(t, attributeQuark)) {
160
ret = transState.getOngoingInterval(attributeQuark);
162
ret = backend.doSingularQuery(t, attributeQuark);
166
* Return a fake interval if we could not find anything in the history.
167
* We do NOT want to return 'null' here.
170
//logMissingInterval(attributeQuark, t);
171
return new TmfStateInterval(t, this.getCurrentEndTime(),
172
attributeQuark, TmfStateValue.nullValue());
178
public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
179
long t1, long t2) throws TimeRangeException,
180
AttributeNotFoundException {
181
List<ITmfStateInterval> intervals;
182
ITmfStateInterval currentInterval;
185
/* Make sure the time range makes sense */
187
throw new TimeRangeException();
190
/* Set the actual, valid end time of the range query */
191
if (t2 > this.getCurrentEndTime()) {
192
tEnd = this.getCurrentEndTime();
197
/* Get the initial state at time T1 */
198
intervals = new ArrayList<ITmfStateInterval>();
199
currentInterval = querySingleState(t1, attributeQuark);
200
intervals.add(currentInterval);
202
/* Get the following state changes */
203
ts = currentInterval.getEndTime();
204
while (ts != -1 && ts < tEnd) {
205
ts++; /* To "jump over" to the next state in the history */
206
currentInterval = querySingleState(ts, attributeQuark);
207
intervals.add(currentInterval);
208
ts = currentInterval.getEndTime();
214
public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
215
long t1, long t2, long resolution) throws TimeRangeException,
216
AttributeNotFoundException {
217
List<ITmfStateInterval> intervals;
218
ITmfStateInterval currentInterval;
221
/* Make sure the time range makes sense */
222
if (t2 < t1 || resolution <= 0) {
223
throw new TimeRangeException();
226
/* Set the actual, valid end time of the range query */
227
if (t2 > this.getCurrentEndTime()) {
228
tEnd = this.getCurrentEndTime();
233
/* Get the initial state at time T1 */
234
intervals = new ArrayList<ITmfStateInterval>();
235
currentInterval = querySingleState(t1, attributeQuark);
236
intervals.add(currentInterval);
239
* Iterate over the "resolution points". We skip unneeded queries in the
240
* case the current interval is longer than the resolution.
242
for (ts = t1; (currentInterval.getEndTime() != -1) && (ts < tEnd);
244
if (ts <= currentInterval.getEndTime()) {
247
currentInterval = querySingleState(ts, attributeQuark);
248
intervals.add(currentInterval);
251
/* Add the interval at t2, if it wasn't included already. */
252
if (currentInterval.getEndTime() < tEnd) {
253
currentInterval = querySingleState(tEnd, attributeQuark);
254
intervals.add(currentInterval);
259
static void logMissingInterval(int attribute, long timestamp) {
260
Tracer.traceInfo("No data found in history for attribute " + //$NON-NLS-1$
261
attribute + " at time " + timestamp + //$NON-NLS-1$
262
", returning dummy interval"); //$NON-NLS-1$
266
* @name Debugging methods
270
* Print out the contents of the inner structures to the selected
274
public synchronized void debugPrint(PrintWriter writer) {
275
/* Only used for debugging, shouldn't be externalized */
276
writer.println("------------------------------"); //$NON-NLS-1$
278
/* Print the other inner containers */
279
super.debugPrint(writer);
280
backend.debugPrint(writer);