tmf: Update copyright headers in tmf.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / statesystem / AbstractStateChangeInput.java
CommitLineData
79e0a1df 1/*******************************************************************************
61759503 2 * Copyright (c) 2012, 2013 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
13package org.eclipse.linuxtools.tmf.core.statesystem;
14
15import java.util.concurrent.ArrayBlockingQueue;
16import java.util.concurrent.BlockingQueue;
17
6cfa0200 18import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEventFactory;
79e0a1df
AM
19import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
20import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
3bd46eef 21import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
79e0a1df
AM
22import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
23
24
25/**
26 * Instead of using IStateChangeInput directly, one can extend this class, which
27 * defines a lot of the common functions of the state change input plugin.
28 *
29 * It will handle the state-system-processing in a separate thread, which is
30 * normally not a bad idea for traces of some size.
31 *
32 * processEvent() is replaced with eventHandle(), so that all the multi-thread
33 * logic is abstracted away.
34 *
35 * @author Alexandre Montplaisir
36 * @since 2.0
37 */
38public abstract class AbstractStateChangeInput implements IStateChangeInput {
39
40 private static final int DEFAULT_EVENTS_QUEUE_SIZE = 10000;
41
79e0a1df 42 private final ITmfTrace trace;
79044a66
AM
43 private final Class<? extends ITmfEvent> eventType;
44 private final BlockingQueue<ITmfEvent> eventsQueue;
79e0a1df
AM
45 private final Thread eventHandlerThread;
46
47 private boolean ssAssigned;
79e0a1df
AM
48 private ITmfEvent currentEvent;
49
6f4e8ec0
AM
50 /** State system in which to insert the state changes */
51 protected ITmfStateSystemBuilder ss;
52
79e0a1df
AM
53 /**
54 * Instantiate a new state provider plugin.
55 *
56 * @param trace
57 * The LTTng 2.0 kernel trace directory
79044a66
AM
58 * @param eventType
59 * The specific class for the event type that will be used within
60 * the subclass
71f2da63
AM
61 * @param id
62 * Name given to this state change input. Only used internally.
79e0a1df 63 */
71f2da63
AM
64 public AbstractStateChangeInput(ITmfTrace trace,
65 Class<? extends ITmfEvent> eventType, String id) {
79e0a1df 66 this.trace = trace;
79044a66
AM
67 this.eventType = eventType;
68 eventsQueue = new ArrayBlockingQueue<ITmfEvent>(DEFAULT_EVENTS_QUEUE_SIZE);
79044a66 69 ssAssigned = false;
71f2da63
AM
70
71 String id2 = (id == null ? "Unamed" : id); //$NON-NLS-1$
72 eventHandlerThread = new Thread(new EventProcessor(), id2 + " Event Handler"); //$NON-NLS-1$
73
79e0a1df
AM
74 }
75
76 @Override
77 public ITmfTrace getTrace() {
78 return trace;
79 }
80
81 @Override
82 public long getStartTime() {
faa38350 83 return trace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
79e0a1df
AM
84 }
85
86 @Override
f1f86dfb 87 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb) {
79e0a1df
AM
88 ss = ssb;
89 ssAssigned = true;
90 eventHandlerThread.start();
91 }
92
7e634be6
AM
93 @Override
94 public ITmfStateSystem getAssignedStateSystem() {
95 return ss;
96 }
97
79e0a1df
AM
98 @Override
99 public void dispose() {
100 /* Insert a null event in the queue to stop the event handler's thread. */
101 try {
6cfa0200 102 eventsQueue.put(CtfTmfEventFactory.getNullEvent());
79e0a1df
AM
103 eventHandlerThread.join();
104 } catch (InterruptedException e) {
105 e.printStackTrace();
106 }
107 ssAssigned = false;
108 ss = null;
109 }
110
111 @Override
79044a66
AM
112 public final Class<? extends ITmfEvent> getExpectedEventType() {
113 return eventType;
114 }
115
116 @Override
117 public final void processEvent(ITmfEvent event) {
79e0a1df
AM
118 /* Make sure the target state system has been assigned */
119 if (!ssAssigned) {
120 System.err.println("Cannot process event without a target state system"); //$NON-NLS-1$
121 return;
122 }
123
124 /* Insert the event we're received into the events queue */
125 ITmfEvent curEvent = event;
126 try {
127 eventsQueue.put(curEvent);
128 } catch (InterruptedException e) {
129 e.printStackTrace();
130 }
131 }
132
79e0a1df
AM
133 /**
134 * This is the runner class for the second thread, which will take the
135 * events from the queue and pass them through the state system.
136 */
137 private class EventProcessor implements Runnable {
138
139 @Override
140 public void run() {
141 if (ss == null) {
142 System.err.println("Cannot run event manager without assigning a target state system first!"); //$NON-NLS-1$
143 return;
144 }
145 ITmfEvent event;
146
147 try {
148 event = eventsQueue.take();
149 while (event.getTimestamp().getValue() != -1) {
150 currentEvent = event;
79044a66
AM
151
152 /* Make sure this is an event the sub-class can process */
153 if (eventType.isInstance(event)) {
154 eventHandle(event);
155 }
79e0a1df
AM
156 event = eventsQueue.take();
157 }
158 /* We've received the last event, clean up */
159 closeStateSystem();
160 return;
161 } catch (InterruptedException e) {
162 /* We've been interrupted abnormally */
163 System.out.println("Event handler interrupted!"); //$NON-NLS-1$
164 e.printStackTrace();
165 }
166 }
167
168 private void closeStateSystem() {
169 /* Close the History system, if there is one */
170 if (currentEvent == null) {
171 return;
172 }
173 try {
faa38350 174 ss.closeHistory(currentEvent.getTimestamp().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue());
79e0a1df
AM
175 } catch (TimeRangeException e) {
176 /*
177 * Since we're using currentEvent.getTimestamp, this shouldn't
178 * cause any problem
179 */
180 e.printStackTrace();
181 }
182 }
183 }
184
185 // ------------------------------------------------------------------------
186 // Abstract methods
187 // ------------------------------------------------------------------------
188
79e0a1df
AM
189 /**
190 * Handle the given event and send the appropriate state transitions into
191 * the the state system.
192 *
193 * This is basically the same thing as IStateChangeInput.processEvent(),
194 * except here processEvent() and eventHandle() are run in two different
195 * threads (and the AbstractStateChangeInput takes care of processEvent()
196 * already).
197 *
198 * @param event
199 * The event to process. If you need a specific event type, you
200 * should check for its instance right at the beginning.
201 */
202 protected abstract void eventHandle(ITmfEvent event);
203}
This page took 0.034495 seconds and 5 git commands to generate.