tmf: Update copyright headers in tmf.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / internal / tmf / core / statesystem / backends / historytree / ThreadedHistoryTreeBackend.java
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>
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.backends.historytree;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.util.concurrent.ArrayBlockingQueue;
18 import java.util.concurrent.BlockingQueue;
19
20 import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
21 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
22 import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
23 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
24
25 /**
26 * Variant of the HistoryTreeBackend which runs all the interval-insertion logic
27 * in a separate thread.
28 *
29 * @author alexmont
30 *
31 */
32 public final class ThreadedHistoryTreeBackend extends HistoryTreeBackend
33 implements Runnable {
34
35 /*
36 * From superclass:
37 *
38 * protected final StateHistoryTree sht;
39 */
40
41 private BlockingQueue<HTInterval> intervalQueue;
42 private final Thread shtThread;
43
44 /**
45 * New state history constructor
46 *
47 * Note that it usually doesn't make sense to use a Threaded HT if you're
48 * opening an existing state-file, but you know what you're doing...
49 *
50 * @param newStateFile
51 * The name of the history file that will be created. Should end
52 * in ".ht"
53 * @param blockSize
54 * The size of the blocks in the file
55 * @param maxChildren
56 * The maximum number of children allowed for each core node
57 * @param startTime
58 * The earliest timestamp stored in the history
59 * @param providerVersion
60 * Version of of the state provider. We will only try to reopen
61 * existing files if this version matches the one in the
62 * framework.
63 * @param queueSize
64 * The size of the interval insertion queue. 2000 - 10000 usually
65 * works well
66 * @throws IOException
67 * If there was a problem opening the history file for writing
68 */
69 public ThreadedHistoryTreeBackend(File newStateFile, int blockSize,
70 int maxChildren, long startTime, int providerVersion, int queueSize)
71 throws IOException {
72 super(newStateFile, blockSize, maxChildren, providerVersion, startTime);
73
74 intervalQueue = new ArrayBlockingQueue<HTInterval>(queueSize);
75 shtThread = new Thread(this, "History Tree Thread"); //$NON-NLS-1$
76 shtThread.start();
77 }
78
79 /**
80 * New State History constructor. This version provides default values for
81 * blockSize and maxChildren.
82 *
83 * @param newStateFile
84 * The name of the history file that will be created. Should end
85 * in ".ht"
86 * @param startTime
87 * The earliest timestamp stored in the history
88 * @param providerVersion
89 * Version of of the state provider. We will only try to reopen
90 * existing files if this version matches the one in the
91 * framework.
92 * @param queueSize
93 * The size of the interval insertion queue. 2000 - 10000 usually
94 * works well
95 * @throws IOException
96 * If there was a problem opening the history file for writing
97 */
98 public ThreadedHistoryTreeBackend(File newStateFile, long startTime,
99 int providerVersion, int queueSize) throws IOException {
100 super(newStateFile, providerVersion, startTime);
101
102 intervalQueue = new ArrayBlockingQueue<HTInterval>(queueSize);
103 shtThread = new Thread(this, "History Tree Thread"); //$NON-NLS-1$
104 shtThread.start();
105 }
106
107 /*
108 * The Threaded version does not specify an "existing file" constructor,
109 * since the history is already built (and we only use the other thread
110 * during building). Just use a plain HistoryTreeProvider in this case.
111 *
112 * TODO but what about streaming??
113 */
114
115 @Override
116 public void insertPastState(long stateStartTime, long stateEndTime,
117 int quark, ITmfStateValue value) throws TimeRangeException {
118 /*
119 * Here, instead of directly inserting the elements in the History Tree
120 * underneath, we'll put them in the Queue. They will then be taken and
121 * processed by the other thread executing the run() method.
122 */
123 HTInterval interval = new HTInterval(stateStartTime, stateEndTime,
124 quark, (TmfStateValue) value);
125 try {
126 intervalQueue.put(interval);
127 } catch (InterruptedException e) {
128 /* We should not get interrupted here */
129 System.out.println("State system got interrupted!"); //$NON-NLS-1$
130 e.printStackTrace();
131 }
132 }
133
134 @Override
135 public void finishedBuilding(long endTime) {
136 /*
137 * We need to commit everything in the History Tree and stop the
138 * standalone thread before returning to the StateHistorySystem. (SHS
139 * will then write the Attribute Tree to the file, that must not happen
140 * at the same time we are writing the last nodes!)
141 */
142
143 stopRunningThread(endTime);
144 isFinishedBuilding = true;
145 return;
146 }
147
148 @Override
149 public void dispose() {
150 if (!isFinishedBuilding) {
151 stopRunningThread(TmfTimestamp.PROJECT_IS_CANNED.getValue());
152 }
153 /*
154 * isFinishedBuilding remains false, so the superclass will ask the
155 * back-end to delete the file.
156 */
157 super.dispose();
158 }
159
160 private void stopRunningThread(long endTime) {
161 if (!shtThread.isAlive()) {
162 return;
163 }
164
165 /*
166 * Send a "poison pill" in the queue, then wait for the HT to finish
167 * its closeTree()
168 */
169 try {
170 HTInterval pill = new HTInterval(-1, endTime, -1, TmfStateValue.nullValue());
171 intervalQueue.put(pill);
172 shtThread.join();
173 } catch (TimeRangeException e) {
174 e.printStackTrace();
175 } catch (InterruptedException e) {
176 e.printStackTrace();
177 }
178 }
179
180 @Override
181 public void run() {
182 if (intervalQueue == null) {
183 System.err.println("Cannot start the storage backend without its interval queue."); //$NON-NLS-1$
184 return;
185 }
186 HTInterval currentInterval;
187 try {
188 currentInterval = intervalQueue.take();
189 while (currentInterval.getStartTime() != -1) {
190 /* Send the interval to the History Tree */
191 sht.insertInterval(currentInterval);
192 currentInterval = intervalQueue.take();
193 }
194 assert (currentInterval.getAttribute() == -1);
195 /*
196 * We've been told we're done, let's write down everything and quit.
197 * The end time of this "signal interval" is actually correct.
198 */
199 sht.closeTree(currentInterval.getEndTime());
200 return;
201 } catch (InterruptedException e) {
202 /* We've been interrupted abnormally */
203 System.out.println("State History Tree interrupted!"); //$NON-NLS-1$
204 e.printStackTrace();
205 } catch (TimeRangeException e) {
206 /* This also should not happen */
207 e.printStackTrace();
208 }
209 }
210
211 }
This page took 0.041569 seconds and 6 git commands to generate.