1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 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
.statesystem
.core
.backend
.historytree
;
16 import java
.io
.IOException
;
17 import java
.util
.concurrent
.ArrayBlockingQueue
;
18 import java
.util
.concurrent
.BlockingQueue
;
20 import org
.eclipse
.linuxtools
.internal
.statesystem
.core
.Activator
;
21 import org
.eclipse
.linuxtools
.internal
.statesystem
.core
.backend
.historytree
.HTInterval
;
22 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.TimeRangeException
;
23 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.ITmfStateValue
;
24 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.TmfStateValue
;
27 * Variant of the HistoryTreeBackend which runs all the interval-insertion logic
28 * in a separate thread.
30 * @author Alexandre Montplaisir
33 public final class ThreadedHistoryTreeBackend
extends HistoryTreeBackend
36 private BlockingQueue
<HTInterval
> intervalQueue
;
37 private final Thread shtThread
;
40 * New state history constructor
42 * Note that it usually doesn't make sense to use a Threaded HT if you're
43 * opening an existing state-file, but you know what you're doing...
46 * The name of the history file that will be created. Should end
49 * The size of the blocks in the file
51 * The maximum number of children allowed for each core node
53 * The earliest timestamp stored in the history
54 * @param providerVersion
55 * Version of of the state provider. We will only try to reopen
56 * existing files if this version matches the one in the
59 * The size of the interval insertion queue. 2000 - 10000 usually
62 * If there was a problem opening the history file for writing
64 public ThreadedHistoryTreeBackend(File newStateFile
, int blockSize
,
65 int maxChildren
, long startTime
, int providerVersion
, int queueSize
)
67 super(newStateFile
, blockSize
, maxChildren
, providerVersion
, startTime
);
69 intervalQueue
= new ArrayBlockingQueue
<>(queueSize
);
70 shtThread
= new Thread(this, "History Tree Thread"); //$NON-NLS-1$
75 * New State History constructor. This version provides default values for
76 * blockSize and maxChildren.
79 * The name of the history file that will be created. Should end
82 * The earliest timestamp stored in the history
83 * @param providerVersion
84 * Version of of the state provider. We will only try to reopen
85 * existing files if this version matches the one in the
88 * The size of the interval insertion queue. 2000 - 10000 usually
91 * If there was a problem opening the history file for writing
93 public ThreadedHistoryTreeBackend(File newStateFile
, long startTime
,
94 int providerVersion
, int queueSize
) throws IOException
{
95 super(newStateFile
, providerVersion
, startTime
);
97 intervalQueue
= new ArrayBlockingQueue
<>(queueSize
);
98 shtThread
= new Thread(this, "History Tree Thread"); //$NON-NLS-1$
103 * The Threaded version does not specify an "existing file" constructor,
104 * since the history is already built (and we only use the other thread
105 * during building). Just use a plain HistoryTreeProvider in this case.
107 * TODO but what about streaming??
111 public void insertPastState(long stateStartTime
, long stateEndTime
,
112 int quark
, ITmfStateValue value
) throws TimeRangeException
{
114 * Here, instead of directly inserting the elements in the History Tree
115 * underneath, we'll put them in the Queue. They will then be taken and
116 * processed by the other thread executing the run() method.
118 HTInterval interval
= new HTInterval(stateStartTime
, stateEndTime
,
119 quark
, (TmfStateValue
) value
);
121 intervalQueue
.put(interval
);
122 } catch (InterruptedException e
) {
123 Activator
.getDefault().logError("State system interrupted", e
); //$NON-NLS-1$
128 public void finishedBuilding(long endTime
) {
130 * We need to commit everything in the History Tree and stop the
131 * standalone thread before returning to the StateHistorySystem. (SHS
132 * will then write the Attribute Tree to the file, that must not happen
133 * at the same time we are writing the last nodes!)
136 stopRunningThread(endTime
);
137 isFinishedBuilding
= true;
142 public void dispose() {
143 if (!isFinishedBuilding
) {
144 stopRunningThread(Long
.MAX_VALUE
);
147 * isFinishedBuilding remains false, so the superclass will ask the
148 * back-end to delete the file.
153 private void stopRunningThread(long endTime
) {
154 if (!shtThread
.isAlive()) {
159 * Send a "poison pill" in the queue, then wait for the HT to finish
163 HTInterval pill
= new HTInterval(-1, endTime
, -1, TmfStateValue
.nullValue());
164 intervalQueue
.put(pill
);
166 } catch (TimeRangeException e
) {
167 Activator
.getDefault().logError("Error closing state system", e
); //$NON-NLS-1$
168 } catch (InterruptedException e
) {
169 Activator
.getDefault().logError("State system interrupted", e
); //$NON-NLS-1$
175 if (intervalQueue
== null) {
176 Activator
.getDefault().logError("Cannot start the storage backend without its interval queue."); //$NON-NLS-1$
179 HTInterval currentInterval
;
181 currentInterval
= intervalQueue
.take();
182 while (currentInterval
.getStartTime() != -1) {
183 /* Send the interval to the History Tree */
184 sht
.insertInterval(currentInterval
);
185 currentInterval
= intervalQueue
.take();
187 assert (currentInterval
.getAttribute() == -1);
189 * We've been told we're done, let's write down everything and quit.
190 * The end time of this "signal interval" is actually correct.
192 sht
.closeTree(currentInterval
.getEndTime());
194 } catch (InterruptedException e
) {
195 /* We've been interrupted abnormally */
196 Activator
.getDefault().logError("State History Tree interrupted!", e
); //$NON-NLS-1$
197 } catch (TimeRangeException e
) {
198 /* This also should not happen */
199 Activator
.getDefault().logError("Error starting the state system", e
); //$NON-NLS-1$