13
13
package org.eclipse.linuxtools.internal.tmf.core.statesystem;
16
import java.io.IOException;
15
17
import java.io.PrintWriter;
18
import java.util.ArrayList;
16
19
import java.util.LinkedList;
17
20
import java.util.List;
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.NullProgressMonitor;
24
import org.eclipse.linuxtools.internal.tmf.core.Tracer;
19
25
import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
20
26
import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
21
27
import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
28
import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
29
import org.eclipse.linuxtools.tmf.core.interval.TmfStateInterval;
30
import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemBuilder;
31
import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier2;
22
32
import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
23
33
import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
26
* This is the base class for the StateHistorySystem. It contains all the
27
* current-state-updating methods.
29
* It's not abstract, as it can be used by itself: in this case, no History tree
30
* will be built underneath (no information will be saved to disk) and it will
31
* only be able to respond to queries to the current, latest time.
33
* (See IStateSystemQuerier and IStateSystemBuilder for the Javadoc.)
36
* This is the core class of the Generic State System. It contains all the
37
* methods to build and query a state history. It's exposed externally through
38
* the IStateSystemQuerier and IStateSystemBuilder interfaces, depending if the
39
* user needs read-only access or read-write access.
41
* When building, DON'T FORGET to call .closeHistory() when you are done
42
* inserting intervals, or the storage backend will have no way of knowing it
43
* can close and write itself to disk, and its thread will keep running.
38
@SuppressWarnings("javadoc") // the javadoc is in the IStateSystem* interfaces
39
public class StateSystem {
48
public class StateSystem implements IStateSystemBuilder, IStateSystemQuerier2{
41
50
/* References to the inner structures */
42
protected AttributeTree attributeTree;
43
protected TransientState transState;
46
* Constructor. No configuration needed!
48
public StateSystem() {
49
attributeTree = new AttributeTree(this);
51
/* This will tell the builder to discard the intervals */
52
transState = new TransientState(null);
51
private final AttributeTree attributeTree;
52
private final TransientState transState;
53
private final IStateHistoryBackend backend;
59
* The "state history storage" backend to use.
61
* Put true if this is a new history started from scratch. It is
62
* used to tell the state system where to get its attribute tree.
64
* If there was a problem creating the new history file
66
public StateSystem(IStateHistoryBackend backend, boolean newFile)
68
this.backend = backend;
69
this.transState = new TransientState(backend);
72
attributeTree = new AttributeTree(this);
74
/* We're opening an existing file */
75
this.attributeTree = new AttributeTree(this, backend.supplyAttributeTreeReader());
76
transState.setInactive();
80
//--------------------------------------------------------------------------
81
// General methods related to the attribute tree
82
//--------------------------------------------------------------------------
85
* Method used by the attribute tree when creating new attributes, to keep
86
* the attribute count in the transient state in sync.
88
void addEmptyAttribute() {
89
transState.addEmptyEntry();
55
93
public int getNbAttributes() {
56
94
return attributeTree.getNbAttributes();
60
* @name Quark-retrieving methods
98
public String getAttributeName(int attributeQuark) {
99
return attributeTree.getAttributeName(attributeQuark);
103
public String getFullAttributePath(int attributeQuark) {
104
return attributeTree.getFullAttributeName(attributeQuark);
107
//--------------------------------------------------------------------------
108
// Methods related to the storage backend
109
//--------------------------------------------------------------------------
112
public long getStartTime() {
113
return backend.getStartTime();
117
public long getCurrentEndTime() {
118
return backend.getEndTime();
122
public void closeHistory(long endTime) throws TimeRangeException {
123
File attributeTreeFile;
124
long attributeTreeFilePos;
125
long realEndTime = endTime;
127
if (realEndTime < backend.getEndTime()) {
129
* This can happen (empty nodes pushing the border further, etc.)
130
* but shouldn't be too big of a deal.
132
realEndTime = backend.getEndTime();
134
transState.closeTransientState(realEndTime);
135
backend.finishedBuilding(realEndTime);
137
attributeTreeFile = backend.supplyAttributeTreeWriterFile();
138
attributeTreeFilePos = backend.supplyAttributeTreeWriterFilePosition();
139
if (attributeTreeFile != null) {
141
* If null was returned, we simply won't save the attribute tree,
144
attributeTree.writeSelf(attributeTreeFile, attributeTreeFilePos);
148
//--------------------------------------------------------------------------
149
// Quark-retrieving methods
150
//--------------------------------------------------------------------------
63
153
public int getQuarkAbsolute(String... attribute)
64
154
throws AttributeNotFoundException {
65
155
return attributeTree.getQuarkDontAdd(-1, attribute);
68
159
public int getQuarkAbsoluteAndAdd(String... attribute) {
69
160
return attributeTree.getQuarkAndAdd(-1, attribute);
72
164
public int getQuarkRelative(int startingNodeQuark, String... subPath)
73
165
throws AttributeNotFoundException {
74
166
return attributeTree.getQuarkDontAdd(startingNodeQuark, subPath);
77
170
public int getQuarkRelativeAndAdd(int startingNodeQuark, String... subPath) {
78
171
return attributeTree.getQuarkAndAdd(startingNodeQuark, subPath);
81
175
public List<Integer> getSubAttributes(int quark, boolean recursive)
82
176
throws AttributeNotFoundException {
83
177
return attributeTree.getSubAttributes(quark, recursive);
86
181
public List<Integer> getQuarks(String... pattern) {
87
182
List<Integer> quarks = new LinkedList<Integer>();
88
183
List<String> prefix = new LinkedList<String>();
171
* @name External methods related to insertions in the history -
265
//--------------------------------------------------------------------------
266
// Methods related to insertions in the history
267
//--------------------------------------------------------------------------
174
270
public void modifyAttribute(long t, ITmfStateValue value, int attributeQuark)
175
271
throws TimeRangeException, AttributeNotFoundException,
176
272
StateValueTypeException {
177
273
transState.processStateChange(t, value, attributeQuark);
180
277
public void incrementAttribute(long t, int attributeQuark)
181
278
throws StateValueTypeException, TimeRangeException,
182
279
AttributeNotFoundException {
183
280
int prevValue = queryOngoingState(attributeQuark).unboxInt();
184
/* prevValue should be == 0 if the attribute wasn't existing before */
281
if (prevValue == -1) {
282
/* if the attribute was previously null, start counting at 0 */
185
285
modifyAttribute(t, TmfStateValue.newValueInt(prevValue + 1),
189
290
public void pushAttribute(long t, ITmfStateValue value, int attributeQuark)
190
291
throws TimeRangeException, AttributeNotFoundException,
191
292
StateValueTypeException {
303
* @name "Current" query/update methods -
405
//--------------------------------------------------------------------------
406
// "Current" query/update methods
407
//--------------------------------------------------------------------------
306
410
public ITmfStateValue queryOngoingState(int attributeQuark)
307
411
throws AttributeNotFoundException {
308
412
return transState.getOngoingStateValue(attributeQuark);
311
416
public void updateOngoingState(ITmfStateValue newValue, int attributeQuark)
312
417
throws AttributeNotFoundException {
313
418
transState.changeOngoingStateValue(attributeQuark, newValue);
316
public String getAttributeName(int attributeQuark) {
317
return attributeTree.getAttributeName(attributeQuark);
320
public String getFullAttributePath(int attributeQuark) {
321
return attributeTree.getFullAttributeName(attributeQuark);
423
//--------------------------------------------------------------------------
424
// Regular query methods (sent to the back-end)
425
//--------------------------------------------------------------------------
428
public synchronized List<ITmfStateInterval> queryFullState(long t)
429
throws TimeRangeException {
430
List<ITmfStateInterval> stateInfo = new ArrayList<ITmfStateInterval>(
431
attributeTree.getNbAttributes());
433
/* Bring the size of the array to the current number of attributes */
434
for (int i = 0; i < attributeTree.getNbAttributes(); i++) {
438
/* Query the storage backend */
439
backend.doQuery(stateInfo, t);
442
* If we are currently building the history, also query the "ongoing"
443
* states for stuff that might not yet be written to the history.
445
if (transState.isActive()) {
446
transState.doQuery(stateInfo, t);
450
* We should have previously inserted an interval for every attribute.
451
* If we do happen do see a 'null' object here, just replace it with a a
452
* dummy internal with a null value, to avoid NPE's further up.
454
for (int i = 0; i < stateInfo.size(); i++) {
455
if (stateInfo.get(i) == null) {
456
//logMissingInterval(i, t);
457
stateInfo.set(i, new TmfStateInterval(t, t, i, TmfStateValue.nullValue()));
464
public ITmfStateInterval querySingleState(long t, int attributeQuark)
465
throws AttributeNotFoundException, TimeRangeException {
466
ITmfStateInterval ret;
468
if (transState.hasInfoAboutStateOf(t, attributeQuark)) {
469
ret = transState.getOngoingInterval(attributeQuark);
471
ret = backend.doSingularQuery(t, attributeQuark);
475
* Return a fake interval if we could not find anything in the history.
476
* We do NOT want to return 'null' here.
479
//logMissingInterval(attributeQuark, t);
480
return new TmfStateInterval(t, this.getCurrentEndTime(),
481
attributeQuark, TmfStateValue.nullValue());
487
public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
488
long t1, long t2) throws TimeRangeException,
489
AttributeNotFoundException {
490
List<ITmfStateInterval> intervals;
491
ITmfStateInterval currentInterval;
494
/* Make sure the time range makes sense */
496
throw new TimeRangeException();
499
/* Set the actual, valid end time of the range query */
500
if (t2 > this.getCurrentEndTime()) {
501
tEnd = this.getCurrentEndTime();
506
/* Get the initial state at time T1 */
507
intervals = new ArrayList<ITmfStateInterval>();
508
currentInterval = querySingleState(t1, attributeQuark);
509
intervals.add(currentInterval);
511
/* Get the following state changes */
512
ts = currentInterval.getEndTime();
513
while (ts != -1 && ts < tEnd) {
514
ts++; /* To "jump over" to the next state in the history */
515
currentInterval = querySingleState(ts, attributeQuark);
516
intervals.add(currentInterval);
517
ts = currentInterval.getEndTime();
523
public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
524
long t1, long t2, long resolution) throws TimeRangeException,
525
AttributeNotFoundException {
526
return queryHistoryRange(attributeQuark, t1, t2, resolution, new NullProgressMonitor());
530
public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
531
long t1, long t2, long resolution, IProgressMonitor monitor) throws TimeRangeException,
532
AttributeNotFoundException {
533
List<ITmfStateInterval> intervals;
534
ITmfStateInterval currentInterval;
537
/* Make sure the time range makes sense */
538
if (t2 < t1 || resolution <= 0) {
539
throw new TimeRangeException();
542
/* Set the actual, valid end time of the range query */
543
if (t2 > this.getCurrentEndTime()) {
544
tEnd = this.getCurrentEndTime();
549
/* Get the initial state at time T1 */
550
intervals = new ArrayList<ITmfStateInterval>();
551
currentInterval = querySingleState(t1, attributeQuark);
552
intervals.add(currentInterval);
555
* Iterate over the "resolution points". We skip unneeded queries in the
556
* case the current interval is longer than the resolution.
558
for (ts = t1; (currentInterval.getEndTime() != -1) && (ts < tEnd);
560
if (monitor.isCanceled()) {
563
if (ts <= currentInterval.getEndTime()) {
566
currentInterval = querySingleState(ts, attributeQuark);
567
intervals.add(currentInterval);
570
/* Add the interval at t2, if it wasn't included already. */
571
if (currentInterval.getEndTime() < tEnd) {
572
currentInterval = querySingleState(tEnd, attributeQuark);
573
intervals.add(currentInterval);
578
//--------------------------------------------------------------------------
580
//--------------------------------------------------------------------------
582
static void logMissingInterval(int attribute, long timestamp) {
583
Tracer.traceInfo("No data found in history for attribute " + //$NON-NLS-1$
584
attribute + " at time " + timestamp + //$NON-NLS-1$
585
", returning dummy interval"); //$NON-NLS-1$