1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
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
10 * Alexandre Montplaisir - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.core
.statesystem
;
15 import java
.util
.concurrent
.ArrayBlockingQueue
;
16 import java
.util
.concurrent
.BlockingQueue
;
18 import org
.eclipse
.linuxtools
.tmf
.core
.ctfadaptor
.CtfTmfEventFactory
;
19 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.exceptions
.TimeRangeException
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
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.
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.
32 * processEvent() is replaced with eventHandle(), so that all the multi-thread
33 * logic is abstracted away.
35 * @author Alexandre Montplaisir
38 public abstract class AbstractStateChangeInput
implements IStateChangeInput
{
40 private static final int DEFAULT_EVENTS_QUEUE_SIZE
= 10000;
42 private final ITmfTrace trace
;
43 private final Class
<?
extends ITmfEvent
> eventType
;
44 private final BlockingQueue
<ITmfEvent
> eventsQueue
;
45 private final Thread eventHandlerThread
;
47 private boolean ssAssigned
;
48 private ITmfEvent currentEvent
;
50 /** State system in which to insert the state changes */
51 protected ITmfStateSystemBuilder ss
;
54 * Instantiate a new state provider plugin.
57 * The LTTng 2.0 kernel trace directory
59 * The specific class for the event type that will be used within
62 * Name given to this state change input. Only used internally.
64 public AbstractStateChangeInput(ITmfTrace trace
,
65 Class
<?
extends ITmfEvent
> eventType
, String id
) {
67 this.eventType
= eventType
;
68 eventsQueue
= new ArrayBlockingQueue
<ITmfEvent
>(DEFAULT_EVENTS_QUEUE_SIZE
);
71 String id2
= (id
== null ?
"Unamed" : id
); //$NON-NLS-1$
72 eventHandlerThread
= new Thread(new EventProcessor(), id2
+ " Event Handler"); //$NON-NLS-1$
77 public ITmfTrace
getTrace() {
82 public long getStartTime() {
83 return trace
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
87 public void assignTargetStateSystem(ITmfStateSystemBuilder ssb
) {
90 eventHandlerThread
.start();
94 public ITmfStateSystem
getAssignedStateSystem() {
99 public void dispose() {
100 /* Insert a null event in the queue to stop the event handler's thread. */
102 eventsQueue
.put(CtfTmfEventFactory
.getNullEvent());
103 eventHandlerThread
.join();
104 } catch (InterruptedException e
) {
112 public final Class
<?
extends ITmfEvent
> getExpectedEventType() {
117 public final void processEvent(ITmfEvent event
) {
118 /* Make sure the target state system has been assigned */
120 System
.err
.println("Cannot process event without a target state system"); //$NON-NLS-1$
124 /* Insert the event we're received into the events queue */
125 ITmfEvent curEvent
= event
;
127 eventsQueue
.put(curEvent
);
128 } catch (InterruptedException e
) {
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.
137 private class EventProcessor
implements Runnable
{
142 System
.err
.println("Cannot run event manager without assigning a target state system first!"); //$NON-NLS-1$
148 event
= eventsQueue
.take();
149 while (event
.getTimestamp().getValue() != -1) {
150 currentEvent
= event
;
152 /* Make sure this is an event the sub-class can process */
153 if (eventType
.isInstance(event
)) {
156 event
= eventsQueue
.take();
158 /* We've received the last event, clean up */
161 } catch (InterruptedException e
) {
162 /* We've been interrupted abnormally */
163 System
.out
.println("Event handler interrupted!"); //$NON-NLS-1$
168 private void closeStateSystem() {
169 /* Close the History system, if there is one */
170 if (currentEvent
== null) {
174 ss
.closeHistory(currentEvent
.getTimestamp().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue());
175 } catch (TimeRangeException e
) {
177 * Since we're using currentEvent.getTimestamp, this shouldn't
185 // ------------------------------------------------------------------------
187 // ------------------------------------------------------------------------
190 * Handle the given event and send the appropriate state transitions into
191 * the the state system.
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()
199 * The event to process. If you need a specific event type, you
200 * should check for its instance right at the beginning.
202 protected abstract void eventHandle(ITmfEvent event
);