Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 7714bea88e88b0927580cdbd0099cd5ef78c0742 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                
                                                                







                                                                                 
                                                   
 
                            
                               






                                                                                    
                                                                                    
                                              
                                    

                                                               

                                                       


                                            
                                              
                                               
                                            
 
 
                           
                                                 
 

                             

                                                       
 

                                                                          
                                                                      
                                                      
 
                                                               
 
                            

                               
 
                                                         
                          
                           
                                                         
                                                         








































                                                                                                                      
















                                                                                                                  
                                                            













                                                                                                                                                     




                                                                  





                                             



                    
                                
                                

                                

                                 

                        
 



                                   

     

                                                           

     



                                                           
                                                      




                                                     

     

                                                                        

     



                                                                        

                                                                   

     

                                           



                                                                  

                                            

     

                                           



                                                                  

                                            


             
                                    
                                           



                                                                  
                                            
                                   

                                              





                                                   
     







                                                     



                                                 

             




                                                                  
                                                                     















                                                                       
                                                                     










                                                                       
                                                         

                                                                  
                                                                                                   


                                                                       








                                                            
 

                                                    
                             

                                                                  
                                                                                                   







                                                                       







                                               


                                           
                               
                                                                     




                                           
 

                                                       

                                                                  
                                                                                                   


                                                                       








                                                                
 

                                                 
                                                                                    
                          








                                                                                   

                                          
                                         
                                                              

                                                




                                                

                                                                      
             



                                  
                                                                
                                              



                                                                  
                                   
                                               
                                                               

     
                                                        
                                              



                                                          
                                   
                                                               



                             
                      
                  
                                           



                                 



                                                                      
         

                                     
                                                               



                               



                                                                      
         
                      
                                                               



                                                                                  




                                                  

                                     
                      
                                                               



                             
                                           
                                         
                                      
                                                  

                                               
                                     
                                           
                                                
                                                   


                                                                             
                                         

             
     


                                                                  
                                                                               

                                                                                                           

                                         




                                                      

                               
                                            
                                           
     
 
             
                                                
                         



                                                           
                                                           

                               

                         
 


                                                                 




                                                                   
                                         
         

                               

                         


                                                                     
        













                                                                
             





                                                                         
     
 

                                                                                 
                                            








                                                                           


                     
 

                                     

                                                                  
                     


                                                                                      
                                                 
         
                               
                                         


                                                                                


                                    









                                                         
 
/*******************************************************************************
 * Copyright (c) 2007, 2008 Wind River Systems, Inc. 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:
 *     Wind River Systems - initial API and implementation
 *******************************************************************************/
package org.eclipse.tm.internal.tcf.debug.ui.model;

import java.math.BigInteger;
import java.util.LinkedHashMap;
import java.util.Map;

import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.tm.internal.tcf.debug.model.TCFContextState;
import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef;
import org.eclipse.tm.internal.tcf.debug.ui.ImageCache;
import org.eclipse.tm.tcf.protocol.IChannel;
import org.eclipse.tm.tcf.protocol.IToken;
import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.tcf.services.IMemory;
import org.eclipse.tm.tcf.services.IProcesses;
import org.eclipse.tm.tcf.services.IRunControl;
import org.eclipse.tm.tcf.util.TCFDataCache;


@SuppressWarnings("serial")
public class TCFNodeExecContext extends TCFNode {

    private final int seq_no;
    
    private final TCFChildrenExecContext children_exec;
    private final TCFChildrenStackTrace children_stack;

    private final TCFDataCache<IMemory.MemoryContext> mem_context;
    private final TCFDataCache<IRunControl.RunControlContext> run_context;
    private final TCFDataCache<IProcesses.ProcessContext> prs_context;
    private final TCFDataCache<TCFContextState> state;

    private final Map<BigInteger,TCFSourceRef> line_info_cache;

    private int resumed_cnt;
    
    private static int seq_cnt;

    TCFNodeExecContext(TCFNode parent, final String id) {
        super(parent, id);
        seq_no = seq_cnt++;
        children_exec = new TCFChildrenExecContext(this);
        children_stack = new TCFChildrenStackTrace(this);
        line_info_cache = new LinkedHashMap<BigInteger,TCFSourceRef>() {
            @SuppressWarnings("unchecked")
            protected boolean removeEldestEntry(Map.Entry eldest) {
                return size() > 256;
            }
        };
        IChannel channel = model.getLaunch().getChannel();
        mem_context = new TCFDataCache<IMemory.MemoryContext>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                assert command == null;
                IMemory mem = model.getLaunch().getService(IMemory.class);
                if (mem == null) {
                    set(null, null, null);
                    return true;
                }
                command = mem.getContext(id, new IMemory.DoneGetContext() {
                    public void doneGetContext(IToken token, Exception error, IMemory.MemoryContext context) {
                        set(token, error, context);
                    }
                });
                return false;
            }
        };
        run_context = new TCFDataCache<IRunControl.RunControlContext>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                assert command == null;
                IRunControl run = model.getLaunch().getService(IRunControl.class);
                if (run == null) {
                    set(null, null, null);
                    return true;
                }
                command = run.getContext(id, new IRunControl.DoneGetContext() {
                    public void doneGetContext(IToken token, Exception error, IRunControl.RunControlContext context) {
                        set(token, error, context);
                    }
                });
                return false;
            }
        };
        prs_context = new TCFDataCache<IProcesses.ProcessContext>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                assert command == null;
                IProcesses prs = model.getLaunch().getService(IProcesses.class);
                if (prs == null) {
                    set(null, null, null);
                    return true;
                }
                command = prs.getContext(id, new IProcesses.DoneGetContext() {
                    public void doneGetContext(IToken token, Exception error, IProcesses.ProcessContext context) {
                        set(token, error, context);
                    }
                });
                return false;
            }
        };
        state = new TCFDataCache<TCFContextState>(channel) {
            @Override
            protected boolean startDataRetrieval() {
                assert command == null;
                if (!run_context.validate()) {
                    run_context.wait(this);
                    return false;
                }
                IRunControl.RunControlContext ctx = run_context.getData();
                if (ctx == null || !ctx.hasState()) {
                    set(null, null, null);
                    return true;
                }
                command = ctx.getState(new IRunControl.DoneGetState() {
                    public void doneGetState(IToken token, Exception error, boolean suspended, String pc, String reason, Map<String,Object> params) {
                        TCFContextState s = new TCFContextState();
                        s.is_suspended = suspended;
                        s.suspend_pc = pc;
                        s.suspend_reason = reason;
                        s.suspend_params = params;
                        set(token, error, s);
                    }
                });
                return false;
            }
        };
    }

    @Override
    void dispose() {
        run_context.reset(null);
        prs_context.reset(null);
        mem_context.reset(null);
        state.reset(null);
        children_exec.dispose();
        children_stack.dispose();
        super.dispose();
    }

    @Override
    void dispose(String id) {
        children_exec.dispose(id);
        children_stack.dispose(id);
    }

    void setRunContext(IRunControl.RunControlContext ctx) {
        run_context.reset(ctx);
    }

    void setProcessContext(IProcesses.ProcessContext ctx) {
        prs_context.reset(ctx);
    }

    void setMemoryContext(IMemory.MemoryContext ctx) {
        mem_context.reset(ctx);
    }
    
    Map<BigInteger,TCFSourceRef> getLineInfoCache() {
        return line_info_cache;
    }

    public TCFDataCache<IRunControl.RunControlContext> getRunContext() {
        return run_context;
    }

    public TCFDataCache<IProcesses.ProcessContext> getProcessContext() {
        return prs_context;
    }

    public TCFDataCache<IMemory.MemoryContext> getMemoryContext() {
        return mem_context;
    }

    public boolean isRunning() {
        assert Protocol.isDispatchThread();
        if (!run_context.isValid()) return false;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx == null || !ctx.hasState()) return false;
        if (!state.isValid()) return false;
        TCFContextState s = state.getData();
        return s != null && !s.is_suspended;
    }

    public boolean isSuspended() {
        assert Protocol.isDispatchThread();
        if (!run_context.isValid()) return false;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx == null || !ctx.hasState()) return false;
        if (!state.isValid()) return false;
        TCFContextState s = state.getData();
        return s != null && s.is_suspended;
    }

    @Override
    public BigInteger getAddress() {
        assert Protocol.isDispatchThread();
        if (!run_context.isValid()) return null;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx == null || !ctx.hasState()) return null;
        if (!state.isValid()) return null;
        TCFContextState s = state.getData();
        if (s == null) return null;
        if (s.suspend_pc == null) return null;
        return new BigInteger(s.suspend_pc);
    }
    
    public TCFNodeStackFrame getTopFrame() {
        assert Protocol.isDispatchThread();
        if (!children_stack.isValid()) return null;
        return children_stack.getTopFrame();
    }
    
    public TCFDataCache<TCFContextState> getState() {
        return state;
    }
    
    public TCFChildrenStackTrace getStackTrace() {
        return children_stack;
    }
    
    public TCFChildrenExecContext getChildren() {
        return children_exec;
    }

    @Override
    public int getNodeIndex(IPresentationContext p, TCFNode n) {
        if (!run_context.isValid()) return -1;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.hasState()) {
            if (!children_stack.isValid()) return -1;
            if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getId())) {
                TCFNodeStackFrame frame = children_stack.getTopFrame();
                if (frame == null) return -1;
                return frame.getNodeIndex(p, n);
            }
            return children_stack.getIndexOf(n);
        }
        if (!children_exec.isValid()) return -1;
        return children_exec.getIndexOf(n);
    }
    
    @Override
    public int getChildrenCount(IPresentationContext p) {
        if (!run_context.isValid()) return -1;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.hasState()) {
            if (!children_stack.isValid()) return -1;
            if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getId())) {
                TCFNodeStackFrame frame = children_stack.getTopFrame();
                if (frame == null) return -1;
                return frame.getChildrenCount(p);
            }
            return children_stack.size();
        }
        if (!children_exec.isValid()) return -1;
        return children_exec.size();
    }

    @Override
    protected void getData(IChildrenCountUpdate result) {
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.hasState()) {
            if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(result.getPresentationContext().getId())) {
                TCFNodeStackFrame frame = children_stack.getTopFrame();
                if (frame == null) result.setChildCount(0);
                else frame.getData(result);
            }
            else {
                result.setChildCount(children_stack.size());
            }
        }
        else {
            result.setChildCount(children_exec.size());
        }
    }

    @Override
    protected void getData(IChildrenUpdate result) {
        TCFNode[] arr = null;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.hasState()) {
            if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(result.getPresentationContext().getId())) {
                TCFNodeStackFrame frame = children_stack.getTopFrame();
                if (frame == null) {
                    arr = new TCFNode[0];
                }
                else {
                    frame.getData(result);
                    return;
                }
            }
            else {
                arr = children_stack.toArray();
            }
        }
        else {
            arr = children_exec.toArray();
        }
        int offset = 0;
        int r_offset = result.getOffset(); 
        int r_length = result.getLength(); 
        for (TCFNode n : arr) {
            if (offset >= r_offset && offset < r_offset + r_length) {
                result.setChild(n, offset);
            }
            offset++;
        }
    }

    @Override
    protected void getData(IHasChildrenUpdate result) {
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.hasState()) {
            if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(result.getPresentationContext().getId())) {
                TCFNodeStackFrame frame = children_stack.getTopFrame();
                if (frame == null) result.setHasChilren(false);
                else frame.getData(result);
            }
            else {
                result.setHasChilren(children_stack.size() > 0);
            }
        }
        else {
            result.setHasChilren(children_exec.size() > 0);
        }
    }

    @Override
    protected void getData(ILabelUpdate result) {
        result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0);
        String label = id;
        Throwable error = run_context.getError();
        if (error != null) {
            result.setForeground(new RGB(255, 0, 0), 0);
            label += ": " + error.getClass().getName() + ": " + error.getMessage();
        }
        else {
            IRunControl.RunControlContext ctx = run_context.getData();
            if (ctx != null) {
                if (isRunning()) {
                    label += " (Running)";
                }
                else if (isSuspended()) {
                    String r = state.getData().suspend_reason;
                    if (r != null) {
                        label += " (" + r + ")";
                    }
                    else {
                        label += " (Suspended)";
                    }
                }
                String file = (String)ctx.getProperties().get("File");
                if (file != null) label += " " + file;
            }
        }
        result.setLabel(label, 0);
    }

    void onContextAdded(IRunControl.RunControlContext context) {
        children_exec.onContextAdded(context);
    }

    void onContextChanged(IRunControl.RunControlContext context) {
        assert !disposed;
        run_context.reset(context);
        children_stack.onSourceMappingChange();
        addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT);
    }

    void onContextAdded(IMemory.MemoryContext context) {
        children_exec.onContextAdded(context);
    }

    void onContextChanged(IMemory.MemoryContext context) {
        assert !disposed;
        mem_context.reset(context);
        addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT);
    }

    void onContextRemoved() {
        assert !disposed;
        resumed_cnt++;
        dispose();
        addModelDelta(IModelDelta.REMOVED);
    }

    void onContainerSuspended() {
        assert !disposed;
        if (run_context.isValid()) {
            IRunControl.RunControlContext ctx = run_context.getData();
            if (ctx == null) return;
            if (!ctx.hasState()) return;
        }
        state.reset();
        children_stack.onSuspended();
        addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT);
    }

    void onContainerResumed() {
        assert !disposed;
        if (run_context.isValid()) {
            IRunControl.RunControlContext ctx = run_context.getData();
            if (ctx == null) return;
            if (!ctx.hasState()) return;
        }
        state.reset();
        addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT);
    }

    void onContextSuspended(String pc, String reason, Map<String,Object> params) {
        assert !disposed;
        TCFContextState s = new TCFContextState();
        s.is_suspended = true;
        s.suspend_pc = pc;
        s.suspend_reason = reason;
        s.suspend_params = params;
        state.reset(s);
        children_stack.onSuspended();
        resumed_cnt++;
        addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT);
    }

    void onContextResumed() {
        assert !disposed;
        state.reset(new TCFContextState());
        addModelDelta(IModelDelta.STATE);
        final int cnt = ++resumed_cnt;
        Protocol.invokeLater(250, new Runnable() {
            public void run() {
                if (cnt != resumed_cnt) return;
                if (disposed) return;
                children_stack.onResumed();
                if (!validateNode(this)) return;
                addModelDelta(IModelDelta.CONTENT);
                if (parent instanceof TCFNodeExecContext) {
                    ((TCFNodeExecContext)parent).onChildResumedOrSuspended();
                }
                model.fireModelChanged();
            }
        });
    }
    
    void onChildResumedOrSuspended() {
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.isContainer()) addModelDelta(IModelDelta.STATE);
        if (parent instanceof TCFNodeExecContext) ((TCFNodeExecContext)parent).onChildResumedOrSuspended();
    }

    void onContextException(String msg) {
    }

    void onMemoryChanged(Number[] addr, long[] size) {
        assert !disposed;
    }

    void onRegistersChanged() {
        children_stack.onRegistersChanged();
        addModelDelta(IModelDelta.CONTENT);
    }

    @Override
    public boolean validateNode(Runnable done) {
        assert !disposed;
        TCFDataCache<?> pending = null;
        
        if (!mem_context.validate()) pending = mem_context;
        if (!run_context.validate()) pending = run_context;
        if (!prs_context.validate()) pending = prs_context;
        if (pending != null) {
            pending.wait(done);
            return false;
        }

        if (!state.validate()) pending = state;
        if (!children_exec.validate()) pending = children_exec;
        if (!children_stack.validate()) pending = children_stack;
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && !ctx.hasState()) {
            // Container need to validate children for
            // hasSuspendedChildren() method to return valid value.
            TCFDataCache<?> dt = validateChildrenState();
            if (dt != null) pending = dt;
        }
        if (pending != null) {
            pending.wait(done);
            return false;
        }
        
        TCFNodeStackFrame frame = children_stack.getTopFrame();
        if (frame != null && !frame.validateNode(done)) return false;
        
        return true;
    }
    
    // Validate children state for hasSuspendedChildren()
    // Return TCFDataCache to wait for if validation is pending.
    private TCFDataCache<?> validateChildrenState() {
        if (!children_exec.validate()) return children_exec;
        TCFDataCache<?> pending = null;
        for (TCFNode n : children_exec.getData().values()) {
            if (!(n instanceof TCFNodeExecContext)) continue;
            TCFNodeExecContext e = (TCFNodeExecContext)n;
            if (!e.run_context.validate()) {
                pending = e.run_context;
                continue;
            }
            IRunControl.RunControlContext ctx = e.run_context.getData();
            if (ctx == null) continue;
            if (ctx.hasState() && !e.state.validate()) pending = e.state;
            if (ctx.isContainer()) pending = e.validateChildrenState();
        }
        return pending;
    }

    // Return true if at least one child is suspended
    // The method will fail if node is not validated, see validateChildrenState()
    private boolean hasSuspendedChildren() {
        Map<String,TCFNode> m = children_exec.getData();
        if (m == null) return false;
        for (TCFNode n : m.values()) {
            if (!(n instanceof TCFNodeExecContext)) continue;
            TCFNodeExecContext e = (TCFNodeExecContext)n;
            IRunControl.RunControlContext ctx = e.run_context.getData();
            if (ctx == null) continue;
            if (ctx.hasState() && e.isSuspended()) return true;
            if (ctx.isContainer() && e.hasSuspendedChildren()) return true;
        }
        return false;
    }

    @Override
    protected String getImageName() {
        IRunControl.RunControlContext ctx = run_context.getData();
        if (ctx != null && ctx.hasState()) {
            // Thread
            TCFContextState s = state.getData();
            if (s != null && s.is_terminated) return ImageCache.IMG_THREAD_TERMINATED;
            if (s != null && s.is_suspended) return ImageCache.IMG_THREAD_SUSPENDED;
            return ImageCache.IMG_THREAD_RUNNNIG;
        }
        else if (ctx != null) {
            // Thread container (process)
            //if (terminated) return ImageCache.IMG_PROCESS_TERMINATED;
            if (hasSuspendedChildren()) return ImageCache.IMG_PROCESS_SUSPENDED;
            return ImageCache.IMG_PROCESS_RUNNING;
        }
        return super.getImageName();
    }
    
    @Override
    public int compareTo(TCFNode n) {
        if (n instanceof TCFNodeExecContext) {
            TCFNodeExecContext f = (TCFNodeExecContext)n;
            if (seq_no < f.seq_no) return -1;
            if (seq_no > f.seq_no) return +1;
        }
        return id.compareTo(n.id);
    }
}

Back to the top