1 /*******************************************************************************
2 * Copyright (c) 2011 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 * Polytechnique Montréal - Initial API and implementation
11 * Bernd Hufmann - Productification, enhancements and fixes
13 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.subsystems
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Arrays
;
18 import java
.util
.Vector
;
19 import java
.util
.concurrent
.TimeUnit
;
21 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
22 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
23 import org
.eclipse
.linuxtools
.lttng
.LttngConstants
;
24 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.ProviderResource
;
25 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.TargetResource
;
26 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.TraceResource
;
27 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.TraceResource
.TraceState
;
28 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.config
.TraceConfig
;
29 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.service
.ILttControllerService
;
30 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.service
.LttControllerServiceProxy
;
31 import org
.eclipse
.linuxtools
.lttng
.ui
.LTTngUiPlugin
;
32 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.TraceControlConstants
;
33 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.Messages
;
34 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.actions
.PauseTrace
;
35 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.connectorservice
.TraceConnectorService
;
36 import org
.eclipse
.rse
.core
.events
.ISystemResourceChangeEvents
;
37 import org
.eclipse
.rse
.core
.events
.SystemResourceChangeEvent
;
38 import org
.eclipse
.rse
.core
.filters
.ISystemFilter
;
39 import org
.eclipse
.rse
.core
.filters
.ISystemFilterPoolReference
;
40 import org
.eclipse
.rse
.core
.model
.IHost
;
41 import org
.eclipse
.rse
.core
.model
.ISystemMessageObject
;
42 import org
.eclipse
.rse
.core
.model
.ISystemRegistry
;
43 import org
.eclipse
.rse
.core
.model
.SystemMessageObject
;
44 import org
.eclipse
.rse
.core
.model
.SystemStartHere
;
45 import org
.eclipse
.rse
.core
.subsystems
.CommunicationsEvent
;
46 import org
.eclipse
.rse
.core
.subsystems
.ICommunicationsListener
;
47 import org
.eclipse
.rse
.core
.subsystems
.IConnectorService
;
48 import org
.eclipse
.rse
.core
.subsystems
.SubSystem
;
49 import org
.eclipse
.rse
.services
.clientserver
.NamePatternMatcher
;
50 import org
.eclipse
.rse
.services
.clientserver
.messages
.SystemMessageException
;
51 import org
.eclipse
.rse
.ui
.SystemBasePlugin
;
52 import org
.eclipse
.swt
.widgets
.Display
;
53 import org
.eclipse
.tm
.tcf
.protocol
.IToken
;
54 import org
.eclipse
.tm
.tcf
.util
.TCFTask
;
57 * <b><u>TraceSubSystem</u></b>
59 * Implementation of the trace subsystem. Provides methods to initialize connections
60 * to the remote system, connection handling, filtering and retrival of remote
61 * system configuration.
64 public class TraceSubSystem
extends SubSystem
implements ICommunicationsListener
{
66 // ------------------------------------------------------------------------
68 // ------------------------------------------------------------------------
69 private ProviderResource
[] fProviders
; // master list of Providers
71 // ------------------------------------------------------------------------
73 // ------------------------------------------------------------------------
76 * @param connectorService
78 public TraceSubSystem(IHost host
, IConnectorService connectorService
) {
79 super(host
, connectorService
);
82 // ------------------------------------------------------------------------
84 // ------------------------------------------------------------------------
88 * @see org.eclipse.rse.core.subsystems.SubSystem#initializeSubSystem(org.eclipse.core.runtime.IProgressMonitor)
91 public void initializeSubSystem(IProgressMonitor monitor
) {
92 getConnectorService().addCommunicationsListener(this);
97 * @see org.eclipse.rse.core.subsystems.SubSystem#uninitializeSubSystem(org.eclipse.core.runtime.IProgressMonitor)
100 public void uninitializeSubSystem(IProgressMonitor monitor
) {
105 * @see org.eclipse.rse.core.subsystems.SubSystem#getObjectWithAbsoluteName(java.lang.String)
107 * For drag and drop, and clipboard support of remote objects.
109 * Return the remote object within the subsystem that corresponds to the specified unique ID. Because each subsystem maintains it's own objects, it's the responsability of the subsystem to determine how an ID (or key) for a given object maps to
110 * the real object. By default this returns null.
113 public Object
getObjectWithAbsoluteName(String key
) {
119 * @see org.eclipse.rse.core.subsystems.SubSystem#internalResolveFilterString(java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
122 protected Object
[] internalResolveFilterString(String filterString
, IProgressMonitor monitor
) throws java
.lang
.reflect
.InvocationTargetException
, java
.lang
.InterruptedException
{
124 ProviderResource
[] allProviders
;
127 allProviders
= getAllProviders();
128 } catch (SystemMessageException e
) {
129 SystemBasePlugin
.logError("TraceSubSystem", e
); //$NON-NLS-1$
130 Object
[] children
= new SystemMessageObject
[1];
131 children
[0] = new SystemMessageObject(e
.getSystemMessage(), ISystemMessageObject
.MSGTYPE_ERROR
, null);
135 // Now, subset master list, based on filter string...
136 NamePatternMatcher subsetter
= new NamePatternMatcher(filterString
);
137 Vector
<ProviderResource
> v
= new Vector
<ProviderResource
>();
138 for (int idx
= 0; idx
< allProviders
.length
; idx
++) {
139 if (subsetter
.matches(allProviders
[idx
].getName())) {
140 v
.addElement(allProviders
[idx
]);
147 * @see org.eclipse.rse.core.subsystems.SubSystem#internalResolveFilterString(java.lang.Object, java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
150 protected Object
[] internalResolveFilterString(Object parent
, String filterString
, IProgressMonitor monitor
) throws java
.lang
.reflect
.InvocationTargetException
, java
.lang
.InterruptedException
{
155 * @see org.eclipse.rse.core.subsystems.SubSystem#filterEventFilterCreated(java.lang.Object, org.eclipse.rse.core.filters.ISystemFilter)
158 public void filterEventFilterCreated(Object selectedObject
, ISystemFilter newFilter
) {
159 super.filterEventFilterCreated(selectedObject
, newFilter
);
160 ISystemRegistry registry
= SystemStartHere
.getSystemRegistry();
161 registry
.fireEvent(new SystemResourceChangeEvent(this, ISystemResourceChangeEvents
.EVENT_REFRESH
, null));
165 * @see org.eclipse.rse.core.subsystems.SubSystem#filterEventFilterPoolReferenceCreated(org.eclipse.rse.core.filters.ISystemFilterPoolReference)
168 public void filterEventFilterPoolReferenceCreated(ISystemFilterPoolReference newPoolRef
) {
169 super.filterEventFilterPoolReferenceCreated(newPoolRef
);
170 if (getSystemFilterPoolReferenceManager().getSystemFilterPoolReferenceCount() == 1) {
171 ISystemRegistry registry
= SystemStartHere
.getSystemRegistry();
172 registry
.fireEvent(new SystemResourceChangeEvent(this, ISystemResourceChangeEvents
.EVENT_REFRESH
, null));
177 * Retrieves all provider resources from the remote system and updates local references.
179 * @return provider resources
180 * @throws SystemMessageException
181 * @throws InterruptedException
183 public ProviderResource
[] getAllProviders() throws SystemMessageException
, InterruptedException
{
184 ProviderResource
[] providers
= createProviders();
185 if (fProviders
== null) {
186 fProviders
= providers
;
189 for (int i
= 0; i
< fProviders
.length
; i
++) {
190 for (int j
= 0; j
< providers
.length
; j
++) {
191 if(fProviders
[i
].getName().equals(providers
[j
].getName())) {
192 // Check if all targets already exist
193 fProviders
[i
].refreshTargets(providers
[j
].getTargets());
202 * Get the list of all targets.
204 * @return targets The list of targets.
205 * @throws SystemMessageException
207 public TargetResource
[] getAllTargets() throws SystemMessageException
{
208 ArrayList
<TargetResource
> targets
= new ArrayList
<TargetResource
>();
209 if (fProviders
!= null) {
210 for (int i
= 0; i
< fProviders
.length
; i
++) {
211 targets
.addAll(Arrays
.asList(fProviders
[i
].getTargets()));
214 return targets
.toArray(new TargetResource
[0]);
218 * Get the list of all traces.
220 * @return traces The list of traces.
221 * @throws SystemMessageException
223 public TraceResource
[] getAllTraces() throws SystemMessageException
{
224 ArrayList
<TraceResource
> traces
= new ArrayList
<TraceResource
>();
225 if (fProviders
!= null) {
226 for (int i
= 0; i
< fProviders
.length
; i
++) {
227 ProviderResource provider
= fProviders
[i
];
228 int numTargets
= provider
.getTargets().length
;
229 for (int j
= 0; j
< numTargets
; j
++) {
230 TargetResource target
= provider
.getTargets()[j
];
231 if (provider
.getName().equals(LttngConstants
.Lttng_Provider_Kernel
)) {
232 traces
.addAll(Arrays
.asList(target
.getTraces()));
237 return traces
.toArray(new TraceResource
[0]);
241 * Get the list of all traces for given provider and target.
245 * @returns trace resources
247 public TraceResource
[] getAllTraces(String providerName
, String targetName
) throws SystemMessageException
{
248 ArrayList
<TraceResource
> traces
= new ArrayList
<TraceResource
>();
249 ProviderResource selectedProvider
= null;
250 if (fProviders
!= null) {
251 for (int i
= 0; i
< fProviders
.length
; i
++) {
252 ProviderResource provider
= fProviders
[i
];
253 if (provider
.getName().equals(providerName
)) {
254 selectedProvider
= fProviders
[i
];
259 if (selectedProvider
!= null) {
260 int numTargets
= selectedProvider
.getTargets().length
;
261 for (int j
= 0; j
< numTargets
; j
++) {
262 TargetResource target
= selectedProvider
.getTargets()[j
];
263 if (target
.getName().equals(targetName
)) {
264 traces
.addAll(Arrays
.asList(target
.getTraces()));
270 return traces
.toArray(new TraceResource
[0]);
274 * Finds a trace resource within a given provider and target for a given trace name
276 * @param targetName - target name to be searched
277 * @param traceName - trace name to be searched
278 * @return trace resource or null (if not found)
280 public TraceResource
findTrace(String providerName
, String targetName
, String traceName
) {
281 TraceResource trace
= null;
282 TraceResource
[] traces
;
284 traces
= getAllTraces(providerName
, targetName
);
285 for (int i
= 0; i
< traces
.length
; i
++) {
286 if (traces
[i
].getName().equals(traceName
)) {
291 } catch (SystemMessageException e
) {
292 SystemBasePlugin
.logError("TraceSubSystem", e
); //$NON-NLS-1$
299 * Retrieves the providers from the remote system.
301 private ProviderResource
[] createProviders() throws SystemMessageException
{
302 ProviderResource
[] providers
= null;
305 final ILttControllerService service
= getControllerService();
307 // Create future task
308 providers
= new TCFTask
<ProviderResource
[]>() {
312 // Get provider using Lttng controller service proxy
313 service
.getProviders(new ILttControllerService
.DoneGetProviders() {
316 public void doneGetProviders(IToken token
, Exception error
, String
[] str
) {
323 // Create provider list
324 ProviderResource
[] providers
= new ProviderResource
[str
.length
];
326 for (int i
= 0; i
< str
.length
; i
++) {
327 ProviderResource tempProvider
= new ProviderResource(TraceSubSystem
.this);
328 tempProvider
.setName(str
[i
]);
329 providers
[i
] = tempProvider
;
332 // Notify with provider list
336 }}.get(TraceControlConstants
.DEFAULT_TCF_TASK_TIMEOUT
, TimeUnit
.SECONDS
);
337 } catch (Exception e
) {
338 if (e
instanceof SystemMessageException
) throw (SystemMessageException
)e
;
339 throw new SystemMessageException(LTTngUiPlugin
.getDefault().getMessage(e
));
342 for (int i
= 0; i
< providers
.length
; i
++) {
343 createTargets(providers
[i
]);
350 * Retrieves the targets for given provider from the remote system.
352 private TargetResource
[] createTargets(final ProviderResource provider
) throws SystemMessageException
{
353 TargetResource
[] targets
;
355 final ILttControllerService service
= getControllerService();
357 // Create future task
358 targets
= new TCFTask
<TargetResource
[]>() {
362 // Get targets using Lttng controller service proxy
363 service
.getTargets(provider
.getName(), new ILttControllerService
.DoneGetTargets() {
366 public void doneGetTargets(IToken token
, Exception error
, String
[] str
) {
374 TargetResource
[] targets
= new TargetResource
[str
.length
];
375 for (int i
= 0; i
< str
.length
; i
++) {
376 TargetResource tempTarget
= new TargetResource(TraceSubSystem
.this);
377 tempTarget
.setName(str
[i
]);
378 tempTarget
.setParent(provider
);
379 targets
[i
] = tempTarget
;
381 // Notify with target list
385 }}.get(TraceControlConstants
.DEFAULT_TCF_TASK_TIMEOUT
, TimeUnit
.SECONDS
);
386 } catch (Exception e
) {
387 provider
.setTargets(new TargetResource
[0]);
388 if (e
instanceof SystemMessageException
) throw (SystemMessageException
)e
;
389 throw new SystemMessageException(LTTngUiPlugin
.getDefault().getMessage(e
));
392 provider
.setTargets(targets
);
393 for (int i
= 0; i
< targets
.length
; i
++) {
394 if (targets
[i
].getParent().getName().equals(LttngConstants
.Lttng_Provider_Kernel
)) {
395 createTraces(targets
[i
]);
403 * Retrieves the trace instances for a given target from the remote system.
405 private TraceResource
[] createTraces(final TargetResource target
) throws SystemMessageException
{
406 TraceResource
[] traces
;
408 final ILttControllerService service
= getControllerService();
410 // Create future task
411 traces
= new TCFTask
<TraceResource
[]>() {
414 // Get targets using Lttng controller service proxy
415 service
.getTraces(target
.getParent().getName(), target
.getName(), new ILttControllerService
.DoneGetTraces() {
418 public void doneGetTraces(IToken token
, Exception error
, String
[] str
) {
426 TraceResource
[] traces
= new TraceResource
[str
.length
];
427 for (int i
= 0; i
< str
.length
; i
++) {
428 TraceResource trace
= new TraceResource(TraceSubSystem
.this, service
);
429 trace
.setName(str
[i
]);
430 trace
.setParent(target
);
431 trace
.setTraceState(TraceState
.CREATED
);
435 // Notify with trace list
439 }}.get(TraceControlConstants
.DEFAULT_TCF_TASK_TIMEOUT
, TimeUnit
.SECONDS
);
440 } catch (Exception e
) {
441 target
.setTraces(new TraceResource
[0]);
442 if (e
instanceof SystemMessageException
) throw (SystemMessageException
)e
;
443 throw new SystemMessageException(LTTngUiPlugin
.getDefault().getMessage(e
));
446 target
.setTraces(traces
);
448 // get active trace information (is only supported for kernel traces)
449 createTraceConfigurations(target
, traces
);
454 * Retrieves the trace configurations for the given trace from the remote system.
456 private void createTraceConfigurations(final TargetResource target
, TraceResource
[] traces
) throws SystemMessageException
{
457 if (!target
.isUst() && (traces
.length
> 0)) {
459 String
[] activeTraceNames
;
461 final ILttControllerService service
= getControllerService();
462 activeTraceNames
= new TCFTask
<String
[]>() {
465 // Get targets using Lttng controller service proxy
466 service
.getActiveTraces(target
.getParent().getName(), target
.getName(), new ILttControllerService
.DoneGetActiveTraces() {
469 public void doneGetActiveTraces(IToken token
, Exception error
, String
[] str
) {
476 // Notify with active trace list
480 }}.get(TraceControlConstants
.DEFAULT_TCF_TASK_TIMEOUT
, TimeUnit
.SECONDS
);
481 } catch (Exception e
) {
482 if (e
instanceof SystemMessageException
) throw (SystemMessageException
)e
;
483 throw new SystemMessageException(LTTngUiPlugin
.getDefault().getMessage(e
));
486 // get active trace information
487 for (int j
= 0; j
< activeTraceNames
.length
; j
++) {
488 final TraceResource trace
= target
.getTrace(activeTraceNames
[j
]);
491 TraceConfig traceConfig
;
493 // Currently, if a trace is active then all the setup commands have been executed
494 // and it's either started or paused. However, currently there is no means to retrieve
495 // the state (paused or started). So we set it to state started (even if trace is not actually
496 // started on target the command pause will be successful. However, the use will have the wrong
497 // impression that the trace is started) Therefore ... the state needs to be retrievable.
498 // TODO update to correct state if there is a possibility to retrieve the correct state.
499 trace
.setTraceState(TraceState
.STARTED
);
501 final ILttControllerService service
= getControllerService();
502 traceConfig
= new TCFTask
<TraceConfig
>() {
505 // Get targets using Lttng controller service proxy
506 service
.getActiveTraceInfo(target
.getParent().getName(), target
.getName(), trace
.getName(), new ILttControllerService
.DoneGetActiveTraceInfo() {
509 public void doneGetActiveTraceInfo(IToken token
, Exception error
, String
[] str
) {
516 TraceConfig config
= new TraceConfig();
517 config
.setIsAppend(false);
518 if (str
[3].equals("true")) { //$NON-NLS-1$
519 config
.setMode(TraceConfig
.FLIGHT_RECORDER_MODE
);
521 else if (str
[1].equals("true")) { //$NON-NLS-1$
522 config
.setMode(TraceConfig
.NORMAL_MODE
);
525 if (str
[5].equals(TraceConfig
.InvalidTracePath
)) {
526 config
.setNetworkTrace(true);
529 config
.setNetworkTrace(false);
531 config
.setNumChannel(Integer
.valueOf(str
[0]));
532 config
.setTraceName(trace
.getName());
533 config
.setTracePath(str
[5]);
534 config
.setTraceTransport(TraceControlConstants
.Lttng_Trace_Transport_Relay
);
536 // Notify with active trace list
540 }}.get(TraceControlConstants
.DEFAULT_TCF_TASK_TIMEOUT
, TimeUnit
.SECONDS
);
541 } catch (Exception e
) {
542 if (e
instanceof SystemMessageException
) throw (SystemMessageException
)e
;
543 throw new SystemMessageException(LTTngUiPlugin
.getDefault().getMessage(e
));
545 trace
.setTraceConfig(traceConfig
);
553 * @see org.eclipse.rse.core.subsystems.ICommunicationsListener#communicationsStateChange(org.eclipse.rse.core.subsystems.CommunicationsEvent)
556 public void communicationsStateChange(CommunicationsEvent e
) {
557 switch (e
.getState())
559 case CommunicationsEvent
.BEFORE_CONNECT
:
561 case CommunicationsEvent
.AFTER_CONNECT
:
563 case CommunicationsEvent
.BEFORE_DISCONNECT
:
566 final TraceResource
[] traces
= getAllTraces();
568 StringBuffer traceNames
= new StringBuffer(""); //$NON-NLS-1$
569 String filler
= ""; //$NON-NLS-1$
570 for (int j
= 0; j
< traces
.length
; j
++) {
571 // For network traces, ask user to pause tracing
572 if (traces
[j
].isNetworkTraceAndStarted()) {
573 traceNames
.append(filler
);
574 traceNames
.append(traces
[j
].getName());
576 filler
= ", "; //$NON-NLS-1$
578 if (!"".equals(traceNames
.toString())) { //$NON-NLS-1$
579 final String finalTraceNames
= traceNames
.toString();
580 Display
.getDefault().syncExec(new Runnable() {
584 MessageDialog
.openWarning(Display
.getDefault().getActiveShell(), Messages
.Ltt_ShutdownWarning
, Messages
.Ltt_NetworkTraceRunningWarning
+ ":\n" + finalTraceNames
); //$NON-NLS-1$
587 PauseTrace pauseAction
= new PauseTrace();
588 pauseAction
.setSelectedTraces(new ArrayList
<TraceResource
>(Arrays
.asList(traces
)));
589 pauseAction
.run(null);
591 Thread
.sleep(2000); // allow time for target to pause traces before disconnecting the channel
592 } catch (InterruptedException e
) {
599 if (fProviders
!= null) {
600 // reset all providers and it's children
601 for (int i
= 0; i
< fProviders
.length
; i
++) {
602 fProviders
[i
].removeAllTargets();
607 } catch (SystemMessageException ex
) {
608 SystemBasePlugin
.logError("TraceSubSystem", ex
); //$NON-NLS-1$
611 case CommunicationsEvent
.AFTER_DISCONNECT
:
612 getConnectorService().removeCommunicationsListener(this);
614 case CommunicationsEvent
.CONNECTION_ERROR
:
615 // TODO notify user about the lost connection ?!
616 getConnectorService().removeCommunicationsListener(this);
619 } catch (Exception e1
) {
630 * @see org.eclipse.rse.core.subsystems.ICommunicationsListener#isPassiveCommunicationsListener()
633 public boolean isPassiveCommunicationsListener() {
638 * Returns the trace controller service.
640 * @return trace controller service
643 public LttControllerServiceProxy
getControllerService() throws Exception
{
644 return ((TraceConnectorService
)getConnectorService()).getControllerService();