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

Bug 360735: Add support for multi-process for "Show Breakpoints

Supported by Selected Target"

Change-Id: I8b64d5f7d8d87b6c6bce0737249207e9077a1d78
Reviewed-on: https://git.eclipse.org/r/7923
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:
Marc Khouzam 2012-10-19 10:09:35 -04:00
parent f6ce109425
commit 1709e1b676
7 changed files with 381 additions and 38 deletions

View file

@ -13,6 +13,7 @@
package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.breakpoints;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -24,16 +25,19 @@ import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.breakpoints.BreakpointVMProvider;
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
@ -103,16 +107,16 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
@Override
protected void calcFileteredBreakpoints( final DataRequestMonitor<IBreakpoint[]> rm ) {
if ( Boolean.TRUE.equals( getPresentationContext().getProperty( IBreakpointUIConstants.PROP_BREAKPOINTS_FILTER_SELECTION ) ) ) {
if (fUseAggressiveBpFilter) {
if ( fUseAggressiveBpFilter ) {
// Aggressive filtering of breakpoints. Only return bps that are installed on the target.
IBreakpointsTargetDMContext bpContext = null;
IMIExecutionDMContext threadContext = null;
IExecutionDMContext execContext = null;
ISelection debugContext = getDebugContext();
if ( debugContext instanceof IStructuredSelection ) {
Object element = ((IStructuredSelection)debugContext).getFirstElement();
Object element = ( (IStructuredSelection)debugContext ).getFirstElement();
if ( element instanceof IDMVMContext ) {
bpContext = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IBreakpointsTargetDMContext.class );
threadContext = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IMIExecutionDMContext.class );
execContext = DMContexts.getAncestorOfType( ((IDMVMContext)element).getDMContext(), IExecutionDMContext.class );
}
}
@ -127,17 +131,17 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
return;
}
getInstalledBreakpoints( bpContext, threadContext, rm );
getInstalledBreakpoints( bpContext, execContext, rm );
} else {
// Original behavior of bp filtering. Return all bp of type ICBreakpoint
IBreakpoint[] allBreakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
List<IBreakpoint> filteredBPs = new ArrayList<IBreakpoint>(allBreakpoints.length);
List<IBreakpoint> filteredBPs = new ArrayList<IBreakpoint>( allBreakpoints.length );
for (IBreakpoint bp : allBreakpoints) {
if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(CDebugCorePlugin.PLUGIN_ID)) {
filteredBPs.add(bp);
if ( bp instanceof ICBreakpoint && bp.getModelIdentifier().equals( CDebugCorePlugin.PLUGIN_ID ) ) {
filteredBPs.add( bp );
}
}
rm.done( filteredBPs.toArray(new IBreakpoint[filteredBPs.size()]) );
rm.done( filteredBPs.toArray( new IBreakpoint[filteredBPs.size()]) );
}
}
else {
@ -221,7 +225,7 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
return StructuredSelection.EMPTY;
}
void getInstalledBreakpoints( final IBreakpointsTargetDMContext targetContext, final IMIExecutionDMContext threadContext, final DataRequestMonitor<IBreakpoint[]> rm ) {
private void getInstalledBreakpoints( final IBreakpointsTargetDMContext targetContext, final IExecutionDMContext execContext, final DataRequestMonitor<IBreakpoint[]> rm ) {
try {
fSession.getExecutor().execute( new DsfRunnable() {
@ -237,7 +241,7 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
rm.done();
return;
}
bpService.getBreakpoints( targetContext, new DataRequestMonitor<IBreakpoints.IBreakpointDMContext[]>( fSession.getExecutor(), rm ) {
bpService.getBreakpoints( targetContext, new DataRequestMonitor<IBreakpointDMContext[]>( fSession.getExecutor(), rm ) {
@Override
protected void handleSuccess() {
@ -267,7 +271,7 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
for ( final IBreakpointDMContext bpCtx : getData() ) {
bpService.getBreakpointDMData(
bpCtx,
new DataRequestMonitor<IBreakpoints.IBreakpointDMData>( ImmediateExecutor.getInstance(), crm ) {
new DataRequestMonitor<IBreakpointDMData>( ImmediateExecutor.getInstance(), crm ) {
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.concurrent.RequestMonitor#handleSuccess()
@ -276,10 +280,19 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
protected void handleSuccess() {
if ( getData() instanceof MIBreakpointDMData ) {
MIBreakpointDMData data = (MIBreakpointDMData)getData();
if ( !data.isPending() && isThreadBreakpoint( threadContext, data )) {
IBreakpoint bp = bpManager.findPlatformBreakpoint( bpCtx );
if ( bp != null )
bps.add( bp );
if ( !data.isPending() ) {
bpBelongsToContext( execContext, data, new ImmediateDataRequestMonitor<Boolean>(crm) {
@Override
protected void handleSuccess() {
if (getData()) {
IBreakpoint bp = bpManager.findPlatformBreakpoint( bpCtx );
if ( bp != null )
bps.add( bp );
}
crm.done();
}
});
return;
}
}
crm.done();
@ -306,25 +319,55 @@ public class GdbBreakpointVMProvider extends BreakpointVMProvider {
}
}
private boolean isThreadBreakpoint( IMIExecutionDMContext threadContext, MIBreakpointDMData data ) {
if ( threadContext == null || data.getThreadId() == null || data.getThreadId().length() == 0 ) {
// Ignore threads
return true;
private void bpBelongsToContext( IExecutionDMContext execContext, final MIBreakpointDMData data, final DataRequestMonitor<Boolean> rm ) {
if ( execContext == null ) {
// No execution context so accept all breakpoints
rm.done( true );
return;
}
int threadId = threadContext.getThreadId();
try {
int bpThreadId = Integer.parseInt( data.getThreadId() );
if ( bpThreadId == 0 )
return true;
return ( threadId == bpThreadId );
// First check if a thread is selected as the context. In that case, we only want to show breakpoints that
// are applicable to that thread.
IMIExecutionDMContext threadContext = DMContexts.getAncestorOfType( execContext, IMIExecutionDMContext.class );
if ( threadContext != null ) {
// A thread is selected. Now make sure this breakpoint is assigned to this thread.
if ( data.getThreadId() != null && data.getThreadId().length() > 0 ) {
try {
int bpThreadId = Integer.parseInt( data.getThreadId() );
// A threadId of 0 means all threads of this process. We therefore will have to check
// if this breakpoint applies to the process that is selected. But if the threadId is not 0
// we simply make sure we have the right thread selected.
if ( bpThreadId != 0 ) {
rm.done( threadContext.getThreadId() == bpThreadId );
return;
}
}
catch( NumberFormatException e ) {
assert false;
GdbUIPlugin.getDefault().getLog().log( new Status(
IStatus.ERROR,
GdbUIPlugin.getUniqueIdentifier(),
"Invalid breakpoint thread id" ) ); //$NON-NLS-1$
rm.done( true );
return;
}
}
}
// If we get here it is that the breakpoint is not assigned to a single thread.
// We therefore make sure the breakpoint is applicable to the selected process.
final IMIContainerDMContext containerContext = DMContexts.getAncestorOfType( execContext, IMIContainerDMContext.class );
if ( containerContext != null ) {
if ( data.getGroupIds() != null ) {
List<String> groupIds = Arrays.asList( data.getGroupIds() );
rm.done( groupIds.contains( containerContext.getGroupId() ) );
} else {
// This happens if we are debugging a single process, so all breakpoints apply.
rm.done( true );
}
} else {
// Accept breakpoint
rm.done( true );
}
catch( NumberFormatException e ) {
GdbUIPlugin.getDefault().getLog().log( new Status(
IStatus.ERROR,
GdbUIPlugin.getUniqueIdentifier(),
"Invalid breakpoint thread id" ) ); //$NON-NLS-1$
}
return true;
}
}

View file

@ -8,7 +8,9 @@
* Contributors:
* Ericsson - Initial API and implementation
* Marc Khouzam (Ericsson) - Support for fast tracepoints (Bug 346320)
* Marc Khouzam (Ericsson) - Fetch groupIds when getting breakpoints (Bug 360735)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
import java.util.HashMap;
@ -27,7 +29,10 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
@ -89,6 +94,73 @@ public class GDBBreakpoints_7_2 extends GDBBreakpoints_7_0
super.shutdown(requestMonitor);
}
/**
* {@inheritDoc}
*
* Starting with GDB 7.2, also provides information about which process each breakpoint applies to.
*/
@Override
public void getBreakpoints(final IBreakpointsTargetDMContext context, final DataRequestMonitor<IBreakpointDMContext[]> drm)
{
// Validate the context
if (context == null) {
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
drm.done();
return;
}
// Select the breakpoints context map
// If it doesn't exist then no breakpoint was ever inserted for this breakpoint space.
// In that case, return an empty list.
final Map<Integer, MIBreakpointDMData> breakpointContext = getBreakpointMap(context);
if (breakpointContext == null) {
drm.setData(new IBreakpointDMContext[0]);
drm.done();
return;
}
// Execute the command
fConnection.queueCommand(fConnection.getCommandFactory().createMIBreakList(context),
new DataRequestMonitor<MIBreakListInfo>(getExecutor(), drm) {
@Override
protected void handleSuccess() {
final MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
// Also fetch the information about which breakpoint belongs to which
// process. We currently can only obtain this information from the CLI
// command. This information is needed for breakpoint filtering.
// Bug 360735
fConnection.queueCommand(fConnection.getCommandFactory().createCLIInfoBreak(context),
new ImmediateDataRequestMonitor<CLIInfoBreakInfo>(drm) {
@Override
protected void handleSuccess() {
Map<Integer, String[]> groupIdMap = getData().getBreakpointToGroupMap();
// Refresh the breakpoints map and format the result
breakpointContext.clear();
IBreakpointDMContext[] result = new IBreakpointDMContext[breakpoints.length];
for (int i = 0; i < breakpoints.length; i++) {
MIBreakpointDMData breakpointData = new MIBreakpointDMData(breakpoints[i]);
// Now fill in the thread-group information into the breakpoint data
// It is ok to get null. For example, pending breakpoints are not
// associated to a thread-group; also, when debugging a single process,
// the thread-group list is empty.
int reference = breakpointData.getReference();
String[] groupIds = groupIdMap.get(reference);
breakpointData.setGroupIds(groupIds);
result[i] = new MIBreakpointDMContext(GDBBreakpoints_7_2.this, new IDMContext[] { context }, reference);
breakpointContext.put(reference, breakpointData);
}
drm.setData(result);
drm.done();
}
});
}
});
}
private void setTracepointMode() {
ILaunch launch = (ILaunch)getSession().getModelAdapter(ILaunch.class);
String tpMode = IGDBLaunchConfigurationConstants.DEBUGGER_TRACEPOINT_MODE_DEFAULT;

View file

@ -269,6 +269,10 @@ public class MIBreakpointDMData implements IBreakpointDMData {
return fBreakpoint.isEnabled();
}
///////////////////////////////////////////////////////////////////////////
// MIBreakpointDMData
///////////////////////////////////////////////////////////////////////////
/**
* @since 3.0
*/
@ -283,10 +287,6 @@ public class MIBreakpointDMData implements IBreakpointDMData {
return fBreakpoint.getCommands();
}
///////////////////////////////////////////////////////////////////////////
// MIBreakpointDMData
///////////////////////////////////////////////////////////////////////////
public int getNumber() {
return fBreakpoint.getNumber();
}
@ -295,6 +295,16 @@ public class MIBreakpointDMData implements IBreakpointDMData {
return fBreakpoint.getThreadId();
}
/** @since 4.2 */
public String[] getGroupIds() {
return fBreakpoint.getGroupIds();
}
/** @since 4.2 */
public void setGroupIds(String[] groups) {
fBreakpoint.setGroupIds(groups);
}
public boolean isTemporary() {
return fBreakpoint.isTemporary();
}

View file

@ -43,6 +43,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIDetach;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIExecAbort;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoBreak;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoProgram;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoSharedLibrary;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoThreads;
@ -167,6 +168,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate;
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoProgramInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoThreadsInfo;
@ -241,6 +243,16 @@ public class CommandFactory {
return new CLIExecAbort(ctx);
}
/** @since 4.2 */
public ICommand<CLIInfoBreakInfo> createCLIInfoBreak(IDMContext ctx) {
return new CLIInfoBreak(ctx);
}
/** @since 4.2 */
public ICommand<CLIInfoBreakInfo> createCLIInfoBreak(IDMContext ctx, int bpRef) {
return new CLIInfoBreak(ctx, bpRef);
}
public ICommand<CLIInfoProgramInfo> createCLIInfoProgram(IContainerDMContext ctx) {
return new CLIInfoProgram(ctx);
}

View file

@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marc Khouzam (Ericsson) - 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.output.CLIInfoBreakInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
/**
* 'info break [BP_REFERENCE]
*
* will return information about the specified breakpoint. If no breakpoint is
* specified, it will return information about all breakpoints.
* We use it to find out to which inferior a breakpoint is applicable.
* This information is not available from -break-list or -break-info until GDB 7.6.
*
* @since 4.2
*/
public class CLIInfoBreak extends CLICommand<CLIInfoBreakInfo> {
private static final String INFO_BREAK = "info break"; //$NON-NLS-1$
public CLIInfoBreak(IDMContext ctx) {
super(ctx, INFO_BREAK);
};
public CLIInfoBreak(IDMContext ctx, int bpReference) {
super(ctx, INFO_BREAK + Integer.toString(bpReference));
}
@Override
public CLIInfoBreakInfo getResult(MIOutput MIresult) {
return new CLIInfoBreakInfo(MIresult);
}
}

View file

@ -0,0 +1,113 @@
/*******************************************************************************
* Copyright (c) 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marc Khouzam (Ericsson) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* 'info break [BP_REFERENCE] will return information about
* the specified breakpoint. We use it to find out to which
* inferiors a breakpoint is applicable.
*
* sample output:
*
* (gdb) info break
* Num Type Disp Enb Address What
* 1 breakpoint keep y <MULTIPLE>
* 1.1 y 0x08048533 in main() at loopfirst.cc:8 inf 2
* 1.2 y 0x08048533 in main() at loopfirst.cc:8 inf 1
* 2 breakpoint keep y <MULTIPLE>
* 2.1 y 0x08048553 in main() at loopfirst.cc:9 inf 2
* 2.2 y 0x08048553 in main() at loopfirst.cc:9 inf 1
*
* If only one inferior is being debugged there is not mention of the inferior:
* (gdb) info break
* Num Type Disp Enb Address What
* 1 breakpoint keep y 0x08048533 in main() at loopfirst.cc:8
* 2 breakpoint keep y 0x08048553 in main() at loopfirst.cc:9
*
* Note that the below output is theoretically possible looking at GDB's code but
* I haven't figured out a way to trigger it. Still, we should be prepared for it:
* (gdb) info break
* Num Type Disp Enb Address What
* 1 breakpoint keep y <MULTIPLE>
* 1.1 y 0x08048533 in main() at loopfirst.cc:8 inf 3, 2
* 1.2 y 0x08048533 in main() at loopfirst.cc:8 inf 2, 1
* 2 breakpoint keep y <MULTIPLE>
* 2.1 y 0x08048553 in main() at loopfirst.cc:9 inf 2, 1
* 2.2 y 0x08048553 in main() at loopfirst.cc:9 inf 3, 2, 1
*
* @since 4.2
*/
public class CLIInfoBreakInfo extends MIInfo {
private Map<Integer, String[]> fBreakpointToGroupMap = new HashMap<Integer, String[]>();
public CLIInfoBreakInfo(MIOutput out) {
super(out);
parse();
}
/**
* Returns the map of breakpoint to groupId array indicating to which thread-group
* each breakpoint applies. If there is only a single thread-group being debugged, an
* empty map will be returned.
*/
public Map<Integer, String[]> getBreakpointToGroupMap() {
return fBreakpointToGroupMap;
}
protected void parse() {
final String INFERIOR_PREFIX = " inf "; //$NON-NLS-1$
if (isDone()) {
MIOutput out = getMIOutput();
for (MIOOBRecord oob : out.getMIOOBRecords()) {
if (oob instanceof MIConsoleStreamOutput) {
String line = ((MIConsoleStreamOutput)oob).getString().trim();
int loc = line.indexOf(INFERIOR_PREFIX);
if (loc >= 0) {
// Get the breakpoint id by extracting the first element before a white space
// or before a period. We can set a limit of 2 since we only need the first element
String bpIdStr = line.split("[\\s\\.]", 2)[0]; //$NON-NLS-1$
int bpId = 0;
try {
bpId = Integer.parseInt(bpIdStr);
} catch (NumberFormatException e) {
assert false;
}
String[] groups = fBreakpointToGroupMap.get(bpId);
Set<String> groupIdList = new HashSet<String>();
if (groups != null) {
// Since we already know about this breakpoint id we must retain the list
// we have been building
groupIdList.addAll(Arrays.asList(groups));
}
// Get the comma-separated list of inferiors
// Split the list into individual ids
String inferiorIdStr = line.substring(loc + INFERIOR_PREFIX.length()).trim();
for (String id : inferiorIdStr.split(",")) { //$NON-NLS-1$
// Add the 'i' prefix as GDB does for MI commands
groupIdList.add("i" + id.trim()); //$NON-NLS-1$
}
fBreakpointToGroupMap.put(bpId, groupIdList.toArray(new String[groupIdList.size()]));
}
}
}
}
}
}

View file

@ -11,10 +11,14 @@
* Ericsson - Modified for the breakpoint service
* Ericsson - Added Tracepoint support (284286)
* Abeer Bagul (Tensilica) - Differentiate between hw breakpoint and watchpoint
* Marc Khouzam (Ericsson) - Add 'thread-group' field (bug 360735)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.TracepointActionManager;
@ -105,6 +109,13 @@ public class MIBreakpoint {
*/
private boolean pending;
/**
* The list of groupIds to which this breakpoint applies.
* This field is only reported by MI starting with GDB 7.6.
* null will be returned if this field is not present.
*/
private String[] groupIds;
public MIBreakpoint() {
}
@ -134,6 +145,9 @@ public class MIBreakpoint {
isCatchpoint = other.isCatchpoint;
catchpointType = other.catchpointType;
pending = other.pending;
if (other.groupIds != null) {
groupIds = Arrays.copyOf(other.groupIds, other.groupIds.length);
}
}
public MIBreakpoint(MITuple tuple) {
@ -409,6 +423,25 @@ public class MIBreakpoint {
return pending;
}
/**
* Returns the thread-groups to which this breakpoint applies.
* Returns null if the data is not known.
*
* @since 4.2
*/
public String[] getGroupIds() {
return groupIds;
}
/**
* Sets the list of thread-groups to which this breakpoint applies.
*
* @since 4.2
*/
public void setGroupIds(String[] groups) {
groupIds = groups;
}
// Parse the result string
void parse(MITuple tuple) {
MIResult[] results = tuple.getMIResults();
@ -504,6 +537,10 @@ public class MIBreakpoint {
if (value instanceof MITuple) {
parseCommands((MITuple)value);
}
} else if (var.equals("thread-group")) { //$NON-NLS-1$
if (value instanceof MIList) {
parseGroups((MIList)value);
}
}
}
}
@ -524,4 +561,17 @@ public class MIBreakpoint {
setCommands(cmds.toString());
}
private void parseGroups(MIList list) {
List<String> groups = new ArrayList<String>();
MIValue[] values = list.getMIValues();
for (int i = 0; i < values.length; i++) {
if (values[i] instanceof MIConst) {
groups.add(((MIConst)values[i]).getCString());
}
}
groupIds = groups.toArray(new String[groups.size()]);
}
}