1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 360314: OS awareness debug view

Change-Id: I96b6df8bd5faa7e1da579d9e45580004170ac1e9
Reviewed-on: https://git.eclipse.org/r/5835
Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com>
IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com>
Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
Vladimir Prus 2012-05-05 12:54:55 +04:00 committed by Mikhail Khodjaiants
parent 52cf5f2b85
commit 5439a6af9e
19 changed files with 2022 additions and 3 deletions

View file

@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb.ui;singleton:=true
Bundle-Version: 2.3.0.qualifier
Bundle-Version: 2.4.0.qualifier
Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
@ -32,6 +32,7 @@ Export-Package: org.eclipse.cdt.dsf.gdb.internal.ui;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.commands;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.console;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.launching;x-friends:="org.eclipse.cdt.debug.gdbjtag.ui",
org.eclipse.cdt.dsf.gdb.internal.ui.osview;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.preferences;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.tracepointactions;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints;x-internal:=true,

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2008, 2010 Ericsson and others.
# Copyright (c) 2008, 2012 Ericsson and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@ -9,6 +9,7 @@
# Ericsson - initial API and implementation
# IBM Corporation
# Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
# Vladimir Prus (Mentor Graphics) - OS Resources view (bug 360314)
###############################################################################
pluginName=GDB DSF Debugger Integration UI
providerName=Eclipse CDT
@ -47,3 +48,6 @@ activity.name = CDT DSF-GDB - GDB Debugging
# Pretty Printing
action.fetchMoreChildren.label=Fetch More Children
# OS view
view.osresources.name=OS Resources

View file

@ -263,6 +263,13 @@
id="org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view"
name="%view.traceControl.name">
</view>
<view
category="org.eclipse.debug.ui"
class="org.eclipse.cdt.dsf.gdb.internal.ui.osview.OSResourcesView"
id="org.eclipse.cdt.dsf.gdb.ui.osresources.view"
name="%view.osresources.name"
icon="icons/full/view16/osresources_view.gif">
</view>
</extension>
<extension
point="org.eclipse.ui.perspectiveExtensions">

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>2.3.0-SNAPSHOT</version>
<version>2.4.0-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.dsf.gdb.ui</artifactId>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -0,0 +1,143 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.jface.dialogs.IDialogSettings;
/* Hold information about which columns in a table are visible, and what
* width they have. Stores that information inside preferences store.
*/
class ColumnLayout
{
private String fResourceClass;
private Map<String, Boolean> fVisible = new HashMap<String, Boolean>();
private Map<String, Integer> fWidth = new HashMap<String, Integer>();
private Integer fSortColumn = null;
private Integer fSortDirection = null;
private static IDialogSettings settings;
private static IDialogSettings getDialogSettings()
{
if (settings != null)
return settings;
IDialogSettings topSettings = GdbUIPlugin.getDefault().getDialogSettings();
settings = topSettings.getSection(ResourceClassContributionItem.class.getName());
if (settings == null) {
settings = topSettings.addNewSection(ResourceClassContributionItem.class.getName());
}
return settings;
}
private static void setDefaultSetting(String key, boolean value)
{
IDialogSettings s = getDialogSettings();
if (s.get(key) == null)
s.put(key, value);
}
private static void setDefaultSetting(String key, int value)
{
IDialogSettings s = getDialogSettings();
if (s.get(key) == null)
s.put(key, value);
}
public ColumnLayout(String resourceClass)
{
fResourceClass = resourceClass;
}
public boolean getVisible(String column)
{
if (fVisible.containsKey(column))
return fVisible.get(column);
else
{
setDefaultSetting(columnKey(column, "v"), true); //$NON-NLS-1$
boolean b = getDialogSettings().getBoolean(columnKey(column, "v")); //$NON-NLS-1$
fVisible.put(column, b);
return b;
}
}
public void setVisible(String column, boolean visible)
{
fVisible.put(column, visible);
getDialogSettings().put(columnKey(column, "v"), visible); //$NON-NLS-1$
}
public int getWidth(String column)
{
if (fWidth.containsKey(column))
return fWidth.get(column);
else
{
setDefaultSetting(columnKey(column, "w"), -1); //$NON-NLS-1$
int w = getDialogSettings().getInt(columnKey(column, "w")); //$NON-NLS-1$
fWidth.put(column, w);
return w;
}
}
public void setWidth(String column, int width)
{
fWidth.put(column, width);
getDialogSettings().put(columnKey(column, "w"), width); //$NON-NLS-1$
}
public int getSortColumn()
{
if (fSortColumn == null)
{
setDefaultSetting(globalKey("sortColumn"), 0); //$NON-NLS-1$
fSortColumn = getDialogSettings().getInt(globalKey("sortColumn")); //$NON-NLS-1$
}
return fSortColumn;
}
public void setSortColumn(int column)
{
fSortColumn = column;
getDialogSettings().put(globalKey("sortColumn"), fSortColumn); //$NON-NLS-1$
}
public int getSortDirection()
{
if (fSortDirection == null)
{
setDefaultSetting(globalKey("sortDirection"), 1); //$NON-NLS-1$
fSortDirection = getDialogSettings().getInt(globalKey("sortDirection")); //$NON-NLS-1$
}
return fSortDirection;
}
public void setSortDirection(int direction)
{
fSortDirection = direction;
getDialogSettings().put(globalKey("sortDirection"), fSortDirection); //$NON-NLS-1$
}
private String columnKey(String column, String what)
{
return "columnLayout." + fResourceClass + "." + column + "." + what; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
private String globalKey(String what)
{
return "columnLayout." + fResourceClass + "." + what; //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
/** Helper class to change table and label provider of a TreeViewer in an atomic fashion.
*
* Suppose we want to change both content and label provider of existing TreeViewer. Right now,
* if we set either, TreeViewer will try a refresh, using one new provider and one old. This
* is obviously nonsensical -- for example if we set set new content provider, then old label provider
* will be asked to provide labels for elements it has no idea what to do with, or for columns beyond
* its range, etc.
*
* This class is wrapping our real content provider, and can be retargeted in one call -- after which
* refresh of TreeViewer sees consistent data.
*
* @since 2.4
* */
public class ContentLabelProviderWrapper<U extends ITableLabelProvider & IStructuredContentProvider>
implements ITableLabelProvider, IStructuredContentProvider
{
public ContentLabelProviderWrapper(U realProvider)
{
this.realProvider = realProvider;
}
public void setData(U realProvider)
{
this.realProvider = realProvider;
}
@Override
public Image getColumnImage(Object obj, int index) {
return realProvider.getColumnImage(obj, index);
}
@Override
public void addListener(ILabelProviderListener listener) {
realProvider.addListener(listener);
}
@Override
public boolean isLabelProperty(Object element, String property) {
return realProvider.isLabelProperty(element, property);
}
@Override
public void removeListener(ILabelProviderListener listener) {
realProvider.removeListener(listener);
}
@Override
public String getColumnText(Object obj, int index) {
return realProvider.getColumnText(obj, index);
}
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
realProvider.inputChanged(v, oldInput, newInput);
}
@Override
public void dispose() {
realProvider.dispose();
}
@Override
public Object[] getElements(Object parent) {
return realProvider.getElements(parent);
}
private U realProvider;
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import org.eclipse.osgi.util.NLS;
/**
* @since 2.4
*/
public class Messages extends NLS {
public static String OSView_3;
public static String OSView_4;
public static String OSView_5;
public static String OSView_6;
public static String OSView_7;
public static String OSView_8;
public static String OSView_9;
public static String OSView_10;
public static String OSView_11;
public static String OSView_12;
public static String OSView_13;
public static String OSView_14;
static {
// initialize resource bundle
NLS.initializeMessages(Messages.class.getName(), Messages.class);
}
private Messages() {
}
}

View file

@ -0,0 +1,22 @@
###############################################################################
# Copyright (c) 2011, 2012 Mentor Graphics and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Vladimir Prus (Mentor Graphics) - initial API and implementation
###############################################################################
OSView_3=Refresh
OSView_4=No debug session is selected.
OSView_5=Please select resource class.
OSView_6=Fetching data...
OSView_7=No data has been fetched yet. <a href="{0}">Fetch now</a>.
OSView_8='Refresh (last fetched on' h:mm:ss ')'
OSView_9=Updating OS resources view
OSView_10=OS resources are not available using your target and GDB.
OSView_11=Determining available OS resource classes...
OSView_12=No data has been fetched yet. Target is busy.
OSView_13=Waiting for the debug session to initialize.
OSView_14=Objects from different debug sessions are selected.

View file

@ -0,0 +1,148 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2.IResourcesInformation;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
/* Table data provider that exposes information about OS resources
* of specific class. Constructed from MI output. Once constructed,
* this class is immutable.
*/
class OSData
extends LabelProvider
implements ITableLabelProvider, IStructuredContentProvider
{
private IResourcesInformation data;
private boolean[] columnIsInteger;
private List<Integer> remap;
public OSData(String resourceClass, IResourcesInformation data) {
this.data = data;
determineColumnTypes();
remap = new ArrayList<Integer>(data.getColumnNames().length);
for (int i = 0; i < data.getColumnNames().length; ++i)
remap.add(i);
if (resourceClass.equals("processes")) //$NON-NLS-1$
sendToEnd("Command"); //$NON-NLS-1$
if (resourceClass.equals("threads")) //$NON-NLS-1$
sendToEnd("Command"); //$NON-NLS-1$
if (resourceClass.equals("modules")) //$NON-NLS-1$
sendToEnd("Dependencies"); //$NON-NLS-1$
}
// Determine column types, for the purpose of proper sorting
private void determineColumnTypes()
{
String[] columnNames = data.getColumnNames();
String[][] content = data.getContent();
columnIsInteger = new boolean[columnNames.length];
boolean[] columnHasInteger = new boolean[columnNames.length];
boolean[] columnHasOther = new boolean[columnNames.length];
for (int i = 0; i < content.length; ++i) {
for (int j = 0; j < content[i].length; ++j) {
if (!columnHasOther[j])
{
try {
Integer.parseInt(content[i][j]);
columnHasInteger[j] = true;
}
catch(NumberFormatException e) {
columnHasOther[j] = true;
}
catch(Throwable e) {
e.printStackTrace();
}
}
}
}
for (int j = 0; j < data.getColumnNames().length; ++j) {
columnIsInteger[j] = columnHasInteger[j] && !columnHasOther[j];
}
}
/* Make column named 'column' appear last in UI. */
private void sendToEnd(String column)
{
// Find index in the remap array (which is equal to index in UI)
// at which column named 'column' is found.
int index = -1;
for (int i = 0; i < remap.size(); ++i)
if (data.getColumnNames()[remap.get(i)].equals(column)) {
index = i;
break;
}
if (index == -1)
return;
// Move the element to the end of the list
remap.add(remap.remove(index));
}
public int getColumnCount()
{
return remap.size();
}
public String getColumnName(int i)
{
return data.getColumnNames()[remap.get(i)];
}
public boolean getColumnIsInteger(int j) {
return columnIsInteger[remap.get(j)];
}
@Override
public String getColumnText(Object obj, int index) {
return ((String[]) obj)[remap.get(index)];
}
@Override
public Image getColumnImage(Object obj, int index) {
return getImage(obj);
}
@Override
public Image getImage(Object obj) {
return null;
}
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
@Override
public void dispose() {
}
@Override
public Object[] getElements(Object parent) {
return data.getContent();
}
}

View file

@ -0,0 +1,641 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.debug.ui.contexts.IDebugContextListener;
import org.eclipse.debug.ui.contexts.IDebugContextManager;
import org.eclipse.debug.ui.contexts.IDebugContextService;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;
import org.osgi.framework.Bundle;
/**
* @since 2.4
*/
public class OSResourcesView extends ViewPart implements DsfSession.SessionEndedListener {
private final static String FETCH_LINK_TAG = "fetch"; //$NON-NLS-1$
// The data model for the selected session, or null if no session is
// selected.
private SessionOSData fSessionData;
private Map<String, SessionOSData> fSessionDataCache = new HashMap<String, SessionOSData>();
// The data presently shown by table viewer.
private OSData fTableShownData = null;
// The data which was used to populate column selector menu
private OSData fMenuShownData = null;
private String fResourceClass = null;
// Indicates that we've selected objects from different debug sessions.
boolean fMultiple = false;
// UI objects
private TableViewer fViewer;
private Comparator fComparator;
private Composite fNothingLabelContainer;
private Link fNothingLabel;
private ResourceClassContributionItem fResourceClassEditor;
private Action fRefreshAction;
// Map from resource class name to table column layout.
private Map<String, ColumnLayout> fColumnLayouts = new HashMap<String, ColumnLayout>();
private ColumnLayout fColumnLayout = null;
private IDebugContextListener fDebugContextListener;
@Override
public void createPartControl(Composite xparent) {
Composite parent = new Composite(xparent, SWT.NONE);
GridLayout topLayout = new GridLayout(1, false);
topLayout.marginWidth = 0;
topLayout.marginHeight = 0;
parent.setLayout(topLayout);
fViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
GridData viewerData = new GridData(GridData.FILL_BOTH);
viewerData.exclude = true;
fViewer.getControl().setLayoutData(viewerData);
fViewer.setComparator(fComparator = new Comparator());
Table table = fViewer.getTable();
table.setHeaderVisible(true);
table.setVisible(false);
fNothingLabelContainer = new Composite(parent, SWT.NONE);
GridData nothingLayout = new GridData(SWT.FILL, SWT.FILL, true, true);
fNothingLabelContainer.setLayoutData(nothingLayout);
GridLayout containerLayout = new GridLayout(1, false);
fNothingLabelContainer.setLayout(containerLayout);
fNothingLabel = new Link(fNothingLabelContainer, SWT.BORDER);
fNothingLabel.setText(Messages.OSView_4);
fNothingLabel.setBackground(fNothingLabel.getDisplay().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
fNothingLabel.addListener (SWT.Selection, new Listener () {
@Override
public void handleEvent(Event event) {
if (event.text.equals("fetch")) //$NON-NLS-1$
if (fSessionData != null && fResourceClass != null)
fSessionData.fetchData(fResourceClass);
}
});
fNothingLabelContainer.setBackground(fNothingLabel.getBackground());
GridData nothingLabelLayout = new GridData(SWT.CENTER, SWT.TOP, true, false);
fNothingLabel.setLayoutData(nothingLabelLayout);
fResourceClassEditor = new ResourceClassContributionItem();
fResourceClassEditor.setListener(new ResourceClassContributionItem.Listener() {
@Override
public void resourceClassChanged(String newClass) {
fResourceClass = newClass;
// Since user explicitly changed the class, initiate fetch immediately.
fSessionData.fetchData(fResourceClass);
// Do not call 'update()' here. fetchData call above will notify
// us at necessary moments.
}
});
IActionBars bars = getViewSite().getActionBars();
bars.getToolBarManager().add(fResourceClassEditor);
fRefreshAction = new Action() {
@Override
public void run() {
if (fSessionData != null && fResourceClass != null)
fSessionData.fetchData(fResourceClass);
}
};
fRefreshAction.setText(Messages.OSView_3);
fRefreshAction.setToolTipText(Messages.OSView_3);
try {
Bundle bundle= Platform.getBundle("org.eclipse.ui"); //$NON-NLS-1$
URL url = bundle.getEntry("/"); //$NON-NLS-1$
url = new URL(url, "icons/full/elcl16/refresh_nav.gif"); //$NON-NLS-1$
ImageDescriptor candidate = ImageDescriptor.createFromURL(url);
if (candidate != null && candidate.getImageData() != null) {
fRefreshAction.setImageDescriptor(candidate);
}
} catch (Exception e) {
}
bars.getToolBarManager().add(fRefreshAction);
bars.updateActionBars();
fResourceClass = fResourceClassEditor.getResourceClassId();
setupContextListener();
DsfSession.addSessionEndedListener(this);
}
private void setupContextListener() {
IDebugContextManager contextManager = DebugUITools.getDebugContextManager();
IDebugContextService contextService = contextManager
.getContextService(getSite().getWorkbenchWindow());
fDebugContextListener = new IDebugContextListener() {
@Override
public void debugContextChanged(DebugContextEvent event) {
if ((event.getFlags() & DebugContextEvent.ACTIVATED) != 0) {
ISelection s = event.getContext();
setDebugContext(s);
}
}
};
contextService.addDebugContextListener(fDebugContextListener);
setDebugContext(contextService.getActiveContext());
}
@Override
public void dispose() {
super.dispose();
IDebugContextManager contextManager = DebugUITools.getDebugContextManager();
IDebugContextService contextService = contextManager
.getContextService(getSite().getWorkbenchWindow());
contextService.removeDebugContextListener(fDebugContextListener);
setDebugContext((ICommandControlDMContext)null);
DsfSession.removeSessionEndedListener(this);
}
private void setDebugContext(ISelection s) {
ICommandControlDMContext context = null;
fMultiple = false;
if (s instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) s;
if (ss.size() > 0) {
@SuppressWarnings("rawtypes")
Iterator i = ss.iterator();
context = getCommandControlContext(i.next());
while (i.hasNext()) {
ICommandControlDMContext nextContext = getCommandControlContext(i.next());
if (nextContext == null && context != null
|| nextContext != null && context == null
|| nextContext != null && context != null && !nextContext.equals(context))
{
context = null;
fMultiple = true;
break;
}
}
}
}
setDebugContext(context);
}
private ICommandControlDMContext getCommandControlContext(Object obj) {
IDMContext context = null;
if (obj instanceof IDMVMContext)
context = ((IDMVMContext)obj).getDMContext();
else if (obj instanceof GdbLaunch) {
GdbLaunch l = (GdbLaunch)obj;
final DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), l.getSession().getId());
Query<IDMContext> contextQuery = new Query<IDMContext>() {
@Override
protected void execute(DataRequestMonitor<IDMContext> rm) {
ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
tracker.dispose();
if (commandControl != null)
{
rm.setData(commandControl.getContext());
}
rm.done();
}
};
l.getSession().getExecutor().submit(contextQuery);
try {
context = contextQuery.get();
} catch (Exception e) {
}
}
return DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
}
private void setDebugContext(ICommandControlDMContext context)
{
DsfSession newSession = null;
SessionOSData newSessionData = null;
if (context != null)
{
newSession = DsfSession.getSession(context.getSessionId());
}
if (newSession != null)
{
newSessionData = fSessionDataCache.get(newSession.getId());
if (newSessionData == null)
{
newSessionData = new SessionOSData(newSession, context);
fSessionDataCache.put(newSession.getId(), newSessionData);
newSessionData.setUIListener(new SessionOSData.Listener() {
@Override
public void update() {
// Note that fSessionData always calls the listener in
// UI thread, so we can directly call 'update' here.
OSResourcesView.this.update();
}
}, fViewer.getControl());
}
}
if (newSessionData != fSessionData)
{
fSessionData = newSessionData;
update();
}
}
@Override
public void sessionEnded(DsfSession session) {
String id = session.getId();
SessionOSData data = fSessionDataCache.remove(id);
if (data != null) {
data.dispose();
}
}
private void update() {
if (fViewer == null || fViewer.getControl() == null)
return;
if (fViewer.getControl().isDisposed())
return;
if (fSessionData == null)
{
hideTable(fMultiple ? Messages.OSView_14 : Messages.OSView_4);
fResourceClassEditor.setEnabled(false);
fRefreshAction.setEnabled(false);
return;
}
boolean enable = fSessionData.canFetchData();
fRefreshAction.setEnabled(enable);
fResourceClass = fResourceClassEditor.updateClasses(fSessionData.getResourceClasses());
fResourceClassEditor.setEnabled(enable);
if (!fSessionData.osResourcesSupported()) {
fRefreshAction.setEnabled(false);
fResourceClassEditor.setEnabled(false);
hideTable(Messages.OSView_10);
return;
}
if (fSessionData.waitingForSessionInitialization()) {
fRefreshAction.setEnabled(false);
fResourceClassEditor.setEnabled(false);
hideTable(Messages.OSView_13);
return;
}
if (fSessionData.fetchingClasses()) {
fRefreshAction.setEnabled(false);
fResourceClassEditor.setEnabled(false);
hideTable(Messages.OSView_11);
return;
}
if (fResourceClass == null)
{
fRefreshAction.setEnabled(false);
fResourceClassEditor.setEnabled(true);
hideTable(Messages.OSView_5);
return;
}
final OSData data = fSessionData.existingData(fResourceClass);
if (fSessionData.fetchingContent())
{
hideTable(Messages.OSView_6);
}
else if (data == null)
{
if (fSessionData.canFetchData())
hideTable(NLS.bind(Messages.OSView_7, FETCH_LINK_TAG));
else
hideTable(Messages.OSView_12);
}
else
{
SimpleDateFormat format = new SimpleDateFormat(Messages.OSView_8);
fRefreshAction.setToolTipText(format.format(fSessionData.timestamp(fResourceClass)));
if (data != fTableShownData)
{
Job job = new UIJob(Messages.OSView_9) {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
fTableShownData = data;
populateTable(data);
showTable();
return Status.OK_STATUS;
}
};
job.setPriority(Job.INTERACTIVE);
job.schedule();
}
else
{
assert fViewer.getTable().getColumnCount() == data.getColumnCount();
showTable();
}
}
fRefreshAction.setEnabled(fSessionData.canFetchData());
fResourceClassEditor.setEnabled(fSessionData.canFetchData());
}
/* Hide the table that would show OS awareness data if it were available. Display
* 'message' instead.
*/
private void hideTable(String message) {
setContentDescription(""); //$NON-NLS-1$
fViewer.getControl().setVisible(false);
((GridData) fViewer.getControl().getLayoutData()).exclude = true;
fNothingLabelContainer.setVisible(true);
((GridData) fNothingLabelContainer.getLayoutData()).exclude = false;
fNothingLabelContainer.getParent().layout();
fNothingLabel.setText(message);
fNothingLabelContainer.layout();
// If the table is not shown, we don't want the menu to have stale
// list of columns to select from.
IActionBars bars = getViewSite().getActionBars();
bars.getMenuManager().removeAll();
bars.updateActionBars();
fMenuShownData = null;
}
private void showTable() {
assert fTableShownData != null;
fViewer.getControl().setVisible(true);
((GridData) fViewer.getControl().getLayoutData()).exclude = false;
fNothingLabelContainer.setVisible(false);
((GridData) fNothingLabelContainer.getLayoutData()).exclude = true;
fNothingLabelContainer.getParent().layout();
populateViewMenu(fTableShownData);
}
private void populateTable(final OSData data)
{
final Table table = fViewer.getTable();
while (table.getColumnCount() > 0)
table.getColumns()[0].dispose();
fColumnLayout = fColumnLayouts.get(fResourceClass);
if (fColumnLayout == null)
{
fColumnLayout = new ColumnLayout(fResourceClass);
fColumnLayouts.put(fResourceClass, fColumnLayout);
}
for (int i = 0; i < data.getColumnCount(); ++i) {
final String cn = data.getColumnName(i);
final TableColumn c = new TableColumn(table, SWT.LEFT);
c.setText(cn);
c.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event event) {
fColumnLayout.setWidth(cn, c.getWidth());
}
});
final int final_index = i;
c.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int dir = table.getSortDirection();
if (table.getSortColumn() == c) {
dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
} else {
dir = SWT.DOWN;
}
table.setSortDirection(dir);
table.setSortColumn(c);
fComparator.configure(final_index, data);
fComparator.setDirection(dir == SWT.DOWN ? 1 : -1);
fColumnLayout.setSortColumn(final_index);
fColumnLayout.setSortDirection(dir == SWT.DOWN ? 1 : -1);
fViewer.refresh();
}
});
}
populateViewMenu(data);
int sortColumn = fColumnLayout.getSortColumn();
if (sortColumn < data.getColumnCount())
{
fComparator.configure(sortColumn, data);
}
fComparator.setDirection(fColumnLayout.getSortDirection());
fViewer.getTable().setEnabled(true);
if (fViewer.getContentProvider() == null)
{
ContentLabelProviderWrapper<OSData> wrapper =
new ContentLabelProviderWrapper<OSData>(data);
fViewer.setContentProvider(wrapper);
fViewer.setLabelProvider(wrapper);
}
else
{
// Retarget current content/label providers in atomic fashion. See comments
// on ContentLabelProviderWrapper.
@SuppressWarnings("unchecked")
ContentLabelProviderWrapper<OSData> wrapper = (ContentLabelProviderWrapper<OSData>)fViewer.getContentProvider();
wrapper.setData(data);
}
fViewer.setInput(getViewSite());
fViewer.getControl().setVisible(true);
for (int i = 0; i < fViewer.getTable().getColumnCount(); ++i)
{
TableColumn col = fViewer.getTable().getColumns()[i];
String cn = col.getText();
if (i == sortColumn) {
table.setSortDirection(fColumnLayout.getSortDirection() == 1 ? SWT.DOWN : SWT.UP);
table.setSortColumn(col);
}
if (fColumnLayout.getVisible(cn))
{
int w = fColumnLayout.getWidth(cn);
if (w > 0)
col.setWidth(w);
else
col.pack();
}
else
{
col.setWidth(0);
col.setResizable(false);
}
}
}
private void populateViewMenu(final OSData data) {
assert data.getColumnCount() == fViewer.getTable().getColumnCount();
if (data == fMenuShownData)
return;
IActionBars bars = getViewSite().getActionBars();
bars.getMenuManager().setVisible(true);
bars.getMenuManager().removeAll();
for (int i = 0; i < data.getColumnCount(); ++i) {
final String cn = data.getColumnName(i);
final TableColumn c = fViewer.getTable().getColumns()[i];
Action a = new Action(cn, IAction.AS_CHECK_BOX) {
@Override
public void run() {
if (isChecked()) {
int w = fColumnLayout.getWidth(cn);
if (w > 0)
c.setWidth(w);
else
c.pack();
c.setResizable(true);
} else {
int w = c.getWidth();
c.setWidth(0);
// Make sure we remember the width the column
// had before hiding.
fColumnLayout.setWidth(cn, w);
c.setResizable(false);
}
fColumnLayout.setVisible(cn, isChecked());
}
};
a.setChecked(fColumnLayout.getVisible(cn));
a.setText(cn);
bars.getMenuManager().add(a);
}
bars.updateActionBars();
fMenuShownData = data;
}
class Comparator extends ViewerComparator
{
private int fColumn = 0;
private OSData fData;
private boolean fInteger = false;
private int fDirection = 1;
public void configure(int column, OSData data)
{
fColumn = column;
fData = data;
fInteger = data.getColumnIsInteger(column);
}
public void setDirection(int direction)
{
assert direction == 1 || direction == -1;
fDirection = direction;
}
@Override
public int compare(Viewer viewer, Object xe1, Object xe2) {
String v1 = fData.getColumnText(xe1, fColumn);
String v2 = fData.getColumnText(xe2, fColumn);
if (fInteger) {
Integer i1 = Integer.parseInt(v1);
Integer i2 = Integer.parseInt(v2);
return fDirection*(i1 - i2);
} else {
return fDirection*(v1.compareTo(v2));
}
}
};
@Override
public void setFocus() {
fViewer.getControl().setFocus();
}
}

View file

@ -0,0 +1,210 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2.IResourceClass;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
/**
* @since 2.4
*/
public class ResourceClassContributionItem extends ContributionItem {
// In some places below, we are trying to determine size hint for Combo, given the list of
// content. However, while we can determine width of content, we don't know how much width
// the combobox itself is adding. This constant is our guess.
private static final int COMBO_TRIM_WIDTH = 64;
interface Listener
{
void resourceClassChanged(String newClass);
}
private Combo fResourceClassCombo;
private IResourceClass[] resourceClasses = new IResourceClass[0];
private String fResourceClassId = null;
private Listener fListener;
private boolean blockListener = false;
private ToolItem toolItem;
private boolean enabled = true;
private static IDialogSettings settings;
private static IDialogSettings getDialogSettings()
{
if (settings != null)
return settings;
IDialogSettings topSettings = GdbUIPlugin.getDefault().getDialogSettings();
settings = topSettings.getSection(ResourceClassContributionItem.class.getName());
if (settings == null) {
settings = topSettings.addNewSection(ResourceClassContributionItem.class.getName());
}
return settings;
}
public void setListener(Listener listener) {
fListener = listener;
}
public void setEnabled(boolean enable) {
// It appears that every update of action bars will call 'fill' action below, creating
// combo. So, we want to keep 'enabled' state as member variable, to make sure it is kept
// if combo is recreated.
enabled = enable;
if (fResourceClassCombo != null)
fResourceClassCombo.setEnabled(enable);
}
public String updateClasses(IResourceClass[] resourceClasses) {
boolean different = false;
if (this.resourceClasses.length != resourceClasses.length)
different = true;
else for (int i = 0; i < this.resourceClasses.length; ++i) {
if (!this.resourceClasses[i].getId().equals(resourceClasses[i].getId())
|| !this.resourceClasses[i].getHumanDescription().equals(resourceClasses[i].getHumanDescription()))
{
different = true;
break;
}
}
if (!different)
return fResourceClassId;
this.resourceClasses = resourceClasses;
fResourceClassCombo.removeAll();
final int width = populateCombo();
// Now change the width. Call to setWidth causes relayout automatically.
// IMPORTANT: the visibility check is critical. Without it, we appear to have hit
// an SWT/Gtk bug whenever a debug session and a previously use OS resources view
// is not shown. The bug manifests by 100% CPU consumption inside event loop, and
// it further blocks asyncExec runnables from ever executing. I suppose it might
// be specific to relayout of invisible toolbar.
// If we're invisible, we don't arrange for relayout to happen when the view becomes
// available, because it is not exactly trivial (we need to events on the right control)
// and it only matters when we start a new session and it has a different set of
// resource classes and that requires longer combobox.
if (toolItem.getParent().isVisible())
toolItem.setWidth(width);
return fResourceClassId;
}
/** Populate the combobox with resource classes. Return the width the
* combobox must have, including any trim. If there are no resource classes,
* returns some reasonable default width.
*/
private int populateCombo() {
int width = 0;
String lastResourceClassId = getDialogSettings().get("resourceClass"); //$NON-NLS-1$
int index = -1;
int i = 0;
GC gc = new GC(fResourceClassCombo);
for (i = 0; i < resourceClasses.length; ++i) {
String description = resourceClasses[i].getHumanDescription();
width = Math.max(width, gc.textExtent(description).x);
fResourceClassCombo.add(description);
if (resourceClasses[i].getId().equals(lastResourceClassId))
index = i;
}
if (index != -1) {
fResourceClassId = lastResourceClassId;
blockListener = true;
fResourceClassCombo.select(index);
blockListener = false;
}
if (width == 0) {
// We have some hints what the longest element in combo will be. Even if it's different
// in new GDB version, no problem -- the combo will be resized when it's populated.
width = gc.textExtent("Shared memory regions").x; //$NON-NLS-1$
}
// Because there's no way whatsoever to set the width
// of the combobox list, only complete length, we just add
// random padding.
width = width + COMBO_TRIM_WIDTH;
return width;
}
public String getResourceClassId() {
return fResourceClassId;
}
@Override
public void fill(ToolBar parent, int toolbarItemIndex) {
fResourceClassCombo = new Combo(parent, SWT.NONE);
fResourceClassCombo.setEnabled(enabled);
int width = populateCombo();
fResourceClassCombo.addSelectionListener(new SelectionListener() {
@SuppressWarnings({ "null"})
@Override
public void widgetSelected(SelectionEvent e) {
String description = fResourceClassCombo.getText();
String id = null;
for (int i = 0; i < resourceClasses.length; ++i)
if (resourceClasses[i].getHumanDescription().equals(description)) {
id = resourceClasses[i].getId();
break;
}
// id is never null here, unless we messed up our data structures.
assert id != null;
if (id != null && !id.equals(fResourceClassId))
{
fResourceClassId = id;
getDialogSettings().put("resourceClass", id); //$NON-NLS-1$
if (fListener != null && !blockListener)
fListener.resourceClassChanged(fResourceClassId);
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
toolItem = new ToolItem(parent, SWT.SEPARATOR);
toolItem.setControl(fResourceClassCombo);
toolItem.setWidth(width);
}
@Override
public boolean isDynamic() {
return false;
}
}

View file

@ -0,0 +1,292 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.osview;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2;
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osgi.framework.BundleContext;
/** Responsible for fetching and storing OS awareness data for a
* specific DSF session.
*
* @since 2.4
*/
public class SessionOSData {
private DsfSession fSession;
private DsfServicesTracker fTracker;
private IGDBHardwareAndOS2 fHardwareOs;
private ICommandControlDMContext fContext;
private IGDBHardwareAndOS2.IResourceClass[] fResourceClasses = new IGDBHardwareAndOS2.IResourceClass[0];
private Map<String, OSData> fExistingData = new HashMap<String, OSData>();
private Map<String, Date> fTimestamp = new HashMap<String, Date>();
private Listener fUIListener;
private Control fUIControl;
private boolean fWaitingForSession = true;
private boolean fSupported = true;
private boolean fAcceptingCommands = false;
private boolean fFetchingClasses = false;
private boolean fFetchingContent = false;
public SessionOSData(DsfSession session, final ICommandControlDMContext executionContext)
{
fSession = session;
BundleContext c = GdbUIPlugin.getDefault().getBundle().getBundleContext();
fTracker = new DsfServicesTracker(c, fSession.getId());
fContext = executionContext;
final DsfExecutor executor = fSession.getExecutor();
executor.submit(new DsfRunnable() {
@Override
public void run() {
IMIRunControl runControl = fTracker.getService(IMIRunControl.class);
fAcceptingCommands = runControl.isTargetAcceptingCommands();
fSession.addServiceEventListener(SessionOSData.this, null);
fHardwareOs = fTracker.getService(IGDBHardwareAndOS2.class);
if (fHardwareOs == null) {
fSupported = false;
notifyUI();
return;
}
if (fHardwareOs.isAvailable()) {
fetchClasses();
}
}
});
}
@ConfinedToDsfExecutor("")
private void fetchClasses()
{
fWaitingForSession = false;
fFetchingClasses = true;
fHardwareOs.getResourceClasses(fContext, new DataRequestMonitor<IGDBHardwareAndOS2.IResourceClass[]>(fSession.getExecutor(), null) {
@Override
@ConfinedToDsfExecutor("fExecutor")
protected void handleCompleted() {
if (isSuccess())
{
fResourceClasses = getData();
if (fResourceClasses.length == 0)
fSupported = false;
}
else
{
fSupported = false;
}
fFetchingClasses = false;
notifyUI();
}
});
}
@DsfServiceEventHandler
public void eventDispatched(DataModelInitializedEvent e) {
// If we see this event, it necessary means that by the time we've set event listener,
// isAvailable() was returning false, so we need to fetch classes now.
if (fHardwareOs != null)
fetchClasses();
}
public boolean waitingForSessionInitialization()
{
return fWaitingForSession;
}
public boolean osResourcesSupported()
{
return fSupported;
}
public void dispose()
{
fSession.removeServiceEventListener(SessionOSData.this);
fTracker.dispose();
}
public IGDBHardwareAndOS2.IResourceClass[] getResourceClasses()
{
return fResourceClasses;
}
/** Returns OS awareness data for given resource class that
* was previously fetched, or null if none was ever fetched.
*/
public OSData existingData(String resourceClass)
{
return fExistingData.get(resourceClass);
}
/** Returns the timestamp at which data for 'resourceClass' have
* been obtained.
* @pre existingData(resourceClass) != null
*/
public Date timestamp(String resourceClass)
{
return fTimestamp.get(resourceClass);
}
/** Returns true if fresh data can be fetched at this time.
* Generally, it's possible if we're not fetching data already,
* and if GDB is accepting commands right now.
*
*/
public boolean canFetchData()
{
return fAcceptingCommands && !fFetchingContent;
}
public boolean fetchingClasses()
{
return fFetchingClasses;
}
/** Returns true if we're presently fetching data. This can
* be used to provide some feedback to the user.
*/
public boolean fetchingContent()
{
return fFetchingContent;
}
/** Fetches up-to-date data for resourceClass. Listeners will be
* informed when the new data is available. */
public void fetchData(final String resourceClass)
{
fFetchingContent = true;
notifyUI();
final DsfExecutor executor = fSession.getExecutor();
executor.submit(new DsfRunnable() {
@Override
public void run() {
fHardwareOs.getResourcesInformation(fContext, resourceClass, new DataRequestMonitor<IGDBHardwareAndOS2.IResourcesInformation>(executor, null) {
@Override
@ConfinedToDsfExecutor("fExecutor")
protected void handleCompleted() {
fFetchingContent = false;
if (isSuccess())
{
OSData data = new OSData(resourceClass, getData());
fExistingData.put(resourceClass, data);
fTimestamp.put(resourceClass, new Date());
}
else
{
StatusManager.getManager().handle(getStatus(), StatusManager.BLOCK);
}
notifyUI();
}
});
}
});
}
public interface Listener
{
void update();
}
/** Setup the listener that will be notified whenever externally
* visible state changes. The listener will always be invoked
* in the UI thread. 'control' is the control associated with
* the listener. The listener will not be called if the control
* is disposed.
*/
public void setUIListener(Listener listener, Control control)
{
fUIListener = listener;
fUIControl = control;
}
private void notifyUI()
{
final Control c = fUIControl;
if (c != null && !c.isDisposed())
// There be dragons: if you try to use c.getDisplay() below, then this Runnable will not
// run until resource view is actually visible. And it will also block other interesting
// async/job runnables, like perspective switch runnable using during debug launch,
// causing launch to be stuck at random point.
//
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (!c.isDisposed())
fUIListener.update();
}
});
}
@DsfServiceEventHandler
public void eventDispatched(IResumedDMEvent e) {
if (e instanceof IContainerResumedDMEvent) {
// This event is raised only in all-stop. It does not
// seem to be possible to issue -info-os in all-stop,
// regardless of whether target-async is in effect, and
// according to DSF folks, all-stop+target-async will
// not work anyway. So, we assume that no commands
// can be issued right now.
fAcceptingCommands = false;
notifyUI();
}
}
@DsfServiceEventHandler
public void eventDispatched(ISuspendedDMEvent e) {
if (e instanceof IContainerSuspendedDMEvent) {
fAcceptingCommands = true;
notifyUI();
}
}
}

View file

@ -0,0 +1,95 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
import java.util.Hashtable;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
/**
* @since 4.2
*/
public class GDBHardwareAndOS_7_5 extends GDBHardwareAndOS implements IGDBHardwareAndOS2 {
public GDBHardwareAndOS_7_5(DsfSession session) {
super(session);
}
@Override
public boolean isAvailable() {
return getSessionInitializationComplete();
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(new RequestMonitor(ImmediateExecutor.getInstance(), requestMonitor) {
@Override
protected void handleSuccess() {
register(new String[] { IGDBHardwareAndOS2.class.getName() },
new Hashtable<String, String>());
requestMonitor.done();
}
});
}
@Override
public void getResourceClasses(final IDMContext dmc, final DataRequestMonitor<IResourceClass[]> rm) {
IGDBControl control = getServicesTracker().getService(IGDBControl.class);
if (control == null) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Service not available", null)); //$NON-NLS-1$
return;
}
CommandFactory factory = control.getCommandFactory();
control.queueCommand(factory.createMIInfoOS(dmc), new DataRequestMonitor<MIInfoOsInfo>(getExecutor(), rm) {
@Override
@ConfinedToDsfExecutor("fExecutor")
protected void handleSuccess() {
rm.setData(getData().getResourceClasses());
rm.done();
}
});
}
@Override
public void getResourcesInformation(final IDMContext dmc, final String resourceClass, final DataRequestMonitor<IResourcesInformation> rm) {
IGDBControl control = getServicesTracker().getService(IGDBControl.class);
if (control == null) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Service not available", null)); //$NON-NLS-1$
return;
}
CommandFactory factory = control.getCommandFactory();
control.queueCommand(factory.createMIInfoOS(dmc, resourceClass), new DataRequestMonitor<MIInfoOsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getData().getResourcesInformation());
rm.done();
}
});
}
}

View file

@ -11,6 +11,7 @@
* Onur Akdemir (TUBITAK BILGEM-ITI) - Multi-process debugging (Bug 237306)
* Marc Khouzam (Ericsson) - Support for GDB 7.4 (Bug 367788)
* Marc Khouzam (Ericsson) - Include IGDBHardware service for the multicore visualizer (Bug 335027)
* Vladimir Prus (Mentor Graphics) - Support for OS resources.
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -62,6 +63,8 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
public static final String GDB_7_3_VERSION = "7.3"; //$NON-NLS-1$
/** @since 4.1 */
public static final String GDB_7_4_VERSION = "7.4"; //$NON-NLS-1$
/** @since 4.2*/
public static final String GDB_7_5_VERSION = "7.5"; //$NON-NLS-1$
private final String fVersion;
@ -229,6 +232,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
/** @since 4.1 */
protected IGDBHardwareAndOS createHardwareAndOSService(DsfSession session, ILaunchConfiguration config) {
if (GDB_7_5_VERSION.compareTo(fVersion) <= 0) {
return new GDBHardwareAndOS_7_5(session);
}
return new GDBHardwareAndOS(session);
}
}

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
/**
* Interface for accessing information about OS resources.
*
* <strong>EXPERIMENTAL</strong>. This class or interface has been added as part
* of a work in progress. There is no guarantee that this API will work or that
* it will remain the same.
*
* @since 4.2
*/
public interface IGDBHardwareAndOS2 extends IGDBHardwareAndOS {
/** Returns true if information returned by the other methods is available.
* If false is returned, it means that session initialization is in progress,
* and further request should be made after DataModelInitializedEvent is fired.
*/
public boolean isAvailable();
/** Information about OS resource class. */
public interface IResourceClass
{
/** The id of this resource class, used in GDB requests. */
public String getId();
/** Human-friendly description of this class, suitable for direct display in UI. */
public String getHumanDescription();
}
/**
* Return a list of OS resource classes GDB knows about
*/
public void getResourceClasses(IDMContext dmc, DataRequestMonitor<IResourceClass[]> rm);
/** Information about OS resources of specific resource class
* This is conceptually a table. GDB provides column headers, and
* data rows, but does not provide any additional information about
* the meaning
*/
public interface IResourcesInformation
{
/** Return the names of the columns in resource table. */
public String[] getColumnNames();
/** Returns rows of the resource table. Each element is an array
* of the size equal to getColumnNames().length
*/
public String[][] getContent();
}
/**
* Return table describing resources of specified class.
*/
void getResourcesInformation(IDMContext dmc, String resourceClassId, DataRequestMonitor<IResourcesInformation> rm);
}

View file

@ -18,6 +18,7 @@
* Marc Khouzam (Ericsson) - New method for new MIGDBSetPythonPrintStack (Bug 367788)
* Mathias Kunter - New methods for handling different charsets (Bug 370462)
* Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536)
* Vladimir Prus (Mentor Graphics) - Support for -info-os (Bug 360314)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command;
@ -118,6 +119,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetTargetCharset;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetTargetWideCharset;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBShowExitCode;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInfoOs;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExec;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsole;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsoleKill;
@ -181,6 +183,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIDataReadMemoryInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataWriteMemoryInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBShowExitCodeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIListFeaturesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackInfoDepthInfo;
@ -708,6 +711,20 @@ public class CommandFactory {
return new MIInferiorTTYSet(dmc, tty);
}
/**
* @since 4.2
*/
public ICommand<MIInfoOsInfo> createMIInfoOS(IDMContext ctx) {
return new MIInfoOs(ctx);
}
/**
* @since 4.2
*/
public ICommand<MIInfoOsInfo> createMIInfoOS(IDMContext ctx, String resourceClass) {
return new MIInfoOs(ctx, resourceClass);
}
public ICommand<MIInfo> createMIInterpreterExec(IDMContext ctx, String interpreter, String cmd) {
return new MIInterpreterExec<MIInfo>(ctx, interpreter, cmd);
}

View file

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2011 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.commands;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
/**
* MIInfoOS
*
* -info-os [ type ]
* If no argument is supplied, the command returns a table of
* available operating-system-specific information types. If one of these
* types is supplied as an argument type, then the command returns a
* table of data of that type.
*
* The types of information available depend on the target operating system.
* @since 4.2
*/
public class MIInfoOs extends MICommand<MIInfoOsInfo> {
public MIInfoOs(IDMContext ctx)
{
super(ctx, "-info-os"); //$NON-NLS-1$
}
public MIInfoOs(IDMContext ctx, String resourceClass)
{
super(ctx, "-info-os", new String[]{resourceClass}); //$NON-NLS-1$
specificResource = true;
}
@Override
public MIInfoOsInfo getResult(MIOutput out) {
return new MIInfoOsInfo(out, specificResource);
}
private boolean specificResource = false;
}

View file

@ -0,0 +1,187 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vladimir Prus (Mentor Graphics) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.dsf.gdb.service.IGDBHardwareAndOS2;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
/**
* Example output:
*
* (gdb) -info-os
* ^done,OSDataTable={nr_rows="9",nr_cols="3",
* hdr=[{width="10",alignment="-1",col_name="col0",colhdr="Type"},
* {width="10",alignment="-1",col_name="col1",colhdr="Description"},
* {width="10",alignment="-1",col_name="col2",colhdr="Title"}],
* body=[item={col0="processes",col1="Listing of all processes",
* col2="Processes"},
* item={col0="procgroups",col1="Listing of all process groups",
* col2="Process groups"},
* item={col0="threads",col1="Listing of all threads",
* col2="Threads"},
* item={col0="files",col1="Listing of all file descriptors",
* col2="File descriptors"},
* item={col0="sockets",col1="Listing of all internet-domain sockets",
* col2="Sockets"},
* item={col0="shm",col1="Listing of all shared-memory regions",
* col2="Shared-memory regions"},
* item={col0="semaphores",col1="Listing of all semaphores",
* col2="Semaphores"},
* item={col0="msg",col1="Listing of all message queues",
* col2="Message queues"},
* item={col0="modules",col1="Listing of all loaded kernel modules",
* col2="Kernel modules"}]}
* (gdb) -info-os processes
* ^done,OSDataTable={nr_rows="190",nr_cols="4",
* hdr=[{width="10",alignment="-1",col_name="col0",colhdr="pid"},
* {width="10",alignment="-1",col_name="col1",colhdr="user"},
* {width="10",alignment="-1",col_name="col2",colhdr="command"},
* {width="10",alignment="-1",col_name="col3",colhdr="cores"}],
* body=[item={col0="1",col1="root",col2="/sbin/init",col3="0"},
* item={col0="2",col1="root",col2="[kthreadd]",col3="1"},
* item={col0="3",col1="root",col2="[ksoftirqd/0]",col3="0"},
* ...
* item={col0="26446",col1="stan",col2="bash",col3="0"},
* item={col0="28152",col1="stan",col2="bash",col3="1"}]}
* (gdb)
*
* @since 4.2
*/
public class MIInfoOsInfo extends MIInfo {
// The fields below are used for response with list of classes.
private IGDBHardwareAndOS2.IResourceClass[] resourceClasses;
// The below fields are used only for data with specific resource class
private String[] columnNames;
private String[][] content;
public MIInfoOsInfo(MIOutput record, boolean resourcesInformation) {
super(record);
if (isDone()) {
if (resourcesInformation)
parseResourcesInformation();
else
parseResourceClasses();
}
}
public IGDBHardwareAndOS2.IResourcesInformation getResourcesInformation()
{
return new IGDBHardwareAndOS2.IResourcesInformation() {
@Override
public String[][] getContent() { return content; }
@Override
public String[] getColumnNames() { return columnNames; }
};
}
public IGDBHardwareAndOS2.IResourceClass[] getResourceClasses()
{
return resourceClasses;
}
private void parseResourceClasses()
{
List<IGDBHardwareAndOS2.IResourceClass> classes = new ArrayList<IGDBHardwareAndOS2.IResourceClass>();
MITuple table = (MITuple)get(getMIOutput(), "OSDataTable"); //$NON-NLS-1$
MIList body = (MIList)get(table, "body"); //$NON-NLS-1$
for (MIResult r: body.getMIResults()) {
MITuple row = (MITuple)r.getMIValue();
final String id = getString(row.getMIResults()[0]);
final String description = getString(row.getMIResults()[2]);
classes.add(new IGDBHardwareAndOS2.IResourceClass() {
@Override
public String getId() { return id; }
@Override
public String getHumanDescription() { return description; }
});
}
resourceClasses = classes.toArray(new IGDBHardwareAndOS2.IResourceClass[classes.size()]);
}
private void parseResourcesInformation()
{
MITuple table = (MITuple) get(getMIOutput(), "OSDataTable"); //$NON-NLS-1$
MIList header = (MIList) get(table, "hdr"); //$NON-NLS-1$
columnNames = new String[header.getMIValues().length];
int i = 0;
for (MIValue v : header.getMIValues()) {
MITuple column = (MITuple) v;
String columnName = ((MIConst) get(column, "colhdr")).getString(); //$NON-NLS-1$
columnNames[i++] = Character.toUpperCase(columnName.charAt(0)) + columnName.substring(1);
}
MIList body = (MIList) get(table, "body"); //$NON-NLS-1$
if (body == null)
{
content = new String[0][];
return;
}
content = new String[body.getMIResults().length][];
i = 0;
for (MIResult r : body.getMIResults()) {
MITuple row = (MITuple) r.getMIValue();
assert row.getMIResults().length == columnNames.length;
String[] rowStrings = new String[row.getMIResults().length];
int j = 0;
for (MIResult r2 : row.getMIResults())
{
rowStrings[j] = ((MIConst) r2.getMIValue()).getString();
++j;
}
content[i++] = rowStrings;
}
}
private MIValue get(MIResult[] results, String name) {
for (MIResult r : results)
if (r.getVariable().equals(name))
return r.getMIValue();
return null;
}
private MIValue get(MIOutput output, String name) {
return get(output.getMIResultRecord().getMIResults(), name);
}
private MIValue get(MITuple tuple, String name) {
return get(tuple.getMIResults(), name);
}
private String getString(MIValue value)
{
return ((MIConst)value).getString();
}
private String getString(MIResult result)
{
return getString(result.getMIValue());
}
}