From 9ddde641192347f72707940fa6779573140ce042 Mon Sep 17 00:00:00 2001 From: Dmitry Kozlov Date: Thu, 11 Jul 2013 21:00:34 +0400 Subject: [PATCH] Bug 390827 - Trace View enhancement Enhance Trace Control View UI. Change-Id: I3ae49dece2056c8e8fd9eb21118926b039a5cdf0 Signed-off-by: Dmitry Kozlov Reviewed-on: https://git.eclipse.org/r/7997 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam Reviewed-by: Mikhail Khodjaiants IP-Clean: Mikhail Khodjaiants Tested-by: Mikhail Khodjaiants --- .../icons/full/obj16/circular_buffer.png | Bin 0 -> 411 bytes .../icons/full/obj16/disconnected_tracing.png | Bin 0 -> 913 bytes .../icons/full/obj16/refresh_auto.gif | Bin 0 -> 375 bytes .../icons/full/obj16/stop_visual_trace.gif | Bin 964 -> 961 bytes .../icons/full/obj16/tracevariables.gif | Bin 881 -> 115 bytes .../icons/full/obj16/write_obj.gif | Bin 0 -> 210 bytes dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml | 19 +- .../GdbSelectPrevTraceRecordCommand.java | 46 +- .../ui/commands/GdbStartTracingCommand.java | 21 +- .../ui/tracepoints/CircularProgress.java | 103 ++ .../internal/ui/tracepoints/FlatButton.java | 19 +- .../ui/tracepoints/FlatRadioButton.java | 109 ++ .../ui/tracepoints/TraceControlModel.java | 518 +++++++ .../ui/tracepoints/TraceControlView.java | 1288 +++++++++++------ .../ui/tracepoints/TraceVarDetailsDialog.java | 7 +- .../tracepoints/TracepointImageRegistry.java | 17 +- .../ui/tracepoints/TracepointsMessages.java | 59 +- .../TracepointsMessages.properties | 72 +- .../META-INF/MANIFEST.MF | 2 +- dsf-gdb/org.eclipse.cdt.dsf.gdb/pom.xml | 2 +- .../dsf/gdb/service/GDBTraceControl_7_2.java | 302 ++-- .../dsf/gdb/service/GDBTraceControl_7_4.java | 120 ++ .../gdb/service/GdbDebugServicesFactory.java | 4 + .../cdt/dsf/gdb/service/IGDBTraceControl.java | 83 +- .../dsf/gdb/service/IGDBTraceControl2.java | 49 + .../eclipse/cdt/dsf/gdb/service/Messages.java | 3 +- .../cdt/dsf/gdb/service/Messages.properties | 1 + .../mi/service/command/CommandFactory.java | 29 +- .../commands/MIGDBSetCircularTraceBuffer.java | 26 + .../commands/MIGDBSetDisconnectedTracing.java | 26 + .../command/commands/MIGDBSetTraceNotes.java | 26 + .../command/commands/MIGDBSetTraceUser.java | 26 + .../command/output/MITraceStatusInfo.java | 184 ++- 33 files changed, 2505 insertions(+), 656 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/circular_buffer.png create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/disconnected_tracing.png create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/refresh_auto.gif create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/write_obj.gif create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/CircularProgress.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatRadioButton.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlModel.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_4.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl2.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetCircularTraceBuffer.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetDisconnectedTracing.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceNotes.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceUser.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/circular_buffer.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/circular_buffer.png new file mode 100644 index 0000000000000000000000000000000000000000..c868cf3b6054c2d6386533529a36555a14d696c1 GIT binary patch literal 411 zcmV;M0c8G(P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*n+ z4^l*o$awod*ze`&-EA-GvKSW~ybDnf?D67Ul-2=kdummaDw`hesz; zHcq^DilhJ%&w<1>MpUPk{?5U;G&N4U{cPeA&xwN@Q7_J6hG8JF7XnKFk;E}T2s(_1 zb~_`34~bPX?zj5vLk2)(#tOhJah})2+~)QmJeNp=rolpy9C^1sJ-*h8;iLYi z1HMY5_Ba#aA`du6JhZIr$f873l|5esZTsoxt!h#b3$Y<^zsV<_J3$+Pz<`$7j7kjx zoR?lmypEjg$^aR=h-O`#Cifcm!~4|b$g7j~7|+iq`vzIfVMp)x%Uu8f002ovPDHLk FV1myssPO;* literal 0 HcmV?d00001 diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/disconnected_tracing.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/disconnected_tracing.png new file mode 100644 index 0000000000000000000000000000000000000000..cf470f99db49ecfca73ae4c151c43f812d0edd6d GIT binary patch literal 913 zcmV;C18)3@P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*n+ z4;2$|2=Cee00R+8L_t(I%Y~E6Yg~04N6+`(JCk`NPE+$}YAk9<>!YR8s1?D04_w&R zorNmZmEgvOg1h<`sEh90xDb@$Lhu1HdB9>@W0z!(`1`}Uq*-w6MM z2e^QC97)|=zdic%^>WLRm_k0sn=hT30=59xf)?;B3<-3A7_c6ot+m-|(+`(6>MNIC zJ4UE1m%mz}+Gws721f-LU!D7;)TynehbL!vXy(Esuya>IBvss~JbU@;MSEfPI6>bb z<7S98RN4_hJ`7s-Hnx6WIeGRH&9!eS-~95nG4_zP7H6y4oLN||T|NKYG^MIfM^&l$ zAy)f{2s&5|Dy3hq4-AeR7aQ^Tix;V^|Hk(po!Au-oU03K^KYMdn8HAY%|?&XW`^y0 zAFZ=^=^S&PU!?fmySV8*R#nhSaq{`s$!D_w6W*V90xEujcqwY_7KKzAr4mBxq2iEJ zuYAn<>J4Il9TPUONq~_fWV1so|L|7XaUG#l2`M+~#9_jA*H8(BB+-B&fA|?WcKQu5 zHbA%k0v#f81Ai~%(1TCljSi-89ZS8X&=vwe!dDSmM~HX?n^)}8{7(!PMnD|mP8+1m zpmbUOV-Dx#C#Pp`Z8s_Iv~fL`FzT_>?bGhYIF3Vkb&ts&fIXRS!RUgxRv zpG`QAJTNxz*@SL4;NXzpM~Zs2L8BXCbj;BgKAb%B-qN^=d+1(`%I+e?xhqV~zJtyK&@;Yo%h8Se|}#nD<|uy>D!Ipl+=d#7^${oqVovpsNzQsYQ&| zuz!F+O5F7LP*x%=QLk_FL7&>xVNcyHlMxXzKr2b;Az&cm0n@?{qptu_xb($`~CU){PFet-st$`?D_5T z`t|tz+~@b<>iFvL`SSMs`1<|k?)mWb`}6nw_4xbw`~CO%`}_R;{Qdp={QTM5*O-`* zo0^aQ{qLTfjr;Jl<>Jq#p@*WLi@mRSw5oltrh%)Zg~zpV#k6z6vURzvdi&mm`ORO- zw0hvkkJPeg)Us*Xy?nid7S*z8wtN(}eH5*75v_6(t#cBrauTL%5dZ)G|NsC0|NsC0 z|NsC0A^8LW002J#EC2ui01yBW000J*z@KnPEEZ45B+@7Z0Sr(m?8KDGG8l_CHbWI< z9c$}Cp}1nN)R4ydxNEJ#U_KZTbFAELg{w&Z5-LSHIuJT75DJP4BttDf8UzF_1P+7_ z4kbb@GCx)e3lX9bIuRy9U{+xQ2?>Nc2_c&`ZXYZ(6FLnIx+0D^H!L;}2(LN_9)mgu V49(6A97O>E8`aj7u?z&H2xvv0qo4X&JcnpUqLX`u#D@y#x=VLF_+o0gcACI1O=}N n%E^;#DhrieW-4p?$ygLUcj#p))_NjY{NmIix5-*O91PX~2sbFd diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/write_obj.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/write_obj.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed686b518dc23edcea11f449a37d49789462bcd3 GIT binary patch literal 210 zcmZ?wbhEHb6krfwIKsd%uV?<8?j^0QTYmof!=Re|lXZlOe z3{sjMWi&g{c1DWx?5u$Q|Nk?P0u+C;FfstG(gA4#*~!4_ub|Sm#DXU^%ZhJRUvsfc z@9JahlMKo_U$?vRt1;U}t&D&4A%I8GYngFmjM@B)*+w5cM0jp3S@ePTHv>zvqv2jb Vk@v@i-4r*K`H + + - - - - diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSelectPrevTraceRecordCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSelectPrevTraceRecordCommand.java index 7bd2a0bfee5..e2719b0ee7b 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSelectPrevTraceRecordCommand.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSelectPrevTraceRecordCommand.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 Ericsson and others. + * Copyright (c) 2010, 2013 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 @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Disable button when no trace record is selected *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.commands; @@ -25,6 +26,7 @@ import org.eclipse.cdt.dsf.gdb.service.GDBTraceControl_7_2.TraceRecordSelectedCh import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext; import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData2; import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; @@ -119,35 +121,37 @@ public class GdbSelectPrevTraceRecordCommand extends AbstractDebugCommand implem Query canSelectRecordQuery = new Query() { @Override public void execute(final DataRequestMonitor rm) { - IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + final IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); if (traceControl != null) { traceControl.getTraceStatus(dmc, new DataRequestMonitor(fExecutor, rm) { @Override protected void handleSuccess() { - if (getData().getNumberOfCollectedFrame() > 0) { - IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); - if (traceControl != null) { - traceControl.isTracing(dmc, new DataRequestMonitor(fExecutor, rm) { - @Override - protected void handleSuccess() { - rm.setData(!getData()); - rm.done(); - }; - }); - } else { - rm.setData(false); - rm.done(); - } - } else { - rm.setData(false); - rm.done(); + if (getData().getNumberOfCollectedFrame() <= 0) { + // No frames to look at. + rm.done(false); + return; } + + if (getData() instanceof ITraceStatusDMData2) { + if (((ITraceStatusDMData2)getData()).getCurrentTraceFrameId() == null) { + // Haven't started looking at frames, so don't enable the "Previous" button + rm.done(false); + return; + } + } + + traceControl.isTracing(dmc, new DataRequestMonitor(fExecutor, rm) { + @Override + protected void handleSuccess() { + // Can do visualization if we are tracing. + rm.done(!getData()); + }; + }); }; }); } else { - rm.setData(false); - rm.done(); + rm.done(false); } } }; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java index 5ca46d2f65a..9de35ffeec3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java @@ -16,10 +16,12 @@ import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.debug.core.model.IStartTracingHandler; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl2; import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; @@ -63,11 +65,20 @@ public class GdbStartTracingCommand extends AbstractDebugCommand implements ISta Query startTracingQuery = new Query() { @Override - public void execute(DataRequestMonitor rm) { - IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); - - if (traceControl != null) { - traceControl.startTracing(dmc, rm); + public void execute(final DataRequestMonitor rm) { + final IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + if (traceControl != null) { + String user = System.getProperty("user.name"); //$NON-NLS-1$ + if (user != null && user.length() > 0 && traceControl instanceof IGDBTraceControl2) { + ((IGDBTraceControl2)traceControl).setTraceUser(dmc, user, new ImmediateRequestMonitor() { + @Override + protected void handleCompleted() { + traceControl.startTracing(dmc, rm); + }; + }); + } else { + traceControl.startTracing(dmc, rm); + } } else { rm.done(); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/CircularProgress.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/CircularProgress.java new file mode 100644 index 00000000000..024a4133ff0 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/CircularProgress.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; + +public class CircularProgress extends Canvas { + + private static final String PERCENT_SIGN = "%"; //$NON-NLS-1$ + private static final String PERCENT_TEXT = "100%"; //$NON-NLS-1$ + private static final int PROGRESS_WIDTH = 8; + private static final int PROGRESS_MARGIN = 2; + private static final int PROGRESS_ARC = 15; + final protected int[] fBufferProgressMeasure = {0}; + + public CircularProgress(Composite parent, int flags) + { + super(parent, flags); + + addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + onPaint(e); + } + }); + + GC gc = new GC(this); + Point e = gc.textExtent(PERCENT_TEXT); + int size = e.x + 8 * PROGRESS_MARGIN + 2 * PROGRESS_WIDTH; + setBounds(0, 0, size, size); + } + + /** + * Set progress as number of percent (0-100) + */ + public void setProgress(int progress) { + fBufferProgressMeasure[0] = progress; + } + + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + return computeSize(wHint, hHint); + } + + @Override + public Point computeSize(int wHint, int hHint) { + return new Point(getBounds().width, getBounds().height); + } + + private void onPaint(PaintEvent e) { + Rectangle clientArea = getClientArea(); + int margin = PROGRESS_MARGIN; + int width = PROGRESS_WIDTH; + e.gc.setBackground(getParent().getBackground()); + e.gc.fillRectangle(0, 0, clientArea.width, clientArea.height); + e.gc.setBackground(getParent().getDisplay().getSystemColor(SWT.COLOR_GRAY)); + e.gc.fillOval(margin, margin, clientArea.width-2*margin, clientArea.height-2*margin); + e.gc.setBackground(getParent().getBackground()); + e.gc.fillOval(margin+width, margin+width, clientArea.width-2*(margin+width), clientArea.height-2*(margin+width)); + + String progress; + + e.gc.setBackground(getParent().getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION)); + if (0 <= fBufferProgressMeasure[0] && fBufferProgressMeasure[0] <= 100) { + // Draw usual progress bar and text value in % + progress = fBufferProgressMeasure[0] + PERCENT_SIGN; + int n = (int) (fBufferProgressMeasure[0] * 3.6); + e.gc.fillArc(margin, margin, clientArea.width-2*margin, clientArea.height-2*margin, 90 , -n ); + } else { + // Draw constantly moving progress without exact value and text value 100% + progress = PERCENT_TEXT; + int n = (int) ((fBufferProgressMeasure[0] % 100) * 3.6); + // Fill in the full buffer first + e.gc.fillOval(margin, margin, clientArea.width-2*margin, clientArea.height-2*margin); + // Move progress bar within the buffer + e.gc.setBackground(getParent().getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); + e.gc.fillArc(margin, margin, clientArea.width-2*margin, clientArea.height-2*margin, 90 - n - PROGRESS_ARC, - PROGRESS_ARC ); + } + e.gc.setBackground(getParent().getBackground()); + e.gc.fillOval(margin+width, margin+width, clientArea.width-2*(margin+width), clientArea.width-2*(margin+width)); + + // Progress % in the text form + e.gc.setForeground(getParent().getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + e.gc.setFont(getParent().getDisplay().getSystemFont()); + Point p = e.gc.textExtent(progress); + e.gc.drawText(progress,(clientArea.width - p.x)/2 + 1,(clientArea.height-p.y)/2); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatButton.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatButton.java index 76de2be0ac6..3f8922b24b5 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatButton.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatButton.java @@ -7,6 +7,7 @@ * * Contributors: * Vladimir Prus (Mentor Graphics) - initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - extend to be inheritance-friendly *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; @@ -28,9 +29,9 @@ import org.eclipse.swt.widgets.TypedListener; public class FlatButton extends Canvas { - private String fText; - private int fMargin = 4; - private Cursor fHandCursor; + protected String fText; + protected int fMargin = 4; + protected Cursor fHandCursor; public FlatButton(Composite parent, int flags) { super(parent, flags); @@ -48,9 +49,7 @@ public class FlatButton extends Canvas { addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { - if (isEnabled()) { - notifyListeners(SWT.Selection, null); - } + onSelection(e); } }); } @@ -94,7 +93,7 @@ public class FlatButton extends Canvas { return new Point(e.x + fMargin*2, e.y + fMargin*2); } - private void onPaint(PaintEvent event) { + protected void onPaint(PaintEvent event) { GC gc = event.gc; Rectangle ca = getClientArea(); @@ -123,4 +122,10 @@ public class FlatButton extends Canvas { borderColor.dispose(); shadowColor.dispose(); } + + protected void onSelection(MouseEvent e) { + if (isEnabled()) { + notifyListeners(SWT.Selection, null); + } + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatRadioButton.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatRadioButton.java new file mode 100644 index 00000000000..f260a6c51b5 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/FlatRadioButton.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2014 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: + * Dmitry Kozlov (Mentor Graphics) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; + +public class FlatRadioButton extends FlatButton { + + protected static final String STATE_OFF_LABEL = "OFF"; //$NON-NLS-1$ + protected static final String STATE_ON_LABEL = "ON"; //$NON-NLS-1$ + + protected boolean selection = false; + + public FlatRadioButton(Composite parent, int flags) { + super(parent, flags); + } + + @Override + public Point computeSize(int wHint, int hHint) { + + GC gc = new GC(this); + if (fText == null || fText.isEmpty()) { + Point e = gc.textExtent("A"); //$NON-NLS-1$ + return new Point(0, e.y + fMargin*2); + } + + Point e = gc.textExtent(fText); + Point pOn = gc.textExtent(STATE_ON_LABEL); + Point pOff = gc.textExtent(STATE_OFF_LABEL); + int h = Math.max(pOn.y, pOff.y); + return new Point(e.x + fMargin*4 + Math.max(pOn.x, pOff.x), Math.max(e.y, h) + fMargin*2 ); + } + + @Override + protected void onPaint(PaintEvent event) { + GC gc = event.gc; + Rectangle ca = getClientArea(); + + Color mainColor = gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION); + gc.setBackground(mainColor); + float[] mainHSB = mainColor.getRGB().getHSB(); + float h = mainHSB[0]; + float s = mainHSB[1]; + float b = mainHSB[2]; + + Point e = gc.textExtent(fText); + Color borderColor = new Color(gc.getDevice(), new RGB(h, s, (float)(b*0.7))); + Color shadowColor = new Color(gc.getDevice(), new RGB(h, s, (float)(b*0.5))); + + gc.setForeground(borderColor); + gc.drawRectangle(0, 0, ca.width-1, ca.height-1); + + gc.setForeground(shadowColor); + gc.drawLine(0, ca.height-1, ca.width-1, ca.height-1); + + gc.fillRectangle(e.x + fMargin*2 , 1, ca.width - 1 - e.x - fMargin*2 , ca.height-2); + + gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + gc.drawText(fText, fMargin, fMargin, true); + + gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); + Point pOn = gc.textExtent(STATE_ON_LABEL); + Point pOff = gc.textExtent(STATE_OFF_LABEL); + if (selection) { + int offset = pOn.x < pOff.x ? (pOff.x - pOn.x)/2 : 0; + gc.drawText(STATE_ON_LABEL , e.x + fMargin*3 + offset, fMargin); + } else { + int offset = pOn.x < pOff.x ? 0 : (pOn.x - pOff.x)/2 ; + gc.drawText(STATE_OFF_LABEL , e.x + fMargin*3 + offset, fMargin); + } + + borderColor.dispose(); + shadowColor.dispose(); + } + + @Override + protected void onSelection(MouseEvent e) { + if (isEnabled()) { + selection = ! selection; + notifyListeners(SWT.Selection, null); + redraw(); + } + } + + public void setSelection(boolean selection) { + this.selection = selection; + } + + public boolean getSelection() { + return selection; + } + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlModel.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlModel.java new file mode 100644 index 00000000000..024a40fc287 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlModel.java @@ -0,0 +1,518 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - Trace control view enhancements (Bug 390827) + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import java.util.Hashtable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +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.ImmediateRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints.TraceControlView.FailedTraceVariableCreationException; +import org.eclipse.cdt.dsf.gdb.service.GDBTraceControl_7_2.TraceRecordSelectedChangedEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData2; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceVariableDMData; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStartedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStoppedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingSupportedChangeDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl2; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; +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.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.contexts.DebugContextEvent; +import org.eclipse.debug.ui.contexts.IDebugContextListener; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchWindow; + +/** + * This class is a bridge between the TraceControl view and the TraceControl service. + * It performs the necessary requests to the service on behalf of the view. + * Those request must be done on the DSF Executor thread. + * Note that this class will have a single instance which will deal with + * all DSF debug sessions at the same time. + */ +public class TraceControlModel { + + private String fDebugSessionId; + private DsfServicesTracker fServicesTracker; + private volatile IGDBTraceControl fGDBTraceControl; + private volatile ITraceTargetDMContext fTargetContext; + private TraceControlView fTraceControlView; + + private IDebugContextListener fDebugContextListener = new IDebugContextListener() { + @Override + public void debugContextChanged(DebugContextEvent event) { + if ((event.getFlags() & DebugContextEvent.ACTIVATED) != 0) { + updateDebugContext(); + } + } + }; + + TraceControlModel(TraceControlView view) { + fTraceControlView = view; + + IWorkbenchWindow window = fTraceControlView.getSite().getWorkbenchWindow(); + DebugUITools.getDebugContextManager().getContextService(window).addDebugContextListener(fDebugContextListener); + updateDebugContext(); + } + + protected void updateContent() { + if (getSession() == null) { + notifyUI(TracepointsMessages.TraceControlView_trace_status_no_debug_session); + return; + } + + if (fTargetContext == null || fGDBTraceControl == null) { + notifyUI(TracepointsMessages.TraceControlView_trace_status_not_supported); + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + if (fTargetContext != null && fGDBTraceControl != null) { + fGDBTraceControl.getTraceStatus( + fTargetContext, new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + protected void handleCompleted() { + if (isSuccess() && getData() != null) { + notifyUI((ITraceStatusDMData2)getData()); + } else { + notifyUI((ITraceStatusDMData2)null); + } + } + }); + } else { + notifyUI((ITraceStatusDMData2)null); + } + } + }); + } + + public void init() { + if (fDebugSessionId != null) { + debugSessionChanged(); + } else { + updateDebugContext(); + } + } + + public void dispose() { + IWorkbenchWindow window = fTraceControlView.getSite().getWorkbenchWindow(); + DebugUITools.getDebugContextManager().getContextService(window).removeDebugContextListener(fDebugContextListener); + setDebugContext(null); + } + + protected void updateDebugContext() { + IAdaptable debugContext = DebugUITools.getDebugContext(); + if (debugContext instanceof IDMVMContext) { + setDebugContext((IDMVMContext)debugContext); + } else { + setDebugContext(null); + } + } + + protected void setDebugContext(IDMVMContext vmContext) { + if (vmContext != null) { + IDMContext dmContext = vmContext.getDMContext(); + String sessionId = dmContext.getSessionId(); + fTargetContext = DMContexts.getAncestorOfType(dmContext, ITraceTargetDMContext.class); + if (!sessionId.equals(fDebugSessionId)) { + if (getSession() != null) { + try { + final DsfSession session = getSession(); + session.getExecutor().execute(new DsfRunnable() { + @Override + public void run() { + session.removeServiceEventListener(TraceControlModel.this); + } + }); + } catch (RejectedExecutionException e) { + // Session is shut down. + } + } + fDebugSessionId = sessionId; + if (fServicesTracker != null) { + fServicesTracker.dispose(); + } + fServicesTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), sessionId); + getGDBTraceControl(); + debugSessionChanged(); + } + } else if (fDebugSessionId != null) { + if (getSession() != null) { + try { + final DsfSession session = getSession(); + session.getExecutor().execute(new DsfRunnable() { + @Override + public void run() { + session.removeServiceEventListener(TraceControlModel.this); + } + }); + } catch (RejectedExecutionException e) { + // Session is shut down. + } + } + fDebugSessionId = null; + fTargetContext = null; + if (fServicesTracker != null) { + fServicesTracker.dispose(); + fServicesTracker = null; + } + debugSessionChanged(); + } + } + + private void debugSessionChanged() { + if (getSession() != null) { + try { + final DsfSession session = getSession(); + session.getExecutor().execute(new DsfRunnable() { + @Override + public void run() { + session.addServiceEventListener(TraceControlModel.this, null); + } + }); + } catch (RejectedExecutionException e) { + // Session is shut down. + } + } + + updateContent(); + } + + public void exitVisualizationMode() { + if (getSession() == null) { + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + if (fTargetContext != null && fGDBTraceControl != null) { + if (fGDBTraceControl instanceof IGDBTraceControl2) { + ((IGDBTraceControl2)fGDBTraceControl).stopTraceVisualization(fTargetContext, new ImmediateRequestMonitor()); + } else { + // Legacy way of stopping visualization of trace data + ITraceRecordDMContext emptyDmc = fGDBTraceControl.createTraceRecordContext(fTargetContext, "-1"); //$NON-NLS-1$ + fGDBTraceControl.selectTraceRecord(emptyDmc, new ImmediateRequestMonitor()); + } + } + } + }); + } + + /** + * Get the list of trace variables from the backend. + * + * @return null when the list cannot be obtained. + */ + public ITraceVariableDMData[] getTraceVarList() { + if (getSession() == null) { + return null; + } + + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + + if (fTargetContext != null && fGDBTraceControl != null) { + fGDBTraceControl.getTraceVariables(fTargetContext, + new DataRequestMonitor(getSession().getExecutor(), rm) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + rm.setData(getData()); + } else { + rm.setData(null); + } + rm.done(); + }; + + }); + } else { + rm.setData(null); + rm.done(); + } + } + }; + try { + getSession().getExecutor().execute(query); + return query.get(1, TimeUnit.SECONDS); + } catch (InterruptedException exc) { + } catch (ExecutionException exc) { + } catch (TimeoutException e) { + } + + return null; + } + + /** + * Create a new trace variable in the backend. + * + * @throws FailedTraceVariableCreationException when the creation fails. The exception + * will contain the error message to display to the user. + */ + public void createVariable(final String name, final String value) throws FailedTraceVariableCreationException { + if (getSession() == null) { + throw new TraceControlView.FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); + } + + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + + if (fTargetContext != null && fGDBTraceControl != null) { + fGDBTraceControl.createTraceVariable(fTargetContext, name, value, + new RequestMonitor(getSession().getExecutor(), rm) { + @Override + protected void handleFailure() { + String message = TracepointsMessages.TraceControlView_create_variable_error; + Throwable t = getStatus().getException(); + if (t != null) { + message = t.getMessage(); + } + FailedTraceVariableCreationException e = + new FailedTraceVariableCreationException(message); + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Backend error", e)); //$NON-NLS-1$ + rm.done(); + }; + }); + } else { + FailedTraceVariableCreationException e = + new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_trace_variable_tracing_unavailable); + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Tracing unavailable", e)); //$NON-NLS-1$ + rm.done(); + } + } + }; + try { + getSession().getExecutor().execute(query); + query.get(); + } catch (InterruptedException e) { + // Session terminated + } catch (ExecutionException e) { + Throwable t = e.getCause(); + if (t instanceof CoreException) { + t = ((CoreException)t).getStatus().getException(); + if (t instanceof FailedTraceVariableCreationException) { + throw (FailedTraceVariableCreationException)t; + } + } + throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); + } + } + + public void setCurrentTraceRecord(final String traceRecordId) { + if (getSession() == null) { + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + if (fTargetContext != null && fGDBTraceControl != null) { + fGDBTraceControl.getCurrentTraceRecordContext( + fTargetContext, + new ImmediateDataRequestMonitor() { + @Override + protected void handleSuccess() { + final ITraceRecordDMContext previousDmc = getData(); + ITraceRecordDMContext nextRecord = fGDBTraceControl.createTraceRecordContext(fTargetContext, traceRecordId); + + // Must send the event right away to tell the services we are starting visualization + // If we don't, the services won't behave accordingly soon enough + // Bug 347514 + getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(nextRecord), new Hashtable()); + + fGDBTraceControl.selectTraceRecord(nextRecord, new ImmediateRequestMonitor() { + @Override + protected void handleError() { + // If we weren't able to select the next record, we must notify that we are still on the previous one + // since we have already sent a TraceRecordSelectedChangedEvent early, but it didn't happen. + getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(previousDmc), new Hashtable()); + } + }); + }; + }); + + + + } + } + }); + } + + public void setCircularBuffer(final boolean useCircularBuffer) { + if (getSession() == null) { + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + if (fTargetContext != null && fGDBTraceControl != null && fGDBTraceControl instanceof IGDBTraceControl2) { + ((IGDBTraceControl2)fGDBTraceControl).setCircularTraceBuffer(fTargetContext, useCircularBuffer, new ImmediateRequestMonitor()); + } + } + }); + } + + public void setDisconnectedTracing(final boolean disconnected) { + if (getSession() == null) { + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + if (fTargetContext != null && fGDBTraceControl != null && fGDBTraceControl instanceof IGDBTraceControl2) { + ((IGDBTraceControl2)fGDBTraceControl).setDisconnectedTracing(fTargetContext, disconnected, new ImmediateRequestMonitor()); + } + } + }); + } + + public void setTraceNotes(final String notes) { + if (getSession() == null) { + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + if (fTargetContext != null && fGDBTraceControl != null && fGDBTraceControl instanceof IGDBTraceControl2) { + ((IGDBTraceControl2)fGDBTraceControl).setTraceNotes(fTargetContext, notes, new ImmediateRequestMonitor()); + } + } + }); + } + + private void getGDBTraceControl() { + if (getSession() == null) { + fGDBTraceControl = null; + return; + } + + getSession().getExecutor().execute( + new DsfRunnable() { + @Override + public void run() { + fGDBTraceControl = getService(IGDBTraceControl.class); + } + }); + } + + private DsfSession getSession() { + return DsfSession.getSession(fDebugSessionId); + } + + private V getService(Class serviceClass) { + if (fServicesTracker != null) { + return fServicesTracker.getService(serviceClass); + } + return null; + } + + private void notifyUI(final ITraceStatusDMData2 data) { + final TraceControlView v = fTraceControlView; + if (v != null) { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (v != null) { + v.fLastRefreshTime = System.currentTimeMillis(); + v.updateUI(data); + } + } + }); + } + } + + private void notifyUI(final String message) { + final TraceControlView v = fTraceControlView; + if (v != null) { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (v != null) { + v.updateUI(message); + } + } + }); + } + } + + /* + * When tracing starts, we know the status has changed + */ + @DsfServiceEventHandler + public void handleEvent(ITracingStartedDMEvent event) { + updateContent(); + } + + /* + * When tracing stops, we know the status has changed + */ + @DsfServiceEventHandler + public void handleEvent(ITracingStoppedDMEvent event) { + updateContent(); + } + + @DsfServiceEventHandler + public void handleEvent(ITraceRecordSelectedChangedDMEvent event) { + updateContent(); + } + /* + * Since something suspended, might as well refresh our status + * to show the latest. + */ + @DsfServiceEventHandler + public void handleEvent(ISuspendedDMEvent event) { + updateContent(); + } + + /* + * Tracing support has changed, update view + */ + @DsfServiceEventHandler + public void handleEvent(ITracingSupportedChangeDMEvent event) { + updateContent(); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java index e4b54b11dc9..ed90ae4603e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java @@ -1,71 +1,58 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2013 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: - * Ericsson - initial API and implementation + * Ericsson - Initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - Trace control view enhancements (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.RejectedExecutionException; +import java.text.DateFormat; +import java.util.Date; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -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.ImmediateRequestMonitor; -import org.eclipse.cdt.dsf.concurrent.Query; -import org.eclipse.cdt.dsf.concurrent.RequestMonitor; -import org.eclipse.cdt.dsf.datamodel.DMContexts; -import org.eclipse.cdt.dsf.datamodel.IDMContext; -import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceVariableDMData; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStartedDMEvent; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStoppedDMEvent; -import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingSupportedChangeDMEvent; -import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; -import org.eclipse.cdt.dsf.service.DsfServicesTracker; -import org.eclipse.cdt.dsf.service.DsfSession; -import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener; -import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData2; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.STOP_REASON_ENUM; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Slider; +import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IMemento; -import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewSite; -import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.progress.UIJob; /** * TraceControlView Part @@ -74,11 +61,13 @@ import org.eclipse.ui.part.ViewPart; * * @since 2.1 */ -public class TraceControlView extends ViewPart implements IViewPart, SessionEndedListener { +public class TraceControlView extends ViewPart implements IViewPart { + private static final int ACTION_BUTTON_INDENTATION = 10; private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + protected static final int UI_REFRESH_DELAY = 1000; // milliseconds - public class FailedTraceVariableCreationException extends Exception { + public static class FailedTraceVariableCreationException extends Exception { private static final long serialVersionUID = -3042693455630687285L; FailedTraceVariableCreationException() {} @@ -87,24 +76,62 @@ public class TraceControlView extends ViewPart implements IViewPart, SessionEnde super(errorMessage); } } - + /** * Action to refresh the content of the view. */ - private final class ActionRefreshView extends Action { - public ActionRefreshView() { + private final class RefreshViewAction extends Action { + public RefreshViewAction() { setText(TracepointsMessages.TraceControlView_action_Refresh_label); setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_enabled)); setDisabledImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_disabled)); } @Override public void run() { - updateContent(); + fLastRefreshTime = System.currentTimeMillis(); + fTraceControlModel.updateContent(); } } - private final class ActionOpenTraceVarDetails extends Action { - public ActionOpenTraceVarDetails() { + /** + * Action to automatically refresh the content of the view by polling trace-status. + */ + protected final class AutoRefreshAction extends Action { + public AutoRefreshAction() { + super(TracepointsMessages.TraceControlView_auto_refresh_action_label, AS_CHECK_BOX); + setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_Auto)); + } + @Override + public void run() { + if (isChecked()) { + // Call to updateContent which starts refreshUI job only if necessary + // (when tracing is running) + fAutoRefreshEnabled = true; + fRefreshViewAction.setEnabled(false); + fTraceControlModel.updateContent(); + } else { + fAutoRefreshEnabled = false; + fRefreshViewAction.setEnabled(true); + } + } + } + + /** + * Action to refresh the content of the view. + */ + protected final class DisconnectedTracingAction extends Action { + public DisconnectedTracingAction() { + super(TracepointsMessages.TraceControlView_action_Disconnected_tracing_label, AS_CHECK_BOX); + setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Disconnected_Tracing)); + } + @Override + public void run() { + fTraceControlModel.setDisconnectedTracing(isChecked()); + } + } + + protected final class OpenTraceVarDetailsAction extends Action { + public OpenTraceVarDetailsAction() { setText(TracepointsMessages.TraceControlView_action_trace_variable_details); setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Trace_Variables)); } @@ -116,47 +143,63 @@ public class TraceControlView extends ViewPart implements IViewPart, SessionEnde } } - private final class ActionExitVisualizationModeDetails extends Action { - public ActionExitVisualizationModeDetails() { + protected final class ExitVisualizationModeDetailsAction extends Action { + public ExitVisualizationModeDetailsAction() { setText(TracepointsMessages.TraceControlView_action_exit_visualization_mode); setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Exit_Visualization)); } @Override public void run() { - asyncExec(new Runnable() { - @Override - public void run() { - exitVisualizationMode(); - updateActionEnablement(); - }}); + fTraceControlModel.exitVisualizationMode(); + // Content of view will be updated from the event + // triggered by this asynchronous operation. } } - private ISelectionListener fDebugViewListener; - private String fDebugSessionId; - private DsfServicesTracker fServicesTracker; - private volatile ITraceTargetDMContext fTargetContext; + protected TraceControlModel fTraceControlModel; - private StyledText fStatusText; - protected Action fActionRefreshView; - protected Action fOpenTraceVarDetails; - protected Action fActionExitVisualization; - private boolean fTracingSupported; + protected RefreshViewAction fRefreshViewAction; + protected boolean fAutoRefreshEnabled; + protected DisconnectedTracingAction fDisconnectedTracingAction; + protected OpenTraceVarDetailsAction fOpenTraceVarDetails; + protected ExitVisualizationModeDetailsAction fExitVisualizationAction; + protected AutoRefreshAction fAutoRefreshAction; + protected boolean fTraceVisualization; + protected Job refreshUIJob; + protected Font cachedBold; + protected long fLastRefreshTime; + protected ITraceStatusDMData2 fLastTraceData; - private boolean fTraceVisualization; + protected Composite fTopComposite; + protected Composite fStatusComposite; + protected Label fStatusLabel; + protected Label fSecondaryStatusLabel; + protected Composite fSecondaryStatusComposite; + protected FlatButton fActionButton; + + protected Composite fBufferComposite; + protected Label fBufferCollectedFramesLabel; + protected FlatRadioButton fSetCircularBufferButton; + protected CircularProgress fBufferProgress; + + protected Composite fFrameComposite; + protected Label fFrameLabel; + protected Label fFrameNumberLabel; + protected Slider fFrameSlider; + protected Composite fNotesComposite; + protected Label fNotesContentLabel; + protected Text fNotesContentText; + protected Button fSetNotesButton; + + public TraceControlView() { } - + @Override public void init(IViewSite site) throws PartInitException { super.init(site); - site.getPage().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, - fDebugViewListener = new ISelectionListener() { - @Override - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - updateDebugContext(); - }}); + fTraceControlModel = new TraceControlModel(this); } @Override @@ -166,429 +209,794 @@ public class TraceControlView extends ViewPart implements IViewPart, SessionEnde @Override public void createPartControl(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(1, false); - composite.setLayout(layout); - - // Let's just create a place to put a text status for now. - // A fancier display would be nicer though - fStatusText = new StyledText(composite, SWT.MULTI); - GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); - fStatusText.setLayoutData(gd); - fStatusText.setEditable(false); - fStatusText.setCaret(null); - - createActions(); - if (fDebugSessionId != null) { - debugSessionChanged(); - } else { - updateDebugContext(); - } - DsfSession.addSessionEndedListener(this); + createActions(); + + fTopComposite = new Composite(parent, SWT.NONE); + GridLayout topLayout = new GridLayout(1, false); + topLayout.marginWidth = 0; + topLayout.marginHeight = 0; + fTopComposite.setLayout(topLayout); + fTopComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE)); + + // Tracing status line + createStatusLine(fTopComposite); + + // Secondary status: start time, stop time and reason + setSecondaryStatusLineVisible(false, null); + + // Buffer line + createBufferLine(fTopComposite); + setBufferLineVisible(false, null, false); + + // Frame line + createFrameLine(fTopComposite); + setFrameLineVisible(false, null); + + // Trace notes + //createNotesLine(fTopComposite); + //setNotesLineVisible(false, null, false); + + fTraceControlModel.init(); } + protected void createStatusLine(Composite parent) { + fStatusComposite = new Composite(parent, SWT.NONE); + GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); + gd.horizontalSpan = 2; + gd.minimumHeight = 22; + fStatusComposite.setLayoutData(gd); + GridLayout l = new GridLayout(2,false); + l.marginBottom = 0; + fStatusComposite.setLayout(l); + fStatusComposite.setBackgroundMode(SWT.INHERIT_FORCE); + + fStatusLabel = new Label(fStatusComposite, SWT.NONE); + if (cachedBold == null) { + FontData fontData = fStatusLabel.getFont().getFontData()[0]; + fontData.setStyle(SWT.BOLD); + cachedBold = new Font(fStatusLabel.getDisplay(),fontData); + } + fStatusLabel.setFont(cachedBold); + GridData d = new GridData(SWT.LEFT, SWT.CENTER, false, false); + fStatusLabel.setLayoutData(d); + fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_no_debug_session); + fStatusLabel.setBackground(parent.getBackground()); + + fActionButton = new FlatButton(fStatusComposite, SWT.NONE); + fActionButton.setText(EMPTY_STRING); + GridData acGd = new GridData(SWT.LEFT, SWT.CENTER, false, false); + acGd.horizontalIndent = ACTION_BUTTON_INDENTATION; + fActionButton.setLayoutData(acGd); + fActionButton.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + // Run action + IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class); + if (handlerService == null) { + GdbUIPlugin.log(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Missing command handler service")); //$NON-NLS-1$ + return; + } + + try { + String text = ((FlatButton)e.getSource()).getText(); + if (TracepointsMessages.TraceControlView_action_start.equals(text) || + TracepointsMessages.TraceControlView_action_restart.equals(text)) { + handlerService.executeCommand("org.eclipse.cdt.debug.ui.command.startTracing", null); //$NON-NLS-1$ + } else if (TracepointsMessages.TraceControlView_action_stop.equals(text)) { + handlerService.executeCommand("org.eclipse.cdt.debug.ui.command.stopTracing", null); //$NON-NLS-1$ + } else if (TracepointsMessages.TraceControlView_action_finish_visualization.equals(text)) { + fTraceControlModel.exitVisualizationMode(); + } + // Note that the content of the view will be updated due to the event + // triggered by the above operations. There is no point in updating the + // content ourselves since some of the above calls are asynchronous + // and have not completed yet. + } catch (Exception ex) { + GdbUIPlugin.log(ex); + } + } + + }); + + fSecondaryStatusLabel = new Label(fStatusComposite, SWT.NONE | SWT.WRAP); + GridData sslGd = new GridData(SWT.FILL, SWT.TOP, true, false); + sslGd.horizontalSpan = 2; + fSecondaryStatusLabel.setLayoutData(sslGd); + fSecondaryStatusLabel.setBackground(parent.getBackground()); + + Label separator = new Label(fStatusComposite, SWT.SEPARATOR | SWT.HORIZONTAL); + GridData sGd = new GridData(SWT.FILL, SWT.BOTTOM, true, false); + //sGd.heightHint = 3; + sGd.horizontalSpan = 2; + separator.setLayoutData(sGd); + } + + protected void setActionLinkVisible(boolean visible, String text) { + fActionButton.setVisible(visible); + fActionButton.setText(visible ? text: EMPTY_STRING); + } + + private void setSecondaryStatusLineVisible(boolean visible, ITraceStatusDMData2 tData) { + fSecondaryStatusLabel.setVisible(visible); + ((GridData)fSecondaryStatusLabel.getLayoutData()).exclude = !visible; + + if (visible && tData != null) { + STOP_REASON_ENUM stopReason = tData.getStopReason(); + if (stopReason != null) { + fSecondaryStatusLabel.setText(getStopMessage(tData)); + } else if (tData.isTracingActive() && tData.getStartTime() != null) { + String user = EMPTY_STRING; + String lastRefreshed = EMPTY_STRING; + // In case autorefresh is disabled, show when view was manually refreshed last time + if (!fAutoRefreshEnabled) { + lastRefreshed = TracepointsMessages.bind( + TracepointsMessages.TraceControlView_trace_status_secondary_refresh_time, + formatTimeInterval(fLastRefreshTime, System.currentTimeMillis(), true)); + } + if (tData.getUserName() != null && tData.getUserName().length() > 0) { + user = TracepointsMessages.bind(TracepointsMessages.TraceControlView_trace_status_secondary_user, tData.getUserName()); + } + fSecondaryStatusLabel.setText(TracepointsMessages.bind( + TracepointsMessages.TraceControlView_trace_status_secondary_running, + new Object[] { + formatTime(tData.getStartTime()), + user, + lastRefreshed} + )); + } else { + // Should not happen if usage is correct + fSecondaryStatusLabel.setText(EMPTY_STRING); + } + } else { + fSecondaryStatusLabel.setText(EMPTY_STRING); + } + } + + protected void createNotesLine(final Composite parent) { + // Trace notes: notes text and edit notes button + fNotesComposite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + fNotesComposite.setLayout(layout); + fNotesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + fNotesComposite.setBackgroundMode(SWT.INHERIT_FORCE); + + // Separator on the left of whole notes composite + Label separator = new Label(fNotesComposite, SWT.SEPARATOR | SWT.VERTICAL); + GridData slGd = new GridData(SWT.RIGHT, SWT.FILL, false, true); + //slGd.widthHint = 3; + slGd.verticalSpan = 4; + separator.setLayoutData(slGd); + separator.setBackground(fNotesComposite.getBackground()); + + Label fNotesLabel = new Label(fNotesComposite, SWT.NONE); + fNotesLabel.setBackground(parent.getBackground()); + fNotesLabel.setText(TracepointsMessages.TraceControlView_trace_notes_label); + if (cachedBold != null) { + fNotesLabel.setFont(cachedBold); + } + + fSetNotesButton = new Button(fNotesComposite, SWT.TOGGLE); + fSetNotesButton.setImage(TracepointImageRegistry.getImageDescriptor( + TracepointImageRegistry.ICON_Edit_enabled).createImage()); + fSetNotesButton.setSelection(false); + fSetNotesButton.setToolTipText(TracepointsMessages.TraceControlView_trace_notes_edit_tooltip); + fSetNotesButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false)); + fSetNotesButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + handleEditNotesButtonPressed(); + } + }); + + fNotesContentLabel = new Label(fNotesComposite, SWT.WRAP); + fNotesContentLabel.setBackground(parent.getBackground()); + fNotesContentLabel.setText(TracepointsMessages.TraceControlView_trace_notes_not_set); + GridData nclGd = new GridData(SWT.FILL, SWT.TOP, true, false); + nclGd.horizontalSpan = 2; + fNotesContentLabel.setLayoutData(nclGd); + + fNotesContentText = new Text(fNotesComposite, SWT.BORDER); + fNotesContentText.setVisible(false); + GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false); + gd.horizontalSpan = 2; + gd.exclude = true; + fNotesContentText.setLayoutData(gd); + fNotesContentText.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + fSetNotesButton.setSelection(false); + handleEditNotesButtonPressed(); + } + }); + fNotesContentText.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == 0x1b) { + // Esc was pressed, cancel editing + fSetNotesButton.setSelection(false); + handleEditNotesButtonPressed(true); + } + } + }); + + } + + protected void handleEditNotesButtonPressed() { + handleEditNotesButtonPressed(false); + } + + protected void handleEditNotesButtonPressed(boolean cancelEditing) { + boolean isEditMode = fSetNotesButton.getSelection(); + fNotesContentLabel.setVisible(!isEditMode); + ((GridData)fNotesContentLabel.getLayoutData()).exclude = isEditMode; + + fNotesContentText.setVisible(isEditMode); + ((GridData)fNotesContentText.getLayoutData()).exclude = !isEditMode; + + fNotesContentText.setFocus(); + + if (isEditMode) { + String txt = fNotesContentLabel.getText(); + txt = TracepointsMessages.TraceControlView_trace_notes_not_set.equals(txt) ? EMPTY_STRING : txt; + fNotesContentText.setText(txt); + fSetNotesButton.setToolTipText(TracepointsMessages.TraceControlView_trace_notes_save_tooltip); + } else { + fSetNotesButton.setToolTipText(TracepointsMessages.TraceControlView_trace_notes_edit_tooltip); + if (!cancelEditing) { + fNotesContentLabel.setText(fNotesContentText.getText()); + fNotesContentLabel.getSize(); + fTraceControlModel.setTraceNotes(fNotesContentText.getText()); + } + } + fNotesComposite.layout(); + fNotesComposite.redraw(); + fTraceControlModel.updateContent(); + } + + + protected void setNotesLineVisible(boolean visible, ITraceStatusDMData2 tData, boolean readonly) { + fNotesComposite.setVisible(visible); + ((GridData)fNotesComposite.getLayoutData()).exclude = !visible; + + if (visible) { + if (tData.getNotes() != null && tData.getNotes().length() > 0) { + fNotesContentLabel.setText(removeQuotes(tData.getNotes())); + } else { + fNotesContentLabel.setText(TracepointsMessages.TraceControlView_trace_notes_not_set); + } + if (tData != null && tData.getStartTime() != null) + fSetNotesButton.setEnabled(!readonly); + } + } + + protected void createFrameLine(Composite parent) { + fFrameComposite = new Composite(parent, SWT.NONE); + GridData fcGd = new GridData(SWT.FILL, SWT.TOP, true, false); + fcGd.horizontalSpan = 2; + fFrameComposite.setLayoutData(fcGd); + GridLayout layout = new GridLayout(2, false); + layout.marginHeight = 0; + fFrameComposite.setLayout(layout); + + Label separator = new Label(fFrameComposite, SWT.SEPARATOR | SWT.HORIZONTAL); + GridData sepGd = new GridData(SWT.FILL, SWT.CENTER, true, false); + sepGd.horizontalSpan = 2; + sepGd.verticalIndent = 2; + separator.setLayoutData(sepGd); + + fFrameSlider = new Slider(fFrameComposite, SWT.HORIZONTAL | SWT.BORDER); + GridData gd2 = new GridData(SWT.FILL, SWT.CENTER, true, false); + gd2.horizontalSpan = 2; + fFrameSlider.setLayoutData(gd2); + fFrameSlider.setValues(0, 0, 100, 1, 1, 10); + fFrameSlider.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class); + if (e.detail == SWT.ARROW_DOWN) { + try { + handlerService.executeCommand("org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord", null); //$NON-NLS-1$ + } catch (Exception ex) { + } + } else if (e.detail == SWT.ARROW_UP) { + try { + handlerService.executeCommand("org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord", null); //$NON-NLS-1$ + } catch (Exception ex) { + } + } else if (e.detail == SWT.DRAG) { + // We don't want to query gdb while user drags thumb, just update the label instead + // but postpone actual gdb query to the time thumb is released (e.detail == SWT.NONE) + fFrameNumberLabel.setText(TracepointsMessages.bind( + TracepointsMessages.TraceControlView_frame_dragging, + fFrameSlider.getSelection())); + } else { + fTraceControlModel.setCurrentTraceRecord(Integer.toString(fFrameSlider.getSelection())); + } + } + + }); + + fFrameLabel = new Label(fFrameComposite, SWT.NONE); + fFrameLabel.setText(TracepointsMessages.TraceControlView_frame_label); + fFrameLabel.setLayoutData(new GridData()); + + fFrameNumberLabel = new Label(fFrameComposite, SWT.NONE); + fFrameNumberLabel.setText(TracepointsMessages.TraceControlView_frame_not_looking); + GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); + fFrameNumberLabel.setLayoutData(gd); + } + + protected void setFrameLineVisible(boolean visible, ITraceStatusDMData2 traceData) { + fFrameComposite.setVisible(visible); + ((GridData)fFrameComposite.getLayoutData()).exclude = !visible; + + if (visible) { + fFrameSlider.setMinimum(0); + if (traceData.getNumberOfCollectedFrame() == 0) { + fFrameSlider.setMaximum(1); + } else { + fFrameSlider.setMaximum(traceData.getNumberOfCollectedFrame()); + } + int inc = traceData.getNumberOfCollectedFrame() / 20; + fFrameSlider.setPageIncrement(inc <= 1 ? 2 : inc); + + String fl = EMPTY_STRING; + if (traceData.getCurrentTraceFrameId() != null) { + fl += TracepointsMessages.bind(TracepointsMessages.TraceControlView_frame_looking, + new Object[] { traceData.getCurrentTraceFrameId(), + new Integer(traceData.getTracepointNumberForCurrentTraceFrame())} ); + int recId = 0; + try { + recId = Integer.parseInt(traceData.getCurrentTraceFrameId()); + } catch (NumberFormatException e) { + } + fFrameSlider.setSelection(recId); + } else { + fl += TracepointsMessages.bind(TracepointsMessages.TraceControlView_frame_not_looking, traceData.getNumberOfCollectedFrame()); + fFrameSlider.setSelection(0); + } + fFrameNumberLabel.setText(fl); + } + if (traceData != null && traceData != null) { + fFrameSlider.setEnabled(traceData.getNumberOfCollectedFrame() != 0); + } + } + + protected void createBufferLine(final Composite parent) { + + fBufferComposite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + layout.marginHeight = 0; + fBufferComposite.setLayout(layout); + GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false); + fBufferComposite.setLayoutData(gd); + fBufferComposite.setBackgroundMode(SWT.INHERIT_FORCE); + + Label fBufferLabel = new Label(fBufferComposite, SWT.NONE); + fBufferLabel.setText(TracepointsMessages.TraceControlView_buffer_label); + if (cachedBold != null) { + fBufferLabel.setFont(cachedBold); + } + GridData gdBL = new GridData(SWT.FILL, SWT.CENTER, true, false); + fBufferLabel.setLayoutData(gdBL); + fBufferLabel.setBackground(fBufferComposite.getBackground()); + + fBufferProgress = new CircularProgress(fBufferComposite, SWT.NONE); + GridData bpGd = new GridData(SWT.CENTER, SWT.TOP, false, false); + bpGd.verticalSpan = 2; + fBufferProgress.setLayoutData(bpGd); + + fSetCircularBufferButton = new FlatRadioButton(fBufferComposite, SWT.NONE); + fSetCircularBufferButton.setText(TracepointsMessages.TraceControlView_buffer_circular_button_label); + fSetCircularBufferButton.setSelection(false); + fSetCircularBufferButton.setEnabled(true); + fSetCircularBufferButton.setToolTipText(TracepointsMessages.TraceControlView_buffer_circular_off_tooltip); + GridData cbbGd = new GridData(SWT.RIGHT, SWT.CENTER, false, false); + cbbGd.horizontalIndent = 20; + fSetCircularBufferButton.setLayoutData(cbbGd); + fSetCircularBufferButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + fTraceControlModel.setCircularBuffer(fSetCircularBufferButton.getSelection()); + fTraceControlModel.updateContent(); + } + }); + + fBufferCollectedFramesLabel = new Label(fBufferComposite, SWT.WRAP); + fBufferCollectedFramesLabel.setText(TracepointsMessages.TraceControlView_buffer_label); + GridData gd3 = new GridData(SWT.FILL, SWT.BOTTOM, true, false); + fBufferCollectedFramesLabel.setLayoutData(gd3); + } + + protected void setBufferLineVisible(boolean visible, ITraceStatusDMData2 tData, boolean readonly) { + fBufferComposite.setVisible(visible); + ((GridData)fBufferComposite.getLayoutData()).exclude = !visible; + + if (visible && tData != null){ + if (tData.getStopReason() != null && tData.getStopReason() == STOP_REASON_ENUM.OVERFLOW){ + // Buffer overflowed, it should be 100% full instead of 99% + fBufferProgress.setProgress(100); + } else if (tData.getStopReason() != null && tData.isCircularBuffer() && tData.getNumberOfCreatedFrames() > tData.getNumberOfCollectedFrame()) { + // Buffer is circular and overflowed once, it should be 100% full instead of 99% + fBufferProgress.setProgress(100); + } else if (tData.isCircularBuffer() && tData.isTracingActive() && + tData.getNumberOfCreatedFrames() > tData.getNumberOfCollectedFrame()) { + // If we run with Circular buffer and all buffer was filled in once, we continue displaying progress 100% + // and showing moving bar that makes a circle every tData.getNumberOfCollectedFrame() because it is buffer size in frames + // and actual number of collected frames from the start is tData.getNumberOfCreatedFrames(), but only last + // tData.getNumberOfCollectedFrame() are stored in the buffer + int p = (tData.getNumberOfCreatedFrames() % tData.getNumberOfCollectedFrame()) * 100 / tData.getNumberOfCollectedFrame(); + // 100 is an indicator that buffer is already full and should be showed in different manner + fBufferProgress.setProgress(100 + p); + } else { + fBufferProgress.setProgress((tData.getTotalBufferSize() - tData.getFreeBufferSize()) * 100 / tData.getTotalBufferSize()); + } + + fSetCircularBufferButton.setSelection(tData.isCircularBuffer()); + fSetCircularBufferButton.setEnabled(!readonly); + fSetCircularBufferButton.setToolTipText(fSetCircularBufferButton.getSelection() ? + TracepointsMessages.TraceControlView_buffer_circular_on_tooltip : + TracepointsMessages.TraceControlView_buffer_circular_off_tooltip); + fSetCircularBufferButton.redraw(); + fSetCircularBufferButton.update(); + + fBufferCollectedFramesLabel.setText(TracepointsMessages.bind( + TracepointsMessages.TraceControlView_buffer_frames_collected, + tData.getNumberOfCollectedFrame(), + (tData.getTotalBufferSize() - tData.getFreeBufferSize())/1000)); + fBufferProgress.redraw(); + fBufferProgress.update(); + } + } + protected void createActions() { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + window.getActivePage().showActionSet("org.eclipse.cdt.debug.ui.tracepointActionSet"); //$NON-NLS-1$ + IActionBars bars = getViewSite().getActionBars(); IToolBarManager manager = bars.getToolBarManager(); - - // Create the action to refresh the view - fActionRefreshView = new ActionRefreshView(); - bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fActionRefreshView); - manager.add(fActionRefreshView); + // Create the action to refresh the view + fRefreshViewAction = new RefreshViewAction(); + bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fRefreshViewAction); + manager.add(fRefreshViewAction); + fRefreshViewAction.setEnabled(false); + + fAutoRefreshAction = new AutoRefreshAction(); + manager.add(fAutoRefreshAction); + fAutoRefreshAction.setChecked(true); + fAutoRefreshAction.setEnabled(true); + fAutoRefreshEnabled = true; + fLastRefreshTime = System.currentTimeMillis(); + + fDisconnectedTracingAction = new DisconnectedTracingAction(); + manager.add(fDisconnectedTracingAction); + fDisconnectedTracingAction.setEnabled(false); + // Create the action to open the trace variable details - fOpenTraceVarDetails = new ActionOpenTraceVarDetails(); + fOpenTraceVarDetails = new OpenTraceVarDetailsAction(); manager.add(fOpenTraceVarDetails); // Create the action to exit visualization mode - fActionExitVisualization = new ActionExitVisualizationModeDetails(); - manager.add(fActionExitVisualization); + fExitVisualizationAction = new ExitVisualizationModeDetailsAction(); + manager.add(fExitVisualizationAction); bars.updateActionBars(); - updateActionEnablement(); + updateActionEnablement(null); } @Override public void dispose() { - getSite().getPage().removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, fDebugViewListener); - fStatusText = null; // Indicate that we have been disposed - setDebugContext(null); - DsfSession.removeSessionEndedListener(this); + fTraceControlModel.dispose(); + fStatusLabel = null; // Indicate that we have been disposed + if (refreshUIJob != null) { + refreshUIJob.cancel(); + } + + if (cachedBold != null) { + cachedBold.dispose(); + cachedBold = null; + } + super.dispose(); } - - protected void updateContent() { - if (fDebugSessionId != null && getSession() != null) { - final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); - if (ctx != null) { - getSession().getExecutor().execute( - new DsfRunnable() { - @Override - public void run() { - final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); - if (traceControl != null) { - traceControl.getTraceStatus( - ctx, new DataRequestMonitor(getSession().getExecutor(), null) { - @Override - protected void handleCompleted() { - String traceStatus = EMPTY_STRING; - if (isSuccess() && getData() != null) { - fTracingSupported = getData().isTracingSupported(); - if (fTracingSupported) { - traceStatus = getData().toString(); - if (traceStatus.length() > 0) { - Calendar cal = Calendar.getInstance(); - SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$ - - traceStatus = TracepointsMessages.TraceControlView_trace_view_content_updated_label + - sdf.format(cal.getTime()) + "\n" + traceStatus; //$NON-NLS-1$ - } - } - } else { - fTracingSupported = false; - } - - final String finalStatus = traceStatus; - asyncExec(new Runnable() { - @Override - public void run() { - fStatusText.setText(finalStatus); - updateActionEnablement(); - }}); - } - }); - } else { - fTracingSupported = false; - - asyncExec(new Runnable() { - @Override - public void run() { - fStatusText.setText(EMPTY_STRING); - updateActionEnablement(); - }}); - } - - } - }); - return; - } - } - - if (fStatusText != null) { - fStatusText.setText(EMPTY_STRING); - } - updateActionEnablement(); - } - - protected void exitVisualizationMode() { - if (fDebugSessionId == null || getSession() == null) { - return; - } - - final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); - if (ctx == null) { - return; - } - - getSession().getExecutor().execute( - new DsfRunnable() { - @Override - public void run() { - final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); - if (traceControl != null) { - ITraceRecordDMContext emptyDmc = traceControl.createTraceRecordContext(ctx, "-1"); //$NON-NLS-1$ - traceControl.selectTraceRecord(emptyDmc, new ImmediateRequestMonitor()); - } - } - }); - } - protected void updateDebugContext() { - IAdaptable debugContext = DebugUITools.getDebugContext(); - if (debugContext instanceof IDMVMContext) { - setDebugContext((IDMVMContext)debugContext); + protected void updateUI(final String statusMessage) { + try { + fLastTraceData = null; + setSecondaryStatusLineVisible(false, null); + //setNotesLineVisible(false, null, false); + setFrameLineVisible(false, null); + setBufferLineVisible(false, null, false); + fStatusLabel.setText(statusMessage); + setActionLinkVisible(false, EMPTY_STRING); + updateActionEnablement(null); + updateLayout(); + fDisconnectedTracingAction.setEnabled(false); + } catch (SWTException ex) { + } + } + + protected void updateUI(final ITraceStatusDMData2 traceData) { + fLastTraceData = traceData; + if (traceData == null ) { + // should not happen, but still process it correctly + updateUI(TracepointsMessages.TraceControlView_trace_status_inactive); + } else if (!traceData.isTracingSupported()) { + updateUI(TracepointsMessages.TraceControlView_trace_status_not_supported); + } else if (traceData.isTracingFromFile()) { + // Off-line tracing from data file + fDisconnectedTracingAction.setEnabled(false); + String s = TracepointsMessages.TraceControlView_trace_status_offline; + fStatusLabel.setText(s); + setActionLinkVisible(false, EMPTY_STRING); + + // If start and stop time are not available in trace data file, do not show secondary status line + if (getTimeMilliseconds(traceData.getStartTime()) != 0 && getTimeMilliseconds(traceData.getStopTime()) != 0) { + setSecondaryStatusLineVisible(true, traceData); + } else { + setSecondaryStatusLineVisible(false, traceData); + } + //setNotesLineVisible(true, traceData, true); + setBufferLineVisible(true, traceData, true); + setFrameLineVisible(true, traceData); + + updateActionEnablement(traceData); + updateLayout(); + + } else if (!traceData.isTracingActive() && traceData.getStopReason() == null){ + // Tracing is not started yet + fDisconnectedTracingAction.setEnabled(true); + fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_not_started); + setActionLinkVisible(true,TracepointsMessages.TraceControlView_action_start); + + setSecondaryStatusLineVisible(false, null); + //setNotesLineVisible(true, traceData, false); + setBufferLineVisible(true, traceData, false); + setFrameLineVisible(false, null); + + updateActionEnablement(traceData); + updateLayout(); + } else { - setDebugContext(null); + // Live execution tracing started and running or started and stopped + fDisconnectedTracingAction.setEnabled(true); + + // If stopped, stop reason, time and note. + STOP_REASON_ENUM fStopReason = traceData.getStopReason(); + if (fStopReason != null) { + // Tracing has stopped we need notes, secondary status line, and frames slider + setSecondaryStatusLineVisible(true, traceData); + //setNotesLineVisible(true, traceData, false); + + setFrameLineVisible(true, traceData); + setBufferLineVisible(true, traceData, false); + if (traceData.getCurrentTraceFrameId() != null) { + fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_visualization); + setActionLinkVisible(true, TracepointsMessages.TraceControlView_action_finish_visualization); + } else { + if (traceData.getNumberOfCollectedFrame() == 0) { + fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_not_started); + } else { + fStatusLabel.setText(TracepointsMessages.TraceControlView_trace_status_stopped); + } + setActionLinkVisible(true, TracepointsMessages.TraceControlView_action_restart); + } + } else { + // Tracing is running, don't show stop reason line, stop notes and frames line. + String s = TracepointsMessages.TraceControlView_trace_status_in_progress; + fStatusLabel.setText(s); + setActionLinkVisible(true, TracepointsMessages.TraceControlView_action_stop); + setSecondaryStatusLineVisible(true, traceData); + //setNotesLineVisible(true, traceData, false); + setFrameLineVisible(false, traceData); + setBufferLineVisible(true, traceData, true); + startRefreshUIJob(); + } + + updateActionEnablement(traceData); + updateLayout(); } } - - protected void setDebugContext(IDMVMContext vmContext) { - if (vmContext != null) { - IDMContext dmContext = vmContext.getDMContext(); - String sessionId = dmContext.getSessionId(); - fTargetContext = DMContexts.getAncestorOfType(dmContext, ITraceTargetDMContext.class); - if (!sessionId.equals(fDebugSessionId)) { - if (fDebugSessionId != null && getSession() != null) { - try { - final DsfSession session = getSession(); - session.getExecutor().execute(new DsfRunnable() { - @Override - public void run() { - session.removeServiceEventListener(TraceControlView.this); - } - }); - } catch (RejectedExecutionException e) { - // Session is shut down. + + protected void startRefreshUIJob() { + if (refreshUIJob == null) { + refreshUIJob = new UIJob("Refresh Trace Control view UI") { //$NON-NLS-1$ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + // Run on the UI thread to avoid synchronization + if (fAutoRefreshEnabled) { + fTraceControlModel.updateContent(); + } else { + // Update the UI to simply say how long ago was the last refresh + updateUI(fLastTraceData); } + + return Status.OK_STATUS; } - fDebugSessionId = sessionId; - if (fServicesTracker != null) { - fServicesTracker.dispose(); - } - fServicesTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), sessionId); - debugSessionChanged(); - } - } else if (fDebugSessionId != null) { - if (getSession() != null) { - try { - final DsfSession session = getSession(); - session.getExecutor().execute(new DsfRunnable() { - @Override - public void run() { - session.removeServiceEventListener(TraceControlView.this); - } - }); - } catch (RejectedExecutionException e) { - // Session is shut down. - } - } - fDebugSessionId = null; - fTargetContext = null; - if (fServicesTracker != null) { - fServicesTracker.dispose(); - fServicesTracker = null; - } - debugSessionChanged(); + }; } + refreshUIJob.schedule(UI_REFRESH_DELAY); } - - private void debugSessionChanged() { - // When dealing with a new debug session, assume tracing is not supported. - // updateContent() will fix it - fTracingSupported = false; - if (fDebugSessionId != null && getSession() != null) { - try { - final DsfSession session = getSession(); - session.getExecutor().execute(new DsfRunnable() { - @Override - public void run() { - session.addServiceEventListener(TraceControlView.this, null); - } - }); - } catch (RejectedExecutionException e) { - // Session is shut down. - } - } - - updateContent(); - } - - protected void updateActionEnablement() { - fOpenTraceVarDetails.setEnabled(fTracingSupported); - fActionRefreshView.setEnabled(fTracingSupported); - - // This hack is to avoid adding an API late in the release. - // For the next release, we should have a proper call to know if - // we can stop visualization or not - if (fStatusText != null && fStatusText.getText().toLowerCase().indexOf("off-line") != -1) { //$NON-NLS-1$ - fActionExitVisualization.setEnabled(false); + protected String getStopMessage(ITraceStatusDMData2 tData) { + String stopMessage; + STOP_REASON_ENUM fStopReason = tData.getStopReason(); + if (fStopReason == STOP_REASON_ENUM.REQUEST) { + stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_user_request; + } else if (fStopReason == STOP_REASON_ENUM.PASSCOUNT) { + if (tData.getStoppingTracepoint() != null) { + stopMessage = TracepointsMessages.bind(TracepointsMessages.TraceControlView_tracing_stopped_tracepoint_number, tData.getStoppingTracepoint()); + } else { + stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_passcount; + } + } else if (fStopReason == STOP_REASON_ENUM.OVERFLOW) { + stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_buffer_full; + } else if (fStopReason == STOP_REASON_ENUM.DISCONNECTION) { + stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_disconnection; + } else if (fStopReason == STOP_REASON_ENUM.ERROR) { + stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_error; } else { - fActionExitVisualization.setEnabled(fTraceVisualization); + stopMessage = TracepointsMessages.TraceControlView_tracing_stopped_unknown; } - } - - private void asyncExec(Runnable runnable) { - if (fStatusText != null) { - fStatusText.getDisplay().asyncExec(runnable); + + String user = EMPTY_STRING; + if (tData.getUserName() != null && tData.getUserName().length() > 0) { + user = TracepointsMessages.bind(TracepointsMessages.TraceControlView_trace_status_secondary_user, tData.getUserName()); } - } - - @Override - public void sessionEnded(DsfSession session) { - if (session.getId().equals(fDebugSessionId)) { - asyncExec(new Runnable() { - @Override - public void run() { - setDebugContext(null); - }}); + if (tData.isTracingFromFile()) { + stopMessage = TracepointsMessages.bind( + TracepointsMessages.TraceControlView_trace_status_secondary_offline, + new Object[] {formatTime(tData.getStartTime()), + user, + formatTime(tData.getStopTime()), + stopMessage + }); + } else { + stopMessage = TracepointsMessages.bind( + TracepointsMessages.TraceControlView_trace_status_secondary_stopped, + new Object[] {formatTimeInterval(tData.getStartTime(),tData.getStopTime()), + user, + formatTime(tData.getStopTime()), + stopMessage + }); } + + return stopMessage; } - /* - * When tracing starts, we know the status has changed - */ - @DsfServiceEventHandler - public void handleEvent(ITracingStartedDMEvent event) { - updateContent(); + protected void updateActionEnablement(ITraceStatusDMData2 traceData) { + fOpenTraceVarDetails.setEnabled(traceData != null && traceData.isTracingSupported()); + fExitVisualizationAction.setEnabled(traceData != null && traceData.getCurrentTraceFrameId() != null && + !traceData.isTracingFromFile()); + fDisconnectedTracingAction.setChecked(traceData != null && traceData.isDisconnectedTracingEnabled()); } - - /* - * When tracing stops, we know the status has changed - */ - @DsfServiceEventHandler - public void handleEvent(ITracingStoppedDMEvent event) { - updateContent(); - } - - @DsfServiceEventHandler - public void handleEvent(ITraceRecordSelectedChangedDMEvent event) { - if (event.isVisualizationModeEnabled()) { - fTraceVisualization = true; - } else { - fTraceVisualization = false; - } - updateContent(); - } - /* - * Since something suspended, might as well refresh our status - * to show the latest. - */ - @DsfServiceEventHandler - public void handleEvent(ISuspendedDMEvent event) { - updateContent(); - } - - /* - * Tracing support has changed, update view - */ - @DsfServiceEventHandler - public void handleEvent(ITracingSupportedChangeDMEvent event) { - updateContent(); - } - - + @Override public void setFocus() { - if (fStatusText != null) { - fStatusText.setFocus(); + if (fStatusLabel != null) { + fStatusLabel.setFocus(); } } - private DsfSession getSession() { - return DsfSession.getSession(fDebugSessionId); + public void updateLayout() { + fStatusComposite.layout(true); + fTopComposite.layout(true); } - private V getService(Class serviceClass) { - if (fServicesTracker != null) { - return fServicesTracker.getService(serviceClass); + protected long getTimeMilliseconds(String time) { + long microseconds = 0; + try { + if (time.length() != 0) { + String[] times = time.split("\\."); //$NON-NLS-1$ + microseconds += Long.parseLong(times[0]) * 1000000; + microseconds += Long.parseLong(times[1]); + } + } catch (NumberFormatException ex) { + GdbPlugin.log(ex); } - return null; + return microseconds / 1000; + } + + /** + * Format time from gdb presentation into user-understandable form + * @param time in gd presentation + * @return + */ + protected String formatTime(String time) { + long milliseconds = getTimeMilliseconds(time); + return formatTime(milliseconds); + } + + /** + * Format time from standard milliseconds since Epoch into user-understandable form + */ + protected String formatTime(long milliseconds) { + Date date = new Date(milliseconds); + long currentTime = System.currentTimeMillis(); + long days = TimeUnit.MILLISECONDS.toDays(currentTime - milliseconds); + if (days == 0) { + // today + return TracepointsMessages.bind(TracepointsMessages.TraceControlView_today, DateFormat.getTimeInstance(DateFormat.SHORT).format(date)); + } else if (days == 1) { + // yesterday + return TracepointsMessages.bind(TracepointsMessages.TraceControlView_yesterday, DateFormat.getTimeInstance(DateFormat.SHORT).format(date)); + } + + return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date); } /** - * Get the list of trace variables from the backend. - * - * @return null when the list cannot be obtained. + * Format time interval returned by trace status command into human-readable */ - public ITraceVariableDMData[] getTraceVarList() { - if (fDebugSessionId == null || getSession() == null) { - return null; - } - - final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); - if (ctx == null) { - return null; - } - - Query query = new Query() { - @Override - protected void execute(final DataRequestMonitor rm) { - final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); - - if (traceControl != null) { - traceControl.getTraceVariables(ctx, - new DataRequestMonitor(getSession().getExecutor(), rm) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - rm.setData(getData()); - } else { - rm.setData(null); - } - rm.done(); - }; - - }); - } else { - rm.setData(null); - rm.done(); - } + protected String formatTimeInterval(String startTime, String stopTime) { + long startMicroseconds = 0; + long stopMicroseconds = 0; + try { + if (startTime.length() != 0) { + String[] times = startTime.split("\\."); //$NON-NLS-1$ + startMicroseconds += Long.parseLong(times[0]) * 1000000; + startMicroseconds += Long.parseLong(times[1]); } - }; - try { - getSession().getExecutor().execute(query); - return query.get(1, TimeUnit.SECONDS); - } catch (InterruptedException exc) { - } catch (ExecutionException exc) { - } catch (TimeoutException e) { + if (stopTime.length() != 0) { + String[] times = stopTime.split("\\."); //$NON-NLS-1$ + stopMicroseconds += Long.parseLong(times[0]) * 1000000; + stopMicroseconds += Long.parseLong(times[1]); + } + return formatTimeInterval(startMicroseconds/1000, stopMicroseconds/1000, true); + } catch (NumberFormatException ex) { + GdbPlugin.log(ex); } + return EMPTY_STRING; + } + + /** + * Format time interval returned by trace status command into human-readable + */ + protected String formatTimeInterval(long startMilliseconds, long stopMilliseconds, boolean shortForm) { + long millis = stopMilliseconds - startMilliseconds; + long days = TimeUnit.MILLISECONDS.toDays(millis); + millis -= TimeUnit.DAYS.toMillis(days); + long hours = TimeUnit.MILLISECONDS.toHours(millis); + millis -= TimeUnit.HOURS.toMillis(hours); + long minutes = TimeUnit.MILLISECONDS.toMinutes(millis); + millis -= TimeUnit.MINUTES.toMillis(minutes); + long seconds = TimeUnit.MILLISECONDS.toSeconds(millis); + + StringBuilder sb = new StringBuilder(64); + if (!shortForm) { + if (days != 0) sb.append(days + TracepointsMessages.TraceControlView_date_days); + if (hours != 0) sb.append(hours + TracepointsMessages.TraceControlView_date_hours); + if (minutes != 0) sb.append(minutes + TracepointsMessages.TraceControlView_date_minutes); + if (seconds != 0) sb.append(seconds + TracepointsMessages.TraceControlView_date_seconds); + if (sb.length() == 0) sb.append(TracepointsMessages.TraceControlView_date_zero); + } else { + if (days != 0) sb.append(days + TracepointsMessages.TraceControlView_date_short_days); + if (hours != 0) sb.append(hours + TracepointsMessages.TraceControlView_date_short_hours); + if (minutes != 0) sb.append(minutes + TracepointsMessages.TraceControlView_date_short_minutes); + if (seconds != 0) sb.append(seconds + TracepointsMessages.TraceControlView_date_short_seconds); + if (sb.length() == 0) sb.append(TracepointsMessages.TraceControlView_date_short_zero); - return null; + } + return(sb.toString()); } - /** - * Create a new trace variable in the backend. - * - * @throws FailedTraceVariableCreationException when the creation fails. The exception - * will contain the error message to display to the user. + /** + * GDB's set trace-user and set trace-notes commands require quotes if argument contains spaces, + * but these quotes are returned by trace status, to workaround this we remove quotes on UI side */ - protected void createVariable(final String name, final String value) throws FailedTraceVariableCreationException { - if (fDebugSessionId == null || getSession() == null) { - throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); - } - - final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); - if (ctx == null) { - throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); - } - - Query query = new Query() { - @Override - protected void execute(final DataRequestMonitor rm) { - final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); - - if (traceControl != null) { - traceControl.createTraceVariable(ctx, name, value, - new RequestMonitor(getSession().getExecutor(), rm) { - @Override - protected void handleFailure() { - String message = TracepointsMessages.TraceControlView_create_variable_error; - Throwable t = getStatus().getException(); - if (t != null) { - message = t.getMessage(); - } - FailedTraceVariableCreationException e = - new FailedTraceVariableCreationException(message); - rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Backend error", e)); //$NON-NLS-1$ - rm.done(); - }; - }); - } else { - FailedTraceVariableCreationException e = - new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_trace_variable_tracing_unavailable); - rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Tracing unavailable", e)); //$NON-NLS-1$ - rm.done(); - } - } - }; - try { - getSession().getExecutor().execute(query); - query.get(); - } catch (InterruptedException e) { - // Session terminated - } catch (ExecutionException e) { - Throwable t = e.getCause(); - if (t instanceof CoreException) { - t = ((CoreException)t).getStatus().getException(); - if (t instanceof FailedTraceVariableCreationException) { - throw (FailedTraceVariableCreationException)t; - } - } - throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); + protected String removeQuotes(String s) { + if (s.startsWith("\"") && s.endsWith("\"")) { //$NON-NLS-1$//$NON-NLS-2$ + return s.substring(1, s.length()-1); + } else { + return s; } } } - diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java index e414bcafc99..fd28fc38cfe 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson. + * Copyright (c) 2010, 2013 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 @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - Initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - Trace control view enhancements (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; @@ -253,7 +254,7 @@ public final class TraceVarDetailsDialog extends Dialog { } protected void handleRefresh() { - ITraceVariableDMData[] vars = fView.getTraceVarList(); + ITraceVariableDMData[] vars = fView.fTraceControlModel.getTraceVarList(); if (vars == null) { setWarningVisible(TracepointsMessages.TraceControlView_refresh_variable_error); createButton.setEnabled(false); @@ -312,7 +313,7 @@ public final class TraceVarDetailsDialog extends Dialog { } try { - fView.createVariable(name, value); + fView.fTraceControlModel.createVariable(name, value); resetInputFields(); nameInput.setFocus(); handleRefresh(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java index 5f152b8c1fc..f035645bd4f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Wind River Systems and others. + * Copyright (c) 2010, 2013 Wind River Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - Trace control view enhancements (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; @@ -33,12 +34,16 @@ public class TracepointImageRegistry extends AbstractImageRegistry { private static final String ORG_ECLIPSE_UI_PLUGIN_ID = "org.eclipse.ui"; //$NON-NLS-1$ private static final String ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID = "org.eclipse.cdt.dsf.gdb.ui"; //$NON-NLS-1$ - public static final String ICON_Refresh_enabled = add(ORG_ECLIPSE_UI_PLUGIN_ID, new String[] {"full/elcl16"}, "refresh_nav.gif"); //$NON-NLS-1$ //$NON-NLS-2$ - public static final String ICON_Refresh_disabled = add(ORG_ECLIPSE_UI_PLUGIN_ID, new String[] {"full/dlcl16"}, "refresh_nav.gif"); //$NON-NLS-1$ //$NON-NLS-2$ - public static final String ICON_Trace_Variables = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "tracevariables.gif"); //$NON-NLS-1$ //$NON-NLS-2$ - public static final String ICON_Exit_Visualization = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "stop_visual_trace.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Refresh_enabled = add(ORG_ECLIPSE_UI_PLUGIN_ID, new String[] {"full/elcl16"}, "refresh_nav.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Refresh_disabled = add(ORG_ECLIPSE_UI_PLUGIN_ID, new String[] {"full/dlcl16"}, "refresh_nav.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Refresh_Auto = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "refresh_auto.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Disconnected_Tracing = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "disconnected_tracing.png"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Circular_Buffer = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "circular_buffer.png"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Trace_Variables = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "tracevariables.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Exit_Visualization = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "stop_visual_trace.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Edit_enabled = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "write_obj.gif"); //$NON-NLS-1$ //$NON-NLS-2$ - private static TracepointImageRegistry INSTANCE= new TracepointImageRegistry(GdbUIPlugin.getDefault()); + private static TracepointImageRegistry INSTANCE = new TracepointImageRegistry(GdbUIPlugin.getDefault()); TracepointImageRegistry(Plugin plugin) { super(plugin); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java index 8c8a677a83d..971d5c09a54 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Wind River Systems and others. + * Copyright (c) 2010, 2013 Wind River Systems 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 @@ -7,6 +7,7 @@ * * Contributors: * Wind River Systems - initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - trace control view enhancements (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; @@ -20,11 +21,23 @@ public final class TracepointsMessages extends NLS { private TracepointsMessages() { // Do not instantiate } - + public static String TraceControlView_buffer_label; + public static String TraceControlView_buffer_circular_button_label; + public static String TraceControlView_buffer_circular_on_tooltip; + public static String TraceControlView_buffer_circular_off_tooltip; + public static String TraceControlView_buffer_frames_collected; + public static String TraceControlView_trace_status_offline; + public static String TraceControlView_tracing_stopped_user_request; + public static String TraceControlView_tracing_stopped_passcount; + public static String TraceControlView_tracing_stopped_tracepoint_number; + public static String TraceControlView_tracing_stopped_buffer_full; + public static String TraceControlView_tracing_stopped_disconnection; + public static String TraceControlView_tracing_stopped_error; + public static String TraceControlView_tracing_stopped_unknown; public static String TraceControlView_action_Refresh_label; - public static String TraceControlView_trace_view_content_updated_label; + public static String TraceControlView_auto_refresh_action_label; public static String TraceControlView_action_trace_variable_details; - public static String TraceControlView_trace_variable_invalid_value; + public static String TraceControlView_action_Disconnected_tracing_label; public static String TraceControlView_trace_variable_tracing_unavailable; public static String TraceControlView_trace_variable_details_dialog_title; public static String TraceControlView_trace_variable_details_column_name; @@ -38,6 +51,44 @@ public final class TracepointsMessages extends NLS { public static String TraceControlView_create_variable_empty_name_error; public static String TraceControlView_action_exit_visualization_mode; public static String TraceControlView_refresh_variable_error; + public static String TraceControlView_trace_status_not_supported; + public static String TraceControlView_trace_status_inactive; + public static String TraceControlView_trace_status_no_debug_session; + public static String TraceControlView_trace_status_not_started; + public static String TraceControlView_trace_status_in_progress; + public static String TraceControlView_trace_status_visualization; + public static String TraceControlView_trace_status_stopped; + public static String TraceControlView_frame_label; + public static String TraceControlView_frame_looking; + public static String TraceControlView_frame_dragging; + public static String TraceControlView_frame_not_looking; + public static String TraceControlView_trace_notes_edit_tooltip; + public static String TraceControlView_trace_notes_save_tooltip; + public static String TraceControlView_trace_notes_not_set; + public static String TraceControlView_trace_notes_label; + public static String TraceControlView_trace_status_secondary_stopped; + public static String TraceControlView_trace_status_secondary_running; + public static String TraceControlView_trace_status_secondary_user; + public static String TraceControlView_trace_status_secondary_refresh_time; + public static String TraceControlView_trace_status_secondary_offline; + public static String TraceControlView_action_start; + public static String TraceControlView_action_stop; + public static String TraceControlView_action_restart; + public static String TraceControlView_action_finish_visualization; + public static String TraceControlView_today; + public static String TraceControlView_yesterday; + public static String TraceControlView_date_days; + public static String TraceControlView_date_hours; + public static String TraceControlView_date_minutes; + public static String TraceControlView_date_seconds; + public static String TraceControlView_date_zero; + public static String TraceControlView_date_short_days; + public static String TraceControlView_date_short_hours; + public static String TraceControlView_date_short_minutes; + public static String TraceControlView_date_short_seconds; + public static String TraceControlView_date_short_zero; + // Not used + public static String TraceControlView_tracing_stopped_at; static { NLS.initializeMessages(TracepointsMessages.class.getName(), TracepointsMessages.class); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties index ec89dcf8205..f52983a817e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties @@ -1,5 +1,5 @@ ########################################################################## -# Copyright (c) 2010 Ericsson and others. +# Copyright (c) 2010, 2013 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 @@ -7,12 +7,13 @@ # # Contributors: # Ericsson - initial API and implementation +# Dmitry Kozlov (Mentor Graphics) - trace control view enhancements (Bug 390827) ########################################################################## TraceControlView_action_Refresh_label=Refresh -TraceControlView_trace_view_content_updated_label=Last updated at: +TraceControlView_auto_refresh_action_label=Refresh view automatically +TraceControlView_action_Disconnected_tracing_label=Continue tracing after GDB has disconnected TraceControlView_action_trace_variable_details=Manage Trace Variables -TraceControlView_trace_variable_invalid_value=Initial value must be an integer TraceControlView_trace_variable_tracing_unavailable=Tracing unavailable TraceControlView_trace_variable_details_dialog_title=Trace Variable Details TraceControlView_trace_variable_details_column_name=Name @@ -26,3 +27,68 @@ TraceControlView_create_variable_error=Error creating trace variable TraceControlView_create_variable_empty_name_error=Cannot create variable with empty name TraceControlView_action_exit_visualization_mode=Exit Visualization Mode TraceControlView_refresh_variable_error=Unable to retrieve trace variables + +TraceControlView_trace_status_not_supported=Tracing is not supported +TraceControlView_trace_status_inactive=Tracing is not active +TraceControlView_trace_status_offline=Examining trace data from a file +TraceControlView_trace_status_not_started=Tracing not started +TraceControlView_trace_status_in_progress=Tracing is running +TraceControlView_trace_status_visualization=Examining trace +TraceControlView_trace_status_stopped=Trace data available +TraceControlView_trace_status_no_debug_session=Debug session is not selected or started + +TraceControlView_trace_status_secondary_stopped={0}trace{1}, stopped {2} on {3} +# {1} is the user name if set provided by binding TraceControlView_trace_status_secondary_user +# {2} is the last refresh time if auto-refresh is not enabled, provided by binding TraceControlView_trace_status_secondary_refresh_time +TraceControlView_trace_status_secondary_running=started {0}{1}{2} +# {1} is the user name if set provided by binding TraceControlView_trace_status_secondary_user +TraceControlView_trace_status_secondary_offline=Tracing was started {0}{1}, stopped {2} on {3} +TraceControlView_trace_status_secondary_user=\ by {0} +# Note: TraceControlView.updateUIRefreshStatusOnly relies on the exact content of this field, +# mind when change it +TraceControlView_trace_status_secondary_refresh_time=, last refreshed {0}ago + +TraceControlView_action_start=Start +TraceControlView_action_stop=Stop +TraceControlView_action_finish_visualization=End +TraceControlView_action_restart=Restart + +TraceControlView_date_days=\ days\ +TraceControlView_date_hours=\ hours\ +TraceControlView_date_minutes=\ minutes\ +TraceControlView_date_seconds=\ seconds\ +TraceControlView_date_zero=0 seconds\ + +TraceControlView_date_short_days=d\ +TraceControlView_date_short_hours=h\ +TraceControlView_date_short_minutes=m\ +TraceControlView_date_short_seconds=s\ +TraceControlView_date_short_zero=0s\ + +TraceControlView_tracing_stopped_at={0}, +TraceControlView_tracing_stopped_user_request=user request +TraceControlView_tracing_stopped_passcount=passcount +TraceControlView_tracing_stopped_tracepoint_number=passcount of tracepoint {0} +TraceControlView_tracing_stopped_buffer_full=buffer full +TraceControlView_tracing_stopped_disconnection=disconnection +TraceControlView_tracing_stopped_error=error +TraceControlView_tracing_stopped_unknown=unknown reason + +TraceControlView_buffer_label=Buffer +TraceControlView_buffer_circular_button_label=Circular +TraceControlView_buffer_circular_on_tooltip= Circular buffer is on +TraceControlView_buffer_circular_off_tooltip= Circular buffer is off +TraceControlView_buffer_frames_collected={0} frames, {1}Kb + +TraceControlView_trace_notes_label=Notes +TraceControlView_trace_notes_not_set=No trace notes set +TraceControlView_trace_notes_edit_tooltip=Edit notes +TraceControlView_trace_notes_save_tooltip=Save notes + +TraceControlView_frame_label=Current selected trace frame: +TraceControlView_frame_not_looking =n/a +TraceControlView_frame_looking={0}, tracepoint {1} +TraceControlView_frame_dragging={0} + +TraceControlView_today={0} today +TraceControlView_yesterday={0} yesterday diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF index 8fdfb027636..12a87469953 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true -Bundle-Version: 4.3.0.qualifier +Bundle-Version: 4.4.0.qualifier Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.GdbPlugin Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime, diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/pom.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb/pom.xml index 4a6afa869af..8bd0a815b64 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/pom.xml +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/pom.xml @@ -11,7 +11,7 @@ ../../pom.xml - 4.3.0-SNAPSHOT + 4.4.0-SNAPSHOT org.eclipse.cdt.dsf.gdb eclipse-plugin diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_2.java index a9b419a5396..22674cd6a8e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_2.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 Ericsson and others. + * Copyright (c) 2010, 2013 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: - * Ericsson - initial API and implementation + * Ericsson - Initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - Add support for IGDBTraceControl2 (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; @@ -14,6 +15,7 @@ import java.util.Hashtable; import java.util.concurrent.TimeUnit; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; @@ -55,7 +57,7 @@ import org.osgi.framework.BundleContext; * * @since 3.0 */ -public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTraceControl, ICachingService { +public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTraceControl2, ICachingService { @Immutable protected static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext { @@ -213,136 +215,143 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace } } - private class TraceStatusDMData implements ITraceStatusDMData { - private int fFreeBufferSize; - private int fTotalBufferSize; - private int fNumberOfCollectedFrames; - private boolean fTracingActive; - private boolean fTracingSupported; - private STOP_REASON_ENUM fStopReason; - private Integer fStoppingTracepoint; - - /** - * Create a status when tracing is supported - */ - public TraceStatusDMData(boolean active, int free, int total, int frames, - STOP_REASON_ENUM reason, Integer tracepoint) { - fFreeBufferSize = free; - fTotalBufferSize = total; - fNumberOfCollectedFrames = frames; - fTracingActive = active; - fTracingSupported = true; - fStopReason = reason; - fStoppingTracepoint = tracepoint; - } - - /** - * Status without a Stop reason - */ - public TraceStatusDMData(boolean active, int free, int total, int frames) { - this(active, free, total, frames, null, null); + private class TraceStatusDMData implements ITraceStatusDMData2 { + private MITraceStatusInfo fInfo; + + public TraceStatusDMData(MITraceStatusInfo info) { + fInfo = info; } /** * Create a status when tracing is not supported */ public TraceStatusDMData() { - this(false, 0, 0, 0); - fTracingSupported = false; + this(null); } @Override public int getFreeBufferSize() { - return fFreeBufferSize; + if (fInfo == null) return 0; + return fInfo.getFreeBufferSize(); } + @Override + public int getNumberOfCreatedFrames() { + if (fInfo == null) return 0; + return fInfo.getNumberOfCreatedFrames(); + } + @Override public int getNumberOfCollectedFrame() { - return fNumberOfCollectedFrames; + if (fInfo == null) return 0; + return fInfo.getNumberOfCollectedFrame(); } @Override public int getTotalBufferSize() { - return fTotalBufferSize; + if (fInfo == null) return 0; + return fInfo.getTotalBufferSize(); } @Override public boolean isTracingActive() { - return fTracingActive; + if (fInfo == null) return false; + return fInfo.isTracingActive(); } @Override public boolean isTracingSupported() { - return fTracingSupported; + return fInfo != null; + } + + @Override + public boolean isCircularBuffer() { + if (fInfo == null) return false; + return fInfo.isCircularBuffer(); + } + + @Override + public boolean isTracingFromFile() { + if (fInfo == null) return false; + return fInfo.isTracingFromFile(); + } + + @Override + public boolean isDisconnectedTracingEnabled() { + if (fInfo == null) return false; + return fInfo.isDisconnectedTracingEnabled(); } @Override public STOP_REASON_ENUM getStopReason() { - return fStopReason; + if (fInfo == null) return null; + return fInfo.getStopReason(); } @Override public Integer getStoppingTracepoint() { - if (fStopReason == null) { + if (fInfo.getStopReason() == null) { return null; } - return fStoppingTracepoint; + return fInfo.getStopTracepoint(); } - @SuppressWarnings("nls") @Override - public String toString() { - String str = "\n"; - - if (!fTracingSupported) { - return "\nTracing is not supported\n"; + public String getUserName() { + if (fInfo == null) return ""; //$NON-NLS-1$ + return fInfo.getUserName() == null ? "" : fInfo.getUserName(); //$NON-NLS-1$ + } + + @Override + public String getNotes() { + if (fInfo == null) return ""; //$NON-NLS-1$ + return fInfo.getNotes() == null ? "" : fInfo.getNotes(); //$NON-NLS-1$ + } + + @Override + public String getStartTime() { + if (fInfo == null) return ""; //$NON-NLS-1$ + return fInfo.getStartTime() == null ? "" : fInfo.getStartTime(); //$NON-NLS-1$ + } + + @Override + public String getStopTime() { + if (fInfo == null) return ""; //$NON-NLS-1$ + return fInfo.getStopTime() == null ? "" : fInfo.getStopTime(); //$NON-NLS-1$ + } + + @Override + public String getStopErrorDescription() { + if (getStopReason() != STOP_REASON_ENUM.ERROR) { + return null; } - - if (fBackend.getSessionType() == SessionType.CORE) { - str += "Off-line trace visualization\n"; - } else { - str += "Tracing with live execution\n"; - } - + return fInfo.getStopErrorDescription(); + } + + @Override + public String getTraceFile() { + if (!isTracingFromFile()) { + return null; + } + return fInfo.getTraceFile(); + } + + @Override + public String getCurrentTraceFrameId() { + // Not currently provided by -trace-status if (fCurrentRecordDmc instanceof MITraceRecordDMContext) { - str += "Looking at trace frame " + - ((MITraceRecordDMContext)fCurrentRecordDmc).getRecordId() + - ", tracepoint " + fTracepointIndexForTraceRecord + "\n\n"; - } else { - str += "Not currently looking at any trace frame\n\n"; + return ((MITraceRecordDMContext)fCurrentRecordDmc).getRecordId(); } - - str += "Tracing is currently" + (!fTracingActive ? " not":"") + " active\n"; - str += "Buffer contains " + fNumberOfCollectedFrames + " trace frame" + - (fNumberOfCollectedFrames>1?"s":"") + "\n";//" (out of ? created in total)\n"; - str += "Currently using " + (fTotalBufferSize - fFreeBufferSize) + - " bytes out of " + fTotalBufferSize + "\n"; - - if (fStopReason != null) { - assert !fTracingActive; - str += "Tracing stopped because of"; - if (fStopReason == STOP_REASON_ENUM.REQUEST) { - str += " user request"; - } else if (fStopReason == STOP_REASON_ENUM.PASSCOUNT) { - str += " passcount"; - if (fStoppingTracepoint != null) { - str += " of tracepoint number " + fStoppingTracepoint; - } - } else if (fStopReason == STOP_REASON_ENUM.OVERFLOW) { - str += " buffer full"; - } else if (fStopReason == STOP_REASON_ENUM.DISCONNECTION) { - str += " disconnection"; - } else if (fStopReason == STOP_REASON_ENUM.ERROR) { - str += " error"; - } else { - str += " unknow reason"; - } - str += "\n"; + return null; + } + + @Override + public Integer getTracepointNumberForCurrentTraceFrame() { + // Not currently provided by -trace-status + if (getCurrentTraceFrameId() != null) { + return fTracepointIndexForTraceRecord; } - - - - return str; + return null; } } @@ -433,7 +442,8 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace */ private void doInitialize(RequestMonitor requestMonitor) { // Register this service. - register(new String[] {IGDBTraceControl.class.getName()}, + register(new String[] {IGDBTraceControl.class.getName(), + IGDBTraceControl2.class.getName()}, new Hashtable()); @@ -468,6 +478,16 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace return GdbPlugin.getBundleContext(); } + /** @since 4.4 */ + protected boolean isTracingCurrentlySupported() { + return fIsTracingCurrentlySupported; + } + + /** @since 4.4 */ + protected CommandCache getTraceStatusCache() { + return fTraceStatusCache; + } + @Override public void canStartTracing(ITraceTargetDMContext context, final DataRequestMonitor rm) { if (context == null) { @@ -521,6 +541,8 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace new DataRequestMonitor(getExecutor(), rm) { @Override protected void handleSuccess() { + fTraceStatusCache.reset(context); + fIsTracingActive = true; getSession().dispatchEvent(new TracingStartedEvent(context), getProperties()); rm.done(); @@ -594,7 +616,9 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace new DataRequestMonitor(getExecutor(), rm) { @Override protected void handleSuccess() { - MITraceStopInfo info = getData(); + fTraceStatusCache.reset(context); + + MITraceStopInfo info = getData(); // Update the tracing state in case it was stopped by the backend if (fIsTracingActive != info.isTracingActive()) { @@ -721,6 +745,8 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace new DataRequestMonitor(getExecutor(), rm) { @Override protected void handleSuccess() { + fTraceStatusCache.reset(context); + fIsTracingCurrentlySupported = true; // Workaround for GDB pre-release where we don't get the details // of the frame when we load a trace file. @@ -760,10 +786,6 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace // because -trace-status can change very fast as it reports // the number of frames collected. Having a small interval of // stale data is currently not a big deal, and not user-visible. - // We just have to be careful in the future that command enablement - // should not be affected by this cache. For example, if a command - // checks if it should be enabled by using this call, and misses - // the latest state due to the cache. // Bug 353034 getExecutor().schedule(new Runnable() { @Override public void run() { fTraceStatusCache.reset(context); } @@ -800,20 +822,7 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace fTraceRecordsStored = info.getNumberOfCollectedFrame(); - STOP_REASON_ENUM stopReason = info.getStopReason(); - if (stopReason == null) { - rm.setData(new TraceStatusDMData(info.isTracingActive(), - info.getFreeBufferSize(), - info.getTotalBufferSize(), - info.getNumberOfCollectedFrame())); - } else { - rm.setData(new TraceStatusDMData(info.isTracingActive(), - info.getFreeBufferSize(), - info.getTotalBufferSize(), - info.getNumberOfCollectedFrame(), - stopReason, - info.getStopTracepoint())); - } + rm.setData(new TraceStatusDMData(info)); } else { fTraceRecordsStored = 0; fIsTracingActive = false; @@ -962,9 +971,9 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace final int reference = Integer.parseInt(recordId); if (reference < 0) { - // This is how we indicate that we want to exit visualization mode - // We should have a specific call in the IGDBTraceControl interface to do this. - stopVisualizingTraceData(targetDmc, rm); + // This was the old way to indicate that we want to exit visualization mode. + // We continue supporting it for backward compatibility + stopTraceVisualization(targetDmc, rm); return; } @@ -1062,7 +1071,9 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace } } - private void stopVisualizingTraceData(final ITraceTargetDMContext context, final RequestMonitor rm) { + /** @since 4.4 */ + @Override + public void stopTraceVisualization(final ITraceTargetDMContext context, final RequestMonitor rm) { if (fIsTracingCurrentlySupported == false) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$ rm.done(); @@ -1086,7 +1097,6 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace ITraceRecordDMContext invalidDmc = new InvalidTraceRecordDMContext(getSession(), context); getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(invalidDmc), getProperties()); - rm.done(); return; } @@ -1134,6 +1144,68 @@ public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTrace } } + /** @since 4.4 */ + @Override + public void setCircularTraceBuffer(final ITraceTargetDMContext context, boolean useCircularBuffer, final RequestMonitor rm) { + if (context == null) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + return; + } + + if (fIsTracingCurrentlySupported == false) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$ + return; + } + + fConnection.queueCommand( + fCommandFactory.createMIGDBSetCircularTraceBuffer(context, useCircularBuffer), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + fTraceStatusCache.reset(context); + rm.done(); + } + }); + } + + /** @since 4.4 */ + @Override + public void setDisconnectedTracing(final ITraceTargetDMContext context, boolean disconnectedTracing,final RequestMonitor rm) { + if (context == null) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + return; + } + + if (fIsTracingCurrentlySupported == false) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$ + return; + } + + fConnection.queueCommand( + fCommandFactory.createMIGDBSetDisconnectedTracing(context, disconnectedTracing), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + fTraceStatusCache.reset(context); + rm.done(); + } + }); + } + + /** @since 4.4 */ + @Override + public void setTraceUser(ITraceTargetDMContext context, String userName, RequestMonitor rm) { + // Only supported started with GDB 7.4 + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, Messages.ErrorNotSupported, null)); + } + + /** @since 4.4 */ + @Override + public void setTraceNotes(ITraceTargetDMContext context, String note, RequestMonitor rm) { + // Only supported started with GDB 7.4 + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, Messages.ErrorNotSupported, null)); + } + @Override public void flushCache(IDMContext context) { fTraceStatusCache.reset(context); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_4.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_4.java new file mode 100644 index 00000000000..7558f303164 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_4.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2013 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.gdb.service; + +import java.util.Hashtable; + +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.IMICommandControl; +import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * This class adds extra support for Trace Control for GDB 7.4 + * + * @since 4.4 + */ +public class GDBTraceControl_7_4 extends GDBTraceControl_7_2 { + + private ICommandControlService fConnection; + private CommandFactory fCommandFactory; + + public GDBTraceControl_7_4(DsfSession session, ILaunchConfiguration config) { + super(session, config); + } + + @Override + public void initialize(final RequestMonitor requestMonitor) { + super.initialize(new ImmediateRequestMonitor(requestMonitor) { + @Override + protected void handleSuccess() { + doInitialize(requestMonitor); + } + }); + } + + private void doInitialize(RequestMonitor requestMonitor) { + // Register this service. + register(new String[] {IGDBTraceControl.class.getName(), + IGDBTraceControl2.class.getName(), + GDBTraceControl_7_2.class.getName(), + GDBTraceControl_7_4.class.getName()}, + new Hashtable()); + + + fConnection = getServicesTracker().getService(ICommandControlService.class); + fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + + requestMonitor.done(); + } + + @Override + public void shutdown(RequestMonitor requestMonitor) { + unregister(); + super.shutdown(requestMonitor); + } + + @Override + public void setTraceUser(final ITraceTargetDMContext context, String userName, final RequestMonitor rm) { + if (context == null) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + return; + } + + if (isTracingCurrentlySupported() == false) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$ + return; + } + + fConnection.queueCommand( + fCommandFactory.createMIGDBSetTraceUser(context, userName), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + getTraceStatusCache().reset(context); + rm.done(); + } + }); + } + + @Override + public void setTraceNotes(final ITraceTargetDMContext context, String note, final RequestMonitor rm) { + if (context == null) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + return; + } + + if (isTracingCurrentlySupported() == false) { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$ + return; + } + + getTraceStatusCache().reset(context); + + fConnection.queueCommand( + fCommandFactory.createMIGDBSetTraceNotes(context, note), + new ImmediateDataRequestMonitor(rm) { + @Override + protected void handleSuccess() { + getTraceStatusCache().reset(context); + rm.done(); + } + }); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java index 738be0af9b7..99bc1e73f66 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java @@ -13,6 +13,7 @@ * Marc Khouzam (Ericsson) - Include IGDBHardware service for the multicore visualizer (Bug 335027) * Vladimir Prus (Mentor Graphics) - Support for OS resources. * Marc Khouzam (Ericsson) - Support for GDB 7.6 memory service + * Marc Khouzam (Ericsson) - Support for GDB 7.4 trace control service *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; @@ -238,6 +239,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { /** @since 3.0 */ protected IGDBTraceControl createTraceControlService(DsfSession session, ILaunchConfiguration config) { + if (GDB_7_4_VERSION.compareTo(fVersion) <= 0) { + return new GDBTraceControl_7_4(session, config); + } // This service is available for GDB 7.2 but there is a pre-release of GDB that // supports the same features and has version of 6.8.50.20090414 if (GDB_7_2_VERSION.compareTo(fVersion) <= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java index e012f646399..db16e886305 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 Ericsson and others. + * Copyright (c) 2010, 2013 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 @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - Initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - Enhance trace status (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; @@ -19,10 +20,6 @@ import org.eclipse.cdt.dsf.datamodel.IDMEvent; import org.eclipse.cdt.dsf.service.IDsfService; /** - * EXPERIMENTAL. 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. - * * The TraceControl service provides access to the debugger Tracing functionality. * It is used to do such things as start and stop tracing. * @@ -133,7 +130,6 @@ public interface IGDBTraceControl extends IDsfService { String file, RequestMonitor rm); - /** * Request that the backend use the specified trace record. */ @@ -161,11 +157,80 @@ public interface IGDBTraceControl extends IDsfService { /** * Returns the id of the tracepoint that caused the stop. - * Should be null if getStopReason is null + * Should be null if getStopReason() is null */ Integer getStoppingTracepoint(); - } - + } + + /** @since 4.4 */ + public interface ITraceStatusDMData2 extends ITraceStatusDMData { + /** + * Returns the user-name of the user that started or stopped a trace. Returns an + * empty string if no user-name is available. + */ + String getUserName(); + /** + * Returns the traces notes related to a started or stopped trace. Returns an + * empty string if no notes are defined. + */ + String getNotes(); + /** + * Returns the start-time of an on-going trace. + * Returns an empty string if no start-time is available or if no trace was started. + */ + String getStartTime(); + /** + * Returns the stop-time of the last trace experiment. + * Returns an empty string if no stop-time is available, if a trace is currently + * running or if no trace was ever started. + */ + String getStopTime(); + /** + * Returns true if trace visualization is done from a trace file + * as compared to one from an ongoing execution. + */ + boolean isTracingFromFile(); + /** + * Returns true if an ongoing tracing experiment will continue after + * GDB disconnects from the target. + */ + boolean isDisconnectedTracingEnabled(); + /** + * Returns true if the buffer being used or to be used to record + * the trace data is a circular buffer (overwriting/flight-recorder), or not. + */ + boolean isCircularBuffer(); + /** + * Returns the number of created frames of the current trace experiment. + */ + int getNumberOfCreatedFrames(); + /** + * Returns the error description if the trace was stopped due to an error (getStopReason() returns ERROR). + * Returns null if the trace is not stopped, or if it is not stopped by an ERROR. + * Can return an empty string in other cases if no description is available. + */ + String getStopErrorDescription(); + /** + * Returns the trace file path when isTracingFromFile() is true. Can return + * an empty string if the file path is not available. + * Should return null if isTracingFromFile() is false; + */ + String getTraceFile(); + + /** + * If a trace frame is currently being examined, this method will return + * its id. Returns null if no trace frame is in focus. + */ + String getCurrentTraceFrameId(); + + /** + * If a trace frame is currently being examined, this method will return + * the GDB tracepoint number that triggered the trace record in focus. + * Returns null if no trace frame is in focus (if getCurrentTraceFrameId() == null). + */ + Integer getTracepointNumberForCurrentTraceFrame(); + } + public interface ITraceVariableDMData extends IDMData { String getName(); String getValue(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl2.java new file mode 100644 index 00000000000..6e4dc9a51fa --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl2.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - initial API and implementation (Bug 390827) + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.service; + +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; + +/** + * Enhancements to the trace control functionality, which allow to enable new settings. + * @since 4.4 + */ +public interface IGDBTraceControl2 extends IGDBTraceControl { + + /** + * Stops the visualization of trace data. + */ + public void stopTraceVisualization(ITraceTargetDMContext context, RequestMonitor rm); + + /** + * Enables/disables the user of a circular trace buffer to collect trace data. + */ + public void setCircularTraceBuffer(ITraceTargetDMContext context, boolean useCircularBuffer, RequestMonitor rm); + + /** + * Enables/disables disconnected tracing. When this flag is enabled, an ongoing tracing experiment will + * continue even if GDB disconnects from the target. + */ + public void setDisconnectedTracing(ITraceTargetDMContext context, boolean disconnectedTracing, RequestMonitor rm); + + /** + * Sets the name of the user that is performing tracing operations. + * This name will be persisted during a disconnected tracing experiment. + */ + public void setTraceUser(ITraceTargetDMContext context, String userName, RequestMonitor rm); + + /** + * Sets some information about the tracing experiment. + * This information will be persisted during a disconnected tracing experiment. + */ + public void setTraceNotes(ITraceTargetDMContext context, String notes, RequestMonitor rm); +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java index bc3be5a1abd..13f6e681016 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Ericsson and others. + * Copyright (c) 2012, 2013 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 @@ -24,6 +24,7 @@ class Messages extends NLS { public static String NoMatches; public static String UniqueMatch; public static String UniqueMatches; + public static String ErrorNotSupported; static { // initialize resource bundle diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties index 8f5360c82ad..8a6245c7a19 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/Messages.properties @@ -16,3 +16,4 @@ GroupPattern=Group-pattern NoMatches=No matches UniqueMatch={0} unique match UniqueMatches={0} unique matches +ErrorNotSupported=Operation not supported with this GDB version diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java index b5852cea9dc..872dbc3f82e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java @@ -22,6 +22,7 @@ * John Dallaway - Support for -data-write-memory-bytes (Bug 387793) * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug (323552) * Philippe Gil (AdaCore) - Add show/set language CLI commands (Bug 421541) + * Dmitry Kozlov (Mentor Graphics) - New trace-related methods (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.mi.service.command; @@ -110,7 +111,9 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetArgs; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetAutoSolib; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetBreakpointPending; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetCharset; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetCircularTraceBuffer; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetDetachOnFork; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetDisconnectedTracing; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetEnv; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetHostCharset; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetLanguage; @@ -125,6 +128,8 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSolibSearchPath; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetTargetAsync; 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.MIGDBSetTraceNotes; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetTraceUser; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBShowExitCode; import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBShowLanguage; import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet; @@ -684,10 +689,20 @@ public class CommandFactory { return new MIGDBSetCharset(ctx, charset); } + /** @since 4.4 */ + public ICommand createMIGDBSetCircularTraceBuffer(ITraceTargetDMContext ctx, boolean useCircularBuffer) { + return new MIGDBSetCircularTraceBuffer(ctx, useCircularBuffer); + } + /** @since 4.0 */ public ICommand createMIGDBSetDetachOnFork(ICommandControlDMContext ctx, boolean detach) { return new MIGDBSetDetachOnFork(ctx, detach); - } + } + + /** @since 4.4 */ + public ICommand createMIGDBSetDisconnectedTracing(ITraceTargetDMContext ctx, boolean disconnectedTracing) { + return new MIGDBSetDisconnectedTracing(ctx, disconnectedTracing); + } public ICommand createMIGDBSetEnv(ICommandControlDMContext dmc, String name) { return new MIGDBSetEnv(dmc, name); @@ -757,6 +772,16 @@ public class CommandFactory { return new MIGDBSetTargetAsync(ctx, isSet); } + /** @since 4.4 */ + public ICommand createMIGDBSetTraceNotes(ITraceTargetDMContext ctx, String notes) { + return new MIGDBSetTraceNotes(ctx, notes); + } + + /** @since 4.4*/ + public ICommand createMIGDBSetTraceUser(ITraceTargetDMContext ctx, String userName) { + return new MIGDBSetTraceUser(ctx, userName); + } + public ICommand createMIGDBShowExitCode(ICommandControlDMContext ctx) { return new MIGDBShowExitCode(ctx); } @@ -1045,4 +1070,4 @@ public class CommandFactory { public ICommand createMIVarUpdate(ICommandControlDMContext dmc, String name) { return new MIVarUpdate(dmc, name); } -} \ No newline at end of file +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetCircularTraceBuffer.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetCircularTraceBuffer.java new file mode 100644 index 00000000000..31450f5aecc --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetCircularTraceBuffer.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - Initial API and implementation +*******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; + +/** + * -gdb-set circular-trace-buffer on | off + * + * Sets circular trace buffer on or off. + * @since 4.4 + */ +public class MIGDBSetCircularTraceBuffer extends MIGDBSet { + public MIGDBSetCircularTraceBuffer(ITraceTargetDMContext ctx, boolean useCircularTraceBuffer) { + super(ctx, new String[] {"circular-trace-buffer", useCircularTraceBuffer ? "on": "off"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetDisconnectedTracing.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetDisconnectedTracing.java new file mode 100644 index 00000000000..02b59485008 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetDisconnectedTracing.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - Initial API and implementation +*******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; + +/** + * -gdb-set disconnected-tracing on | off + * + * Sets disconnected-tracing on or off. + * @since 4.4 + */ +public class MIGDBSetDisconnectedTracing extends MIGDBSet { + public MIGDBSetDisconnectedTracing(ITraceTargetDMContext ctx, boolean disconnectedTracing) { + super(ctx, new String[] {"disconnected-tracing", disconnectedTracing ? "on": "off"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceNotes.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceNotes.java new file mode 100644 index 00000000000..c291df967ff --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceNotes.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - Initial API and implementation +*******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; + +/** + * -gdb-set trace-notes "note" + * + * Sets trace notes + * @since 4.4 + */ +public class MIGDBSetTraceNotes extends MIGDBSet { + public MIGDBSetTraceNotes(ITraceTargetDMContext ctx, String notes) { + super(ctx, new String[] {"trace-notes", notes}); //$NON-NLS-1$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceUser.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceUser.java new file mode 100644 index 00000000000..b57533bf106 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIGDBSetTraceUser.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Dmitry Kozlov (Mentor Graphics) - Initial API and implementation +*******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; + +/** + * -gdb-set trace-user "user" + * + * Sets trace user + * @since 4.4 + */ +public class MIGDBSetTraceUser extends MIGDBSet { + public MIGDBSetTraceUser(ITraceTargetDMContext ctx, String userName) { + super(ctx, new String[] {"trace-user", userName}); //$NON-NLS-1$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java index c41e61de0a0..54a8cff748e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Ericsson and others. + * Copyright (c) 2010, 2013 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 @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - Initial API and implementation + * Dmitry Kozlov (Mentor Graphics) - Enhance trace status (Bug 390827) *******************************************************************************/ package org.eclipse.cdt.dsf.mi.service.command.output; @@ -19,6 +20,27 @@ import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.STOP_REASON_ENUM; * ^done,supported="1",running="0",stop-reason="request",frames="0",buffer-size="5242880",buffer-free="5242880" * ^done,supported="1",running="0",stop-reason="passcount",stopping-tracepoint="7",frames="3",buffer-size="5242880",buffer-free="5242862" * + * Field presence: + * With GDB 7.2: + * "supported" + * "running" + * "stop-reason" + * "stopping-tracepoint" + * "error-description" + * "frames" + * "frames-created" + * "buffer-size" + * "buffer-free" + * "disconnected" + * "circular" + * Added in GDB 7.4: + * "user-name" + * "notes" + * "start-time" + * "stop-time" + * Added in GDB 7.6: + * "trace-file" + * * @since 3.0 */ public class MITraceStatusInfo extends MIInfo { @@ -26,10 +48,20 @@ public class MITraceStatusInfo extends MIInfo { private int fFreeBufferSize = 0; private int fTotalBufferSize = 0; private int fNumberOfCollectedFrames = 0; + private int fNumberOfCreatedFrames = 0; private boolean fIsTracingActive = false; private boolean fIsTracingSupported = false; private STOP_REASON_ENUM fStopReason = null; + private String fStopErrorDesc = ""; //$NON-NLS-1$ private Integer fStoppingTracepoint = null; + private boolean fIsTracingFromFile = false; + private String fTraceFile = ""; //$NON-NLS-1$ + private boolean fIsDisconnectedTracingEnabled = false; + private String fUserName = ""; //$NON-NLS-1$ + private String fNotes = ""; //$NON-NLS-1$ + private String fStartTime = ""; //$NON-NLS-1$ + private String fStopTime = ""; //$NON-NLS-1$ + private boolean fIsCircularBuffer = false; public MITraceStatusInfo(MIOutput out) { super(out); @@ -44,6 +76,11 @@ public class MITraceStatusInfo extends MIInfo { return fNumberOfCollectedFrames; } + /** @since 4.4 */ + public int getNumberOfCreatedFrames() { + return fNumberOfCreatedFrames; + } + public int getTotalBufferSize() { return fTotalBufferSize; } @@ -55,15 +92,60 @@ public class MITraceStatusInfo extends MIInfo { public boolean isTracingSupported() { return fIsTracingSupported; } - + + /** @since 4.4 */ + public boolean isTracingFromFile() { + return fIsTracingFromFile; + } + + /** @since 4.4 */ + public boolean isDisconnectedTracingEnabled() { + return fIsDisconnectedTracingEnabled; + } + public STOP_REASON_ENUM getStopReason() { return fStopReason; } + /** @since 4.4 */ + public String getStopErrorDescription() { + return fStopErrorDesc; + } + public Integer getStopTracepoint() { return fStoppingTracepoint; } + /** @since 4.4 */ + public String getUserName() { + return fUserName; + } + + /** @since 4.4 */ + public String getNotes() { + return fNotes; + } + + /** @since 4.4 */ + public String getStartTime() { + return fStartTime; + } + + /** @since 4.4 */ + public String getStopTime() { + return fStopTime; + } + + /** @since 4.4 */ + public String getTraceFile() { + return isTracingFromFile() ? fTraceFile : null; + } + + /** @since 4.4 */ + public boolean isCircularBuffer() { + return fIsCircularBuffer; + } + private void parse() { if (isDone()) { MIOutput out = getMIOutput(); @@ -75,33 +157,18 @@ public class MITraceStatusInfo extends MIInfo { if (var.equals("supported")) { //$NON-NLS-1$ MIValue val = results[i].getMIValue(); if (val instanceof MIConst) { - fIsTracingSupported = ((MIConst)val).getString().equals("0") ? false : true;; //$NON-NLS-1$ + fIsTracingSupported = ((MIConst)val).getString().equals("0") ? false : true; //$NON-NLS-1$ + fIsTracingFromFile = ((MIConst)val).getString().equals("file"); //$NON-NLS-1$ + } + } else if (var.equals("trace-file")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fTraceFile = ((MIConst)val).getString().trim(); } } else if (var.equals("running")) { //$NON-NLS-1$ MIValue val = results[i].getMIValue(); if (val instanceof MIConst) { - fIsTracingActive = ((MIConst)val).getString().equals("0") ? false : true;; //$NON-NLS-1$ - } - } else if (var.equals("frames")) { //$NON-NLS-1$ - MIValue val = results[i].getMIValue(); - if (val instanceof MIConst) { - try { - fNumberOfCollectedFrames = Integer.parseInt(((MIConst)val).getString()); - } catch (NumberFormatException e) {} - } - } else if (var.equals("buffer-size")) { //$NON-NLS-1$ - MIValue val = results[i].getMIValue(); - if (val instanceof MIConst) { - try { - fTotalBufferSize = Integer.parseInt(((MIConst)val).getString()); - } catch (NumberFormatException e) {} - } - } else if (var.equals("buffer-free")) { //$NON-NLS-1$ - MIValue val = results[i].getMIValue(); - if (val instanceof MIConst) { - try { - fFreeBufferSize = Integer.parseInt(((MIConst)val).getString()); - } catch (NumberFormatException e) {} + fIsTracingActive = ((MIConst)val).getString().equals("0") ? false : true; //$NON-NLS-1$ } } else if (var.equals("stop-reason")) { //$NON-NLS-1$ MIValue val = results[i].getMIValue(); @@ -125,10 +192,73 @@ public class MITraceStatusInfo extends MIInfo { MIValue val = results[i].getMIValue(); if (val instanceof MIConst) { try { - fStoppingTracepoint = Integer.parseInt(((MIConst)val).getString()); + fStoppingTracepoint = Integer.parseInt(((MIConst)val).getString().trim()); } catch (NumberFormatException e) {} } - } + } else if (var.equals("error-description")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fStopErrorDesc = ((MIConst)val).getString().trim(); + } + } else if (var.equals("frames")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fNumberOfCollectedFrames = Integer.parseInt(((MIConst)val).getString().trim()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("frames-created")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fNumberOfCreatedFrames = Integer.parseInt(((MIConst)val).getString().trim()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("buffer-size")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fTotalBufferSize = Integer.parseInt(((MIConst)val).getString().trim()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("buffer-free")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fFreeBufferSize = Integer.parseInt(((MIConst)val).getString().trim()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("disconnected")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fIsDisconnectedTracingEnabled = ((MIConst)val).getString().equals("0") ? false : true; //$NON-NLS-1$ + } + } else if (var.equals("circular")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fIsCircularBuffer = ((MIConst)val).getString().trim().equals("0") ? false : true; //$NON-NLS-1$ + } + } else if (var.equals("user-name")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fUserName = ((MIConst)val).getString().trim(); + } + } else if (var.equals("notes")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fNotes = ((MIConst)val).getString(); + } + } else if (var.equals("start-time")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fStartTime = ((MIConst)val).getString().trim(); + } + } else if (var.equals("stop-time")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fStopTime = ((MIConst)val).getString().trim(); + } + } } } }