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