/******************************************************************************* * Copyright (c) 2012, 2014 Tilera Corporation 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: * William R. Swanson (Tilera Corporation) - initial API and implementation * Marc Dumais (Ericsson) - bug 447897 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model.VisualizerThread; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.utils.DebugViewTreeWalker; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.cdt.visualizer.ui.util.SelectionUtils; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreePath; /** * Debug view tree walker that finds elements to select * based on selection obtained from the multicore visualizer. */ @SuppressWarnings("restriction") // allow access to internal interfaces public class MulticoreVisualizerSelectionFinder extends DebugViewTreeWalker { // --- members --- /** Selection item(s) we're currently looking for. */ protected List<Object> m_selection = null; /** Result we've found, if any. */ protected Set<Object> m_result = null; // --- constructors/destructors --- /** Constructor */ public MulticoreVisualizerSelectionFinder() { } /** Dispose method */ @Override public void dispose() { super.dispose(); } // --- methods --- /** Finds and returns Debug View element for specified * Visualizer selection item. * (E.g. the IDMVMContext for a VisualizerThread. * Returns null if no match is found. */ public ISelection findSelection(ISelection selection) { m_selection = SelectionUtils.getSelectedObjects(selection); m_result = new HashSet<Object>(); walk(); ISelection found = SelectionUtils.toSelection(m_result); return found; } /** Processes an element of the tree view. * Returns true if children of this element should be processed, * and false if they can be skipped. */ @Override public boolean processElement(TreePath path) { boolean result = true; Object element = getElement(path); if (element instanceof IDMVMContext) { IDMContext context = ((IDMVMContext) element).getDMContext(); int pid = getPID(context); int tid = getTID(context); if (isThreadContext(context)) { for (Object o : m_selection) { if (o instanceof VisualizerThread) { VisualizerThread thread = (VisualizerThread) o; // The Debug view model uses the GDB thread, to we need to use that one from the Visualizer model if (thread.getPID() == pid && thread.getGDBTID() == tid) { m_result.add(element); } } } } else if (context instanceof IFrameDMContext) { // FIXME: if we have frame[0] under a selected thread, // select that stack frame instead of the thread if (isThreadFrameZero(context)) { IDMVMContext threadContext = (IDMVMContext) path.getParentPath().getLastSegment(); if (m_result.contains(threadContext)) { m_result.remove(threadContext); m_result.add(element); } } } } return result; } /** Returns PID for specified debug context. */ public static int getPID(IDMContext context) { IMIProcessDMContext processContext = DMContexts.getAncestorOfType(context, IMIProcessDMContext.class); int pid = (processContext == null) ? 0 : Integer.parseInt(processContext.getProcId()); return pid; } /** Returns TID for specified debug context. */ public static int getTID(IDMContext context) { IMIExecutionDMContext execContext = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); int tid = 0; if (execContext != null) { try { tid = Integer.parseInt(execContext.getThreadId()); } catch (NumberFormatException e) { // Unable to resolve thread id assert false : "The thread id does not convert to an integer: " + execContext.getThreadId(); //$NON-NLS-1$ } } return tid; } /** Returns true if specified context represents a thread. */ public static boolean isThreadContext(IDMContext context) { // TODO: is there a more elegant way to express this? return context instanceof IMIExecutionDMContext && context.getParents().length >= 2 && (context.getParents()[0] instanceof IThreadDMContext || context.getParents()[1] instanceof IThreadDMContext); } /** Returns true if context represents the topmost (0th) frame under a thread. */ public static boolean isThreadFrameZero(IDMContext context) { // TODO: is there a more elegant way to express this? String value = context.toString(); return (value != null && value.endsWith(".frame[0]")); //$NON-NLS-1$ } }