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