~ubuntu-branches/ubuntu/trusty/eclipse-linuxtools/trusty

« back to all changes in this revision

Viewing changes to lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/statesystem/StateHistorySystem.java

  • Committer: Package Import Robot
  • Author(s): tony mancill
  • Date: 2013-05-13 21:43:22 UTC
  • mfrom: (1.2.1) (2.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20130513214322-6frgd9du1n0w2uo7
Tags: 1.2.1-1
* Team upload.
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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>
5
 
 *
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
10
 
 *
11
 
 *******************************************************************************/
12
 
 
13
 
package org.eclipse.linuxtools.internal.tmf.core.statesystem;
14
 
 
15
 
import java.io.File;
16
 
import java.io.IOException;
17
 
import java.io.PrintWriter;
18
 
import java.util.ArrayList;
19
 
import java.util.List;
20
 
 
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;
28
 
 
29
 
/**
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).
33
 
 *
34
 
 * This allows the user to then run queries at past timestamps.
35
 
 *
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.
39
 
 *
40
 
 * @author alexmont
41
 
 *
42
 
 */
43
 
public class StateHistorySystem extends StateSystem implements
44
 
        IStateSystemBuilder {
45
 
 
46
 
    /**
47
 
     * In addition, a state "history" system has a storage back-end from which
48
 
     * it can restore past states.
49
 
     */
50
 
    private final IStateHistoryBackend backend;
51
 
 
52
 
    /**
53
 
     * General constructor
54
 
     *
55
 
     * @param backend
56
 
     *            The "state history storage" backend to use.
57
 
     * @param newFile
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.
60
 
     * @throws IOException
61
 
     *             If there was a problem creating the new history file
62
 
     */
63
 
    public StateHistorySystem(IStateHistoryBackend backend, boolean newFile)
64
 
            throws IOException {
65
 
        this.backend = backend;
66
 
        transState = new TransientState(backend);
67
 
 
68
 
        if (newFile) {
69
 
            attributeTree = new AttributeTree(this);
70
 
        } else {
71
 
            /* We're opening an existing file */
72
 
            this.attributeTree = new AttributeTree(this, backend.supplyAttributeTreeReader());
73
 
            transState.setInactive();
74
 
        }
75
 
    }
76
 
 
77
 
    @Override
78
 
    public long getStartTime() {
79
 
        return backend.getStartTime();
80
 
    }
81
 
 
82
 
    @Override
83
 
    public long getCurrentEndTime() {
84
 
        return backend.getEndTime();
85
 
    }
86
 
 
87
 
    @Override
88
 
    public void closeHistory(long endTime) throws TimeRangeException {
89
 
        File attributeTreeFile;
90
 
        long attributeTreeFilePos;
91
 
        long realEndTime = endTime;
92
 
 
93
 
        if (realEndTime < backend.getEndTime()) {
94
 
            /*
95
 
             * This can happen (empty nodes pushing the border further, etc.)
96
 
             * but shouldn't be too big of a deal.
97
 
             */
98
 
            realEndTime = backend.getEndTime();
99
 
        }
100
 
        transState.closeTransientState(realEndTime);
101
 
        backend.finishedBuilding(realEndTime);
102
 
 
103
 
        attributeTreeFile = backend.supplyAttributeTreeWriterFile();
104
 
        attributeTreeFilePos = backend.supplyAttributeTreeWriterFilePosition();
105
 
        if (attributeTreeFile != null) {
106
 
            /*
107
 
             * If null was returned, we simply won't save the attribute tree,
108
 
             * too bad!
109
 
             */
110
 
            attributeTree.writeSelf(attributeTreeFile, attributeTreeFilePos);
111
 
        }
112
 
    }
113
 
 
114
 
    /**
115
 
     * @name External query methods
116
 
     */
117
 
 
118
 
    @Override
119
 
    public synchronized List<ITmfStateInterval> queryFullState(long t)
120
 
            throws TimeRangeException {
121
 
        List<ITmfStateInterval> stateInfo = new ArrayList<ITmfStateInterval>(
122
 
                attributeTree.getNbAttributes());
123
 
 
124
 
        /* Bring the size of the array to the current number of attributes */
125
 
        for (int i = 0; i < attributeTree.getNbAttributes(); i++) {
126
 
            stateInfo.add(null);
127
 
        }
128
 
 
129
 
        /* Query the storage backend */
130
 
        backend.doQuery(stateInfo, t);
131
 
 
132
 
        /*
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.
135
 
         */
136
 
        if (transState.isActive()) {
137
 
            transState.doQuery(stateInfo, t);
138
 
        }
139
 
 
140
 
        /*
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.
144
 
         */
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()));
149
 
            }
150
 
        }
151
 
        return stateInfo;
152
 
    }
153
 
 
154
 
    @Override
155
 
    public ITmfStateInterval querySingleState(long t, int attributeQuark)
156
 
            throws AttributeNotFoundException, TimeRangeException {
157
 
        ITmfStateInterval ret;
158
 
 
159
 
        if (transState.hasInfoAboutStateOf(t, attributeQuark)) {
160
 
            ret = transState.getOngoingInterval(attributeQuark);
161
 
        } else {
162
 
            ret = backend.doSingularQuery(t, attributeQuark);
163
 
        }
164
 
 
165
 
        /*
166
 
         * Return a fake interval if we could not find anything in the history.
167
 
         * We do NOT want to return 'null' here.
168
 
         */
169
 
        if (ret == null) {
170
 
            //logMissingInterval(attributeQuark, t);
171
 
            return new TmfStateInterval(t, this.getCurrentEndTime(),
172
 
                    attributeQuark, TmfStateValue.nullValue());
173
 
        }
174
 
        return ret;
175
 
    }
176
 
 
177
 
    @Override
178
 
    public List<ITmfStateInterval> queryHistoryRange(int attributeQuark,
179
 
            long t1, long t2) throws TimeRangeException,
180
 
            AttributeNotFoundException {
181
 
        List<ITmfStateInterval> intervals;
182
 
        ITmfStateInterval currentInterval;
183
 
        long ts, tEnd;
184
 
 
185
 
        /* Make sure the time range makes sense */
186
 
        if (t2 <= t1) {
187
 
            throw new TimeRangeException();
188
 
        }
189
 
 
190
 
        /* Set the actual, valid end time of the range query */
191
 
        if (t2 > this.getCurrentEndTime()) {
192
 
            tEnd = this.getCurrentEndTime();
193
 
        } else {
194
 
            tEnd = t2;
195
 
        }
196
 
 
197
 
        /* Get the initial state at time T1 */
198
 
        intervals = new ArrayList<ITmfStateInterval>();
199
 
        currentInterval = querySingleState(t1, attributeQuark);
200
 
        intervals.add(currentInterval);
201
 
 
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();
209
 
        }
210
 
        return intervals;
211
 
    }
212
 
 
213
 
    @Override
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;
219
 
        long ts, tEnd;
220
 
 
221
 
        /* Make sure the time range makes sense */
222
 
        if (t2 < t1 || resolution <= 0) {
223
 
            throw new TimeRangeException();
224
 
        }
225
 
 
226
 
        /* Set the actual, valid end time of the range query */
227
 
        if (t2 > this.getCurrentEndTime()) {
228
 
            tEnd = this.getCurrentEndTime();
229
 
        } else {
230
 
            tEnd = t2;
231
 
        }
232
 
 
233
 
        /* Get the initial state at time T1 */
234
 
        intervals = new ArrayList<ITmfStateInterval>();
235
 
        currentInterval = querySingleState(t1, attributeQuark);
236
 
        intervals.add(currentInterval);
237
 
 
238
 
        /*
239
 
         * Iterate over the "resolution points". We skip unneeded queries in the
240
 
         * case the current interval is longer than the resolution.
241
 
         */
242
 
        for (ts = t1; (currentInterval.getEndTime() != -1) && (ts < tEnd);
243
 
                ts += resolution) {
244
 
            if (ts <= currentInterval.getEndTime()) {
245
 
                continue;
246
 
            }
247
 
            currentInterval = querySingleState(ts, attributeQuark);
248
 
            intervals.add(currentInterval);
249
 
        }
250
 
 
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);
255
 
        }
256
 
        return intervals;
257
 
    }
258
 
 
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$
263
 
    }
264
 
 
265
 
    /**
266
 
     * @name Debugging methods
267
 
     */
268
 
 
269
 
    /**
270
 
     * Print out the contents of the inner structures to the selected
271
 
     * PrintWriter.
272
 
     */
273
 
    @Override
274
 
    public synchronized void debugPrint(PrintWriter writer) {
275
 
        /* Only used for debugging, shouldn't be externalized */
276
 
        writer.println("------------------------------"); //$NON-NLS-1$
277
 
 
278
 
        /* Print the other inner containers */
279
 
        super.debugPrint(writer);
280
 
        backend.debugPrint(writer);
281
 
    }
282
 
}