tmf : Avoid concatenating nonliterals in a StringBuffer
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / statesystem / AbstractTmfStateProvider.java
CommitLineData
79e0a1df 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2012, 2015 Ericsson
79e0a1df
AM
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Alexandre Montplaisir - Initial API and implementation
11 *******************************************************************************/
12
2bdf0193 13package org.eclipse.tracecompass.tmf.core.statesystem;
79e0a1df 14
e2bcc8a5
AM
15import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
e2bcc8a5 17import org.eclipse.jdt.annotation.NonNull;
d0c7e4ba 18import org.eclipse.jdt.annotation.Nullable;
423cf6a4 19import org.eclipse.tracecompass.common.core.collect.BufferedBlockingQueue;
e894a508
AM
20import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
21import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
2bdf0193
AM
22import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
23import org.eclipse.tracecompass.tmf.core.event.TmfEvent;
24import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
0c7471fb 25import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
2bdf0193 26import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
79e0a1df 27
79e0a1df
AM
28/**
29 * Instead of using IStateChangeInput directly, one can extend this class, which
30 * defines a lot of the common functions of the state change input plugin.
31 *
32 * It will handle the state-system-processing in a separate thread, which is
33 * normally not a bad idea for traces of some size.
34 *
35 * processEvent() is replaced with eventHandle(), so that all the multi-thread
36 * logic is abstracted away.
37 *
38 * @author Alexandre Montplaisir
79e0a1df 39 */
0fe46f2a 40public abstract class AbstractTmfStateProvider implements ITmfStateProvider {
79e0a1df 41
423cf6a4
MK
42 private static final int DEFAULT_EVENTS_QUEUE_SIZE = 127;
43 private static final int DEFAULT_EVENTS_CHUNK_SIZE = 127;
79e0a1df 44
086cd39c 45 private final ITmfTrace fTrace;
423cf6a4 46 private final BufferedBlockingQueue<ITmfEvent> fEventsQueue;
086cd39c 47 private final Thread fEventHandlerThread;
79e0a1df 48
086cd39c 49 private boolean fStateSystemAssigned;
79e0a1df 50
6f4e8ec0 51 /** State system in which to insert the state changes */
086cd39c 52 private @Nullable ITmfStateSystemBuilder fSS = null;
6f4e8ec0 53
79e0a1df
AM
54 /**
55 * Instantiate a new state provider plugin.
56 *
57 * @param trace
58 * The LTTng 2.0 kernel trace directory
71f2da63
AM
59 * @param id
60 * Name given to this state change input. Only used internally.
79e0a1df 61 */
e2bcc8a5 62 public AbstractTmfStateProvider(ITmfTrace trace, String id) {
086cd39c 63 fTrace = trace;
423cf6a4 64 fEventsQueue = new BufferedBlockingQueue<>(DEFAULT_EVENTS_QUEUE_SIZE, DEFAULT_EVENTS_CHUNK_SIZE);
086cd39c 65 fStateSystemAssigned = false;
71f2da63 66
086cd39c 67 fEventHandlerThread = new Thread(new EventProcessor(), id + " Event Handler"); //$NON-NLS-1$
d0c7e4ba
AM
68 }
69
70 /**
71 * Get the state system builder of this provider (to insert states in).
72 *
73 * @return The state system object to be filled
74 */
75 protected @Nullable ITmfStateSystemBuilder getStateSystemBuilder() {
086cd39c 76 return fSS;
79e0a1df
AM
77 }
78
79 @Override
80 public ITmfTrace getTrace() {
086cd39c 81 return fTrace;
79e0a1df
AM
82 }
83
84 @Override
85 public long getStartTime() {
086cd39c 86 return fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
79e0a1df
AM
87 }
88
89 @Override
f1f86dfb 90 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) {
086cd39c
MK
91 fSS = ssb;
92 fStateSystemAssigned = true;
93 fEventHandlerThread.start();
79e0a1df
AM
94 }
95
7e634be6 96 @Override
d0c7e4ba 97 public @Nullable ITmfStateSystem getAssignedStateSystem() {
086cd39c 98 return fSS;
7e634be6
AM
99 }
100
79e0a1df
AM
101 @Override
102 public void dispose() {
103 /* Insert a null event in the queue to stop the event handler's thread. */
104 try {
086cd39c 105 fEventsQueue.put(END_EVENT);
423cf6a4 106 fEventsQueue.flushInputBuffer();
086cd39c 107 fEventHandlerThread.join();
79e0a1df
AM
108 } catch (InterruptedException e) {
109 e.printStackTrace();
110 }
086cd39c
MK
111 fStateSystemAssigned = false;
112 fSS = null;
79e0a1df
AM
113 }
114
79044a66
AM
115 @Override
116 public final void processEvent(ITmfEvent event) {
79e0a1df 117 /* Make sure the target state system has been assigned */
086cd39c 118 if (!fStateSystemAssigned) {
79e0a1df
AM
119 System.err.println("Cannot process event without a target state system"); //$NON-NLS-1$
120 return;
121 }
122
123 /* Insert the event we're received into the events queue */
124 ITmfEvent curEvent = event;
423cf6a4 125 fEventsQueue.put(curEvent);
79e0a1df
AM
126 }
127
1b9d3765
AM
128 /**
129 * Block the caller until the events queue is empty.
130 */
131 public void waitForEmptyQueue() {
132 /*
133 * We will first insert a dummy event that is guaranteed to not modify
134 * the state. That way, when that event leaves the queue, we will know
135 * for sure that the state system processed the preceding real event.
136 */
1b9d3765 137 try {
086cd39c 138 fEventsQueue.put(EMPTY_QUEUE_EVENT);
423cf6a4 139 fEventsQueue.flushInputBuffer();
086cd39c 140 while (!fEventsQueue.isEmpty()) {
6f04e06c 141 Thread.sleep(100);
1b9d3765
AM
142 }
143 } catch (InterruptedException e) {
144 e.printStackTrace();
145 }
146 }
147
ef8dd5af 148 // ------------------------------------------------------------------------
aca5f650 149 // Special event types
ef8dd5af
AM
150 // ------------------------------------------------------------------------
151
aca5f650 152 /** Fake event indicating the build is over, and the provider should close */
0c7471fb
AM
153 private static class EndEvent extends TmfEvent {
154 public EndEvent() {
e1de2fd4 155 super(null, ITmfContext.UNKNOWN_RANK, null, null, null);
0c7471fb
AM
156 }
157 }
158
aca5f650 159 /** Fake event indicating we want to clear the current queue */
0c7471fb
AM
160 private static class EmptyQueueEvent extends TmfEvent {
161 public EmptyQueueEvent() {
e1de2fd4 162 super(null, ITmfContext.UNKNOWN_RANK, null, null, null);
0c7471fb
AM
163 }
164 }
aca5f650
MK
165
166 private static final EndEvent END_EVENT = new EndEvent();
167 private static final EmptyQueueEvent EMPTY_QUEUE_EVENT = new EmptyQueueEvent();
168
169 // ------------------------------------------------------------------------
170 // Inner classes
171 // ------------------------------------------------------------------------
ef8dd5af 172
79e0a1df
AM
173 /**
174 * This is the runner class for the second thread, which will take the
175 * events from the queue and pass them through the state system.
176 */
177 private class EventProcessor implements Runnable {
178
d0c7e4ba 179 private @Nullable ITmfEvent currentEvent;
e8b7cc14 180
79e0a1df
AM
181 @Override
182 public void run() {
086cd39c 183 if (!fStateSystemAssigned) {
79e0a1df
AM
184 System.err.println("Cannot run event manager without assigning a target state system first!"); //$NON-NLS-1$
185 return;
186 }
79e0a1df 187
423cf6a4
MK
188
189 /*
190 * We never insert null in the queue. Cannot be checked at
191 * compile-time until Java 8 annotations...
192 */
193 @NonNull ITmfEvent event = checkNotNull(fEventsQueue.take());
194 /* This is a singleton, we want to do != instead of !x.equals */
195 while (event != END_EVENT) {
196 if (event == EMPTY_QUEUE_EVENT) {
197 /* Synchronization event, should be ignored */
e2bcc8a5 198 event = checkNotNull(fEventsQueue.take());
423cf6a4 199 continue;
79e0a1df 200 }
423cf6a4
MK
201 currentEvent = event;
202 eventHandle(event);
203 event = checkNotNull(fEventsQueue.take());
79e0a1df 204 }
423cf6a4
MK
205 /* We've received the last event, clean up */
206 closeStateSystem();
79e0a1df
AM
207 }
208
209 private void closeStateSystem() {
d0c7e4ba
AM
210 ITmfEvent event = currentEvent;
211 final long endTime = (event == null) ? 0 :
212 event.getTimestamp().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
213
086cd39c
MK
214 if (fSS != null) {
215 fSS.closeHistory(endTime);
d0c7e4ba 216 }
79e0a1df
AM
217 }
218 }
219
220 // ------------------------------------------------------------------------
221 // Abstract methods
222 // ------------------------------------------------------------------------
223
79e0a1df
AM
224 /**
225 * Handle the given event and send the appropriate state transitions into
226 * the the state system.
227 *
228 * This is basically the same thing as IStateChangeInput.processEvent(),
229 * except here processEvent() and eventHandle() are run in two different
230 * threads (and the AbstractStateChangeInput takes care of processEvent()
231 * already).
232 *
233 * @param event
234 * The event to process. If you need a specific event type, you
235 * should check for its instance right at the beginning.
236 */
237 protected abstract void eventHandle(ITmfEvent event);
086cd39c 238
79e0a1df 239}
This page took 0.08815 seconds and 5 git commands to generate.