Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 209983 Details for
Bug 331467
[LTTng] Add a latency analysis compoment
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
New version of latency analysis
0001-Added-latency-analysis-feature-bug-331467.patch (text/plain), 348.86 KB, created by
Bernd Hufmann
on 2012-01-24 11:38:43 EST
(
hide
)
Description:
New version of latency analysis
Filename:
MIME Type:
Creator:
Bernd Hufmann
Created:
2012-01-24 11:38:43 EST
Size:
348.86 KB
patch
obsolete
>From dde498ceb9a886ab369329a4ce816552a8078f4d Mon Sep 17 00:00:00 2001 >From: Bernd Hufmann <bhufmann@gmail.com> >Date: Tue, 24 Jan 2012 11:27:45 -0500 >Subject: [PATCH] Added latency analysis feature (bug 331467) > >--- > .../META-INF/MANIFEST.MF | 5 +- > .../lttng/core/latency/analyzer/EventMatcher.java | 505 ++++++++++++++ > .../lttng/core/latency/analyzer/StackWrapper.java | 152 ++++ > .../linuxtools/lttng/core/util/EventsPair.java | 29 + > .../eclipse/linuxtools/lttng/core/util/Pair.java | 121 ++++ > .../linuxtools/lttng/ui/tests/AllLTTngUITests.java | 1 + > .../lttng/ui/tests/distribution/AllTests.java | 27 + > .../tests/distribution/LatencyGraphModelTest.java | 582 ++++++++++++++++ > .../ui/tests/histogram/HistogramDataModelTest.java | 256 ++++++- > .../META-INF/MANIFEST.MF | 5 + > .../icons/elcl16/add_button.gif | Bin 0 -> 308 bytes > .../icons/elcl16/decreasebar_button.gif | Bin 0 -> 211 bytes > .../icons/elcl16/delete_button.gif | Bin 0 -> 337 bytes > .../icons/elcl16/increasebar_button.gif | Bin 0 -> 208 bytes > .../icons/elcl16/warning.gif | Bin 0 -> 999 bytes > .../icons/eview16/graph.gif | Bin 0 -> 197 bytes > .../plugin.properties | 1 + > lttng/org.eclipse.linuxtools.lttng.ui/plugin.xml | 9 + > .../distribution/model/BaseDistributionData.java | 142 ++++ > .../views/distribution/model/DistributionData.java | 179 +++++ > .../distribution/model/HorDistributionData.java | 70 ++ > .../distribution/model/IBaseDistributionModel.java | 25 + > .../distribution/model/VerDistributionData.java | 69 ++ > .../ui/views/histogram/FullTraceHistogram.java | 7 +- > .../lttng/ui/views/histogram/Histogram.java | 54 +- > .../ui/views/histogram/HistogramDataModel.java | 184 ++++- > .../lttng/ui/views/histogram/HistogramRequest.java | 14 +- > .../ui/views/histogram/HistogramScaledData.java | 34 +- > .../lttng/ui/views/histogram/HistogramView.java | 9 +- > .../ui/views/histogram/IHistogramDataModel.java | 38 + > .../views/histogram/IHistogramModelListener.java | 23 + > .../ui/views/histogram/TimeRangeHistogram.java | 3 +- > .../lttng/ui/views/latency/AbstractViewer.java | 255 +++++++ > .../lttng/ui/views/latency/GraphViewer.java | 158 +++++ > .../lttng/ui/views/latency/HistogramViewer.java | 157 +++++ > .../lttng/ui/views/latency/LatencyView.java | 477 +++++++++++++ > .../lttng/ui/views/latency/Messages.java | 85 +++ > .../ui/views/latency/dialogs/AbstractDialog.java | 240 +++++++ > .../lttng/ui/views/latency/dialogs/AddDialog.java | 488 +++++++++++++ > .../ui/views/latency/dialogs/DeleteDialog.java | 155 ++++ > .../lttng/ui/views/latency/dialogs/ListDialog.java | 252 +++++++ > .../latency/listeners/AbstractMouseListener.java | 80 +++ > .../listeners/AbstractMouseTrackListener.java | 77 ++ > .../latency/listeners/AbstractPaintListener.java | 735 ++++++++++++++++++++ > .../latency/listeners/GraphMouseListener.java | 70 ++ > .../latency/listeners/GraphPaintListener.java | 227 ++++++ > .../latency/listeners/HistogramPaintListener.java | 355 ++++++++++ > .../latency/listeners/TimePointerListener.java | 69 ++ > .../views/latency/listeners/TooltipListener.java | 100 +++ > .../ui/views/latency/listeners/ZoomListener.java | 134 ++++ > .../lttng/ui/views/latency/messages.properties | 59 ++ > .../lttng/ui/views/latency/model/Config.java | 76 ++ > .../ui/views/latency/model/GraphScaledData.java | 246 +++++++ > .../ui/views/latency/model/IGraphDataModel.java | 41 ++ > .../views/latency/model/IGraphModelListener.java | 31 + > .../ui/views/latency/model/LatencyController.java | 189 +++++ > .../views/latency/model/LatencyEventRequest.java | 91 +++ > .../ui/views/latency/model/LatencyGraphModel.java | 380 ++++++++++ > 58 files changed, 7668 insertions(+), 103 deletions(-) > create mode 100644 lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/EventMatcher.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/StackWrapper.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/EventsPair.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/Pair.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/AllTests.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/LatencyGraphModelTest.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/add_button.gif > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/decreasebar_button.gif > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/delete_button.gif > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/increasebar_button.gif > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/warning.gif > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/icons/eview16/graph.gif > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/BaseDistributionData.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/DistributionData.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/HorDistributionData.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/IBaseDistributionModel.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/VerDistributionData.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramDataModel.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramModelListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/AbstractViewer.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/GraphViewer.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/HistogramViewer.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/LatencyView.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/Messages.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AbstractDialog.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AddDialog.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/DeleteDialog.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/ListDialog.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseTrackListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractPaintListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphMouseListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphPaintListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/HistogramPaintListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TimePointerListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TooltipListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/ZoomListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/messages.properties > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/Config.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/GraphScaledData.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphDataModel.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphModelListener.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyController.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyEventRequest.java > create mode 100644 lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyGraphModel.java > >diff --git a/lttng/org.eclipse.linuxtools.lttng.core/META-INF/MANIFEST.MF b/lttng/org.eclipse.linuxtools.lttng.core/META-INF/MANIFEST.MF >index a8275a0..1ac8175 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.core/META-INF/MANIFEST.MF >+++ b/lttng/org.eclipse.linuxtools.lttng.core/META-INF/MANIFEST.MF >@@ -17,6 +17,7 @@ Export-Package: org.eclipse.linuxtools.lttng.core, > org.eclipse.linuxtools.lttng.core.control, > org.eclipse.linuxtools.lttng.core.event, > org.eclipse.linuxtools.lttng.core.exceptions, >+ org.eclipse.linuxtools.lttng.core.latency.analyzer, > org.eclipse.linuxtools.lttng.core.model, > org.eclipse.linuxtools.lttng.core.request, > org.eclipse.linuxtools.lttng.core.signal, >@@ -28,7 +29,9 @@ Export-Package: org.eclipse.linuxtools.lttng.core, > org.eclipse.linuxtools.lttng.core.state.resource, > org.eclipse.linuxtools.lttng.core.state.trace, > org.eclipse.linuxtools.lttng.core.trace, >+ org.eclipse.linuxtools.lttng.core.tracecontrol, > org.eclipse.linuxtools.lttng.core.tracecontrol.model, > org.eclipse.linuxtools.lttng.core.tracecontrol.model.config, >- org.eclipse.linuxtools.lttng.core.tracecontrol.service >+ org.eclipse.linuxtools.lttng.core.tracecontrol.service, >+ org.eclipse.linuxtools.lttng.core.util > Bundle-Localization: plugin >diff --git a/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/EventMatcher.java b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/EventMatcher.java >new file mode 100644 >index 0000000..721efad >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/EventMatcher.java >@@ -0,0 +1,505 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.core.latency.analyzer; >+ >+import java.util.Collection; >+import java.util.Collections; >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.Map.Entry; >+import java.util.Set; >+import java.util.Stack; >+import java.util.Vector; >+ >+import org.eclipse.linuxtools.lttng.core.event.LttngEvent; >+import org.eclipse.linuxtools.lttng.core.util.EventsPair; >+ >+/** >+ * <b><u>EventMatcher</u></b> >+ * <p> >+ * Event matching class. Saves events in a list and returns the previously saved event if the currently processed one is >+ * its response, so that the latency can be computed by subtracting their respective timestamps. >+ * >+ * @author Philippe Sawicki >+ */ >+public class EventMatcher { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Class instance (Singleton pattern). >+ */ >+ private static EventMatcher fInstance = null; >+ >+ /** >+ * Stack abstraction, used to save the events in a list. >+ */ >+ private StackWrapper fStack; >+ >+ /** >+ * Match table, associates a request class to a response class. >+ */ >+ private HashMap<String, String> fMatch; >+ /** >+ * Inverse match table, associates a response class to a request class. >+ */ >+ private HashMap<String, String> fInverseMatch; >+ >+ /** >+ * The number of events processed. >+ */ >+ private int fProcessedEvents; >+ /** >+ * The number of events matched. >+ */ >+ private int fMatchedEvents; >+ >+ /** >+ * Event types identification Strings. >+ */ >+ @SuppressWarnings("nls") >+ public static String >+ ADD_TO_PAGE_CACHE = "add_to_page_cache", >+ BIO_BACKMERGE = "bio_backmerge", >+ BIO_FRONTMERGE = "bio_frontmerge", >+ BIO_QUEUE = "bio_queue", >+ BUFFER_WAIT_END = "buffer_wait_end", >+ BUFFER_WAIT_START = "buffer_wait_start", >+ CALL = "call", >+ CLOSE = "close", >+ CORE_MARKER_FORMAT = "core_marker_format", >+ CORE_MARKER_ID = "core_marker_id", >+ DEV_RECEIVE = "dev_receive", >+ DEV_XMIT = "dev_xmit", >+ END_COMMIT = "end_commit", >+ EXEC = "exec", >+ FILE_DESCRIPTOR = "file_descriptor", >+ GETRQ = "getrq", >+ GETRQ_BIO = "getrq_bio", >+ IDT_TABLE = "idt_table", >+ INTERRUPT = "interrupt", >+ IOCTL = "ioctl", >+ IRQ_ENTRY = "irq_entry", >+ IRQ_EXIT = "irq_exit", >+ LIST_MODULE = "list_module", >+ LLSEEK = "llseek", >+ LSEEK = "lseek", >+ NAPI_COMPLETE = "napi_complete", >+ NAPI_POLL = "napi_poll", >+ NAPI_SCHEDULE = "napi_schedule", >+ NETWORK_IPV4_INTERFACE = "network_ipv4_interface", >+ NETWORK_IP_INTERFACE = "network_ip_interface", >+ OPEN = "open", >+ PAGE_FAULT_ENTRY = "page_fault_entry", >+ PAGE_FAULT_EXIT = "page_fault_exit", >+ PAGE_FAULT_GET_USER_ENTRY = "page_fault_get_user_entry", >+ PAGE_FAULT_GET_USER_EXIT = "page_fault_get_user_exit", >+ PAGE_FREE = "page_free", >+ PLUG = "plug", >+ POLLFD = "pollfd", >+ PREAD64 = "pread64", >+ PRINTF = "printf", >+ PRINTK = "printk", >+ PROCESS_EXIT = "process_exit", >+ PROCESS_FORK = "process_fork", >+ PROCESS_FREE = "process_free", >+ PROCESS_STATE = "process_state", >+ PROCESS_WAIT = "process_wait", >+ READ = "read", >+ REMAP = "remap", >+ REMOVE_FROM_PAGE_CACHE = "remove_from_page_cache", >+ RQ_COMPLETE_FS = "rq_complete_fs", >+ RQ_COMPLETE_PC = "rq_complete_pc", >+ RQ_INSERT_FS = "rq_insert_fs", >+ RQ_INSERT_PC = "rq_insert_pc", >+ RQ_ISSUE_FS = "rq_issue_fs", >+ RQ_ISSUE_PC = "rq_issue_pc", >+ RQ_REQUEUE_PC = "rq_requeue_pc", >+ SCHED_MIGRATE_TASK = "sched_migrate_task", >+ SCHED_SCHEDULE = "sched_schedule", >+ SCHED_TRY_WAKEUP = "sched_try_wakeup", >+ SCHED_WAKEUP_NEW_TASK = "sched_wakeup_new_task", >+ SELECT = "select", >+ SEM_CREATE = "sem_create", >+ SEND_SIGNAL = "send_signal", >+ SHM_CREATE = "shm_create", >+ SLEEPRQ_BIO = "sleeprq_bio", >+ SOCKET_ACCEPT = "socket_accept", >+ SOCKET_BIND = "socket_bind", >+ SOCKET_CALL = "socket_call", >+ SOCKET_CONNECT = "socket_connect", >+ SOCKET_CREATE = "socket_create", >+ SOCKET_GETPEERNAME = "socket_getpeername", >+ SOCKET_GETSOCKNAME = "socket_getsockname", >+ SOCKET_GETSOCKOPT = "socket_getsockopt", >+ SOCKET_LISTEN = "socket_listen", >+ SOCKET_SETSOCKOPT = "socket_setsockopt", >+ SOCKET_SHUTDOWN = "socket_shutdown", >+ SOCKET_SOCKETPAIR = "socket_socketpair", >+ SOFTIRQ_ENTRY = "softirq_entry", >+ SOFTIRQ_EXIT = "softirq_exit", >+ SOFTIRQ_RAISE = "softirq_raise", >+ SOFTIRQ_VEC = "softirq_vec", >+ START_COMMIT = "start_commit", >+ STATEDUMP_END = "statedump_end", >+ SYS_CALL_TABLE = "sys_call_table", >+ SYSCALL_ENTRY = "syscall_entry", >+ SYSCALL_EXIT = "syscall_exit", >+ TASKLET_LOW_ENTRY = "tasklet_low_entry", >+ TASKLET_LOW_EXIT = "tasklet_low_exit", >+ TCPV4_RCV = "tcpv4_rcv", >+ TIMER_ITIMER_EXPIRED = "timer_itimer_expired", >+ TIMER_ITIMER_SET = "timer_itimer_set", >+ TIMER_SET = "timer_set", >+ TIMER_TIMEOUT = "timer_timeout", >+ TIMER_UPDATE_TIME = "timer_update_time", >+ UDPV4_RCV = "udpv4_rcv", >+ UNPLUG_IO = "unplug_io", >+ UNPLUG_TIMER = "unplug_timer", >+ VM_MAP = "vm_map", >+ VPRINTK = "vprintk", >+ WAIT_ON_PAGE_END = "wait_on_page_end", >+ WAIT_ON_PAGE_START = "wait_on_page_start", >+ WRITE = "write", >+ WRITEV = "writev"; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Private constructor to defeat instantiation (Singleton pattern). >+ */ >+ private EventMatcher() { >+ fStack = new StackWrapper(); >+ fMatch = new HashMap<String, String>(); >+ fInverseMatch = new HashMap<String, String>(); >+ >+ fProcessedEvents = 0; >+ fMatchedEvents = 0; >+ >+ createMatchTable(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Returns an instance to the EventMatcher class (Singleton pattern). >+ * @return An instance to the EventMatcher class (Singleton pattern). >+ */ >+ public static EventMatcher getInstance() { >+ if (fInstance == null) >+ fInstance = new EventMatcher(); >+ return fInstance; >+ } >+ >+ /** >+ * Returns the number of events processed. >+ * @return The number of events processed. >+ */ >+ public int getNBProcessedEvents() { >+ return fProcessedEvents; >+ } >+ >+ /** >+ * Returns the number of events matched. >+ * @return The number of events matched. >+ */ >+ public int getNBMatchedEvents() { >+ return fMatchedEvents; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Releases the instance to the EventMatcher class. >+ */ >+ public static void releaseInstance() { >+ fInstance = null; >+ } >+ >+ /** >+ * Creates the event matching table, linking a response class to a request class. >+ */ >+ private void createMatchTable() { >+ // Build the default matches >+ fMatch.put(PAGE_FAULT_GET_USER_EXIT, PAGE_FAULT_GET_USER_ENTRY); >+ fMatch.put(TASKLET_LOW_EXIT, TASKLET_LOW_ENTRY); >+ fMatch.put(PAGE_FAULT_EXIT, PAGE_FAULT_ENTRY); >+ fMatch.put(SYSCALL_EXIT, SYSCALL_ENTRY); >+ fMatch.put(IRQ_EXIT, IRQ_ENTRY); >+ fMatch.put(WRITE, READ); >+ fMatch.put(CLOSE, OPEN); >+ fMatch.put(BUFFER_WAIT_END, BUFFER_WAIT_START); >+ fMatch.put(END_COMMIT, START_COMMIT); >+ fMatch.put(WAIT_ON_PAGE_END, WAIT_ON_PAGE_START); >+ >+ // Build the inverse matches based on the matches >+ Set<Entry<String, String>> pairs = fMatch.entrySet(); >+ Iterator<Entry<String, String>> it = pairs.iterator(); >+ while (it.hasNext()) { >+ Entry<String, String> pair = it.next(); >+ fInverseMatch.put(pair.getValue(), pair.getKey()); >+ } >+ } >+ >+ /** >+ * Processes an event received: if it is identified as a response, try to get its request to remove it from the >+ * list. If no request was saved, dismiss the current response. If it is a request, save it to the list of requests >+ * waiting for a response. >+ * @param event >+ * The event to identify, and maybe process if it is a response. >+ * @return The request event associated with the current event (a response), or null if nothing was found (no >+ * request associated with this response, or the event to identify was a request that was added to the >+ * list). >+ */ >+ public LttngEvent process(LttngEvent event) { >+ fProcessedEvents++; >+ >+ String markerName = event.getMarkerName(); >+ if (fMatch.containsKey(markerName)) { >+ String startEventType = fMatch.get(markerName); >+ Stack<LttngEvent> events = fStack.getStackOf(startEventType); >+ >+ if (events != null) { >+ for (int i = events.size() - 1; i >= 0; i--) { >+ LttngEvent request = events.get(i); >+ >+ if (request.getCpuId() == event.getCpuId() && event.getTimestamp().getValue() > request.getTimestamp().getValue()) { >+ fStack.removeEvent(startEventType, request); >+ fMatchedEvents++; >+ return request; >+ } >+ } >+ } >+ return null; >+ } else { >+ // Add only if there can later be a match for this request >+ if (fMatch.containsValue(event.getMarkerName())) { >+ fStack.put(event.clone()); >+ } >+ return null; >+ } >+ } >+ >+ /** >+ * Clears the stack content. >+ */ >+ public void clearStack() { >+ fStack.clear(); >+ >+ // Reset the processed and matched events counter >+ fProcessedEvents = 0; >+ fMatchedEvents = 0; >+ } >+ >+ /** >+ * Resets all. >+ */ >+ public void resetMatches() { >+ fMatch.clear(); >+ fInverseMatch.clear(); >+ >+ fStack.clear(); >+ >+ // Reset the processed and matched events counter >+ fProcessedEvents = 0; >+ fMatchedEvents = 0; >+ } >+ >+ /** >+ * Returns the list of start events. >+ * @return The list of start events. >+ */ >+ public Collection<String> getStartEvents() { >+ return fMatch.values(); >+ } >+ >+ /** >+ * Returns the list of end events. >+ * @return The list of end events. >+ */ >+ public Set<String> getEndEvents() { >+ return fMatch.keySet(); >+ } >+ >+ /** >+ * Returns the alphabetically-sorted list of start/end events pairs. >+ * @return The alphabetically-sorted list of start/end events pairs. >+ */ >+ public EventsPair getEvents() { >+ Vector<String> start = new Vector<String>(getStartEvents()); >+ Vector<String> end = new Vector<String>(fMatch.size()); >+ >+ Collections.sort(start); >+ for (int i = 0; i < start.size(); i++) { >+ end.add(fInverseMatch.get(start.get(i))); >+ } >+ return new EventsPair(start, end); >+ } >+ >+ /** >+ * Adds a match to the list of events pairs. >+ * @param startType >+ * The start event type. >+ * @param endType >+ * The end event type. >+ */ >+ public void addMatch(String startType, String endType) { >+ fMatch.put(endType, startType); >+ fInverseMatch.put(startType, endType); >+ } >+ >+ /** >+ * Removes a matched pair based on the their type. >+ * >+ * <b>Note :</b> For now, only the pair's end type is used, since a type can only be either one start or one end. >+ * This function takes both types to account for the future, if a pairing process ever becomes more complex. >+ * >+ * @param startType >+ * The type of the pair's start type. >+ * @param endType >+ * The type of the pair's end type. >+ */ >+ public void removeMatch(String startType, String endType) { >+ fMatch.remove(endType); >+ fInverseMatch.remove(startType); >+ } >+ >+ /** >+ * Returns the list of all event possible types. >+ * @return The list of all event possible types. >+ */ >+ public Vector<String> getTypeList() { >+ // Reserve some space for the 103 default event types. >+ Vector<String> eventsList = new Vector<String>(103); >+ >+ eventsList.add(ADD_TO_PAGE_CACHE); >+ eventsList.add(BIO_BACKMERGE); >+ eventsList.add(BIO_FRONTMERGE); >+ eventsList.add(BIO_QUEUE); >+ eventsList.add(BUFFER_WAIT_END); >+ eventsList.add(BUFFER_WAIT_START); >+ eventsList.add(CALL); >+ eventsList.add(CLOSE); >+ eventsList.add(CORE_MARKER_FORMAT); >+ eventsList.add(CORE_MARKER_ID); >+ eventsList.add(DEV_RECEIVE); >+ eventsList.add(DEV_XMIT); >+ eventsList.add(END_COMMIT); >+ eventsList.add(EXEC); >+ eventsList.add(FILE_DESCRIPTOR); >+ eventsList.add(GETRQ); >+ eventsList.add(GETRQ_BIO); >+ eventsList.add(IDT_TABLE); >+ eventsList.add(INTERRUPT); >+ eventsList.add(IOCTL); >+ eventsList.add(IRQ_ENTRY); >+ eventsList.add(IRQ_EXIT); >+ eventsList.add(LIST_MODULE); >+ eventsList.add(LLSEEK); >+ eventsList.add(LSEEK); >+ eventsList.add(NAPI_COMPLETE); >+ eventsList.add(NAPI_POLL); >+ eventsList.add(NAPI_SCHEDULE); >+ eventsList.add(NETWORK_IPV4_INTERFACE); >+ eventsList.add(NETWORK_IP_INTERFACE); >+ eventsList.add(OPEN); >+ eventsList.add(PAGE_FAULT_ENTRY); >+ eventsList.add(PAGE_FAULT_EXIT); >+ eventsList.add(PAGE_FAULT_GET_USER_ENTRY); >+ eventsList.add(PAGE_FAULT_GET_USER_EXIT); >+ eventsList.add(PAGE_FREE); >+ eventsList.add(PLUG); >+ eventsList.add(POLLFD); >+ eventsList.add(PREAD64); >+ eventsList.add(PRINTF); >+ eventsList.add(PRINTK); >+ eventsList.add(PROCESS_EXIT); >+ eventsList.add(PROCESS_FORK); >+ eventsList.add(PROCESS_FREE); >+ eventsList.add(PROCESS_STATE); >+ eventsList.add(PROCESS_WAIT); >+ eventsList.add(READ); >+ eventsList.add(REMAP); >+ eventsList.add(REMOVE_FROM_PAGE_CACHE); >+ eventsList.add(RQ_COMPLETE_FS); >+ eventsList.add(RQ_COMPLETE_PC); >+ eventsList.add(RQ_INSERT_FS); >+ eventsList.add(RQ_INSERT_PC); >+ eventsList.add(RQ_ISSUE_FS); >+ eventsList.add(RQ_ISSUE_PC); >+ eventsList.add(RQ_REQUEUE_PC); >+ eventsList.add(SCHED_MIGRATE_TASK); >+ eventsList.add(SCHED_SCHEDULE); >+ eventsList.add(SCHED_TRY_WAKEUP); >+ eventsList.add(SCHED_WAKEUP_NEW_TASK); >+ eventsList.add(SELECT); >+ eventsList.add(SEM_CREATE); >+ eventsList.add(SEND_SIGNAL); >+ eventsList.add(SHM_CREATE); >+ eventsList.add(SLEEPRQ_BIO); >+ eventsList.add(SOCKET_ACCEPT); >+ eventsList.add(SOCKET_BIND); >+ eventsList.add(SOCKET_CALL); >+ eventsList.add(SOCKET_CONNECT); >+ eventsList.add(SOCKET_CREATE); >+ eventsList.add(SOCKET_GETPEERNAME); >+ eventsList.add(SOCKET_GETSOCKNAME); >+ eventsList.add(SOCKET_GETSOCKOPT); >+ eventsList.add(SOCKET_LISTEN); >+ eventsList.add(SOCKET_SETSOCKOPT); >+ eventsList.add(SOCKET_SHUTDOWN); >+ eventsList.add(SOCKET_SOCKETPAIR); >+ eventsList.add(SOFTIRQ_ENTRY); >+ eventsList.add(SOFTIRQ_EXIT); >+ eventsList.add(SOFTIRQ_RAISE); >+ eventsList.add(SOFTIRQ_VEC); >+ eventsList.add(START_COMMIT); >+ eventsList.add(STATEDUMP_END); >+ eventsList.add(SYS_CALL_TABLE); >+ eventsList.add(SYSCALL_ENTRY); >+ eventsList.add(SYSCALL_EXIT); >+ eventsList.add(TASKLET_LOW_ENTRY); >+ eventsList.add(TASKLET_LOW_EXIT); >+ eventsList.add(TCPV4_RCV); >+ eventsList.add(TIMER_ITIMER_EXPIRED); >+ eventsList.add(TIMER_ITIMER_SET); >+ eventsList.add(TIMER_SET); >+ eventsList.add(TIMER_TIMEOUT); >+ eventsList.add(TIMER_UPDATE_TIME); >+ eventsList.add(UDPV4_RCV); >+ eventsList.add(UNPLUG_IO); >+ eventsList.add(UNPLUG_TIMER); >+ eventsList.add(VM_MAP); >+ eventsList.add(VPRINTK); >+ eventsList.add(WAIT_ON_PAGE_END); >+ eventsList.add(WAIT_ON_PAGE_START); >+ eventsList.add(WRITE); >+ eventsList.add(WRITEV); >+ >+ return eventsList; >+ } >+ >+ /** >+ * Prints the stack content to the console. >+ */ >+ public void print() { >+ fStack.printContent(); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/StackWrapper.java b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/StackWrapper.java >new file mode 100644 >index 0000000..e64ccb2 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/StackWrapper.java >@@ -0,0 +1,152 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.core.latency.analyzer; >+ >+import java.util.Collection; >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.Set; >+import java.util.Stack; >+ >+import org.eclipse.linuxtools.lttng.core.event.LttngEvent; >+ >+/** >+ * <b><u>StackWrapper</u></b> >+ * <p> >+ * Stack pile. >+ * >+ * TODO Change the types of the HashMaps from <String,String> to <Integer,Integer>, in order to take advantage of the >+ * compilation-time String.hashCode() speedup over execution-time String hash computation. >+ * >+ * @author Philippe Sawicki >+ */ >+public class StackWrapper { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Hash map of event stacks. >+ */ >+ private HashMap<String, Stack<LttngEvent>> fStacks = null; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ */ >+ public StackWrapper() { >+ fStacks = new HashMap<String, Stack<LttngEvent>>(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Adds an event to the list of events of the same type. >+ * @param event >+ * The event to add to the list. >+ */ >+ public void put(LttngEvent event) { >+ String key = event.getMarkerName(); >+ >+ if (fStacks.containsKey(key)) { >+ fStacks.get(key).add(event); >+ } else { >+ Stack<LttngEvent> newStack = new Stack<LttngEvent>(); >+ newStack.add(event); >+ fStacks.put(key, newStack); >+ } >+ } >+ >+ /** >+ * Checks if the stack contains a list of events of the given type. >+ * @param key >+ * The type of events to check for. >+ * @return "true" if the stack contains events of the given type, "false" otherwise. >+ */ >+ public boolean containsKey(String key) { >+ return fStacks.containsKey(key); >+ } >+ >+ /** >+ * Returns the list of events of the given type. >+ * @param key >+ * The type of events to return. >+ * @return The list of events of the given type, or null. >+ */ >+ public Stack<LttngEvent> getStackOf(String key) { >+ return fStacks.get(key); >+ } >+ >+ /** >+ * Removes the given event from the given stack list. >+ * @param key >+ * The given stack type. >+ * @param event >+ * The event to remove from the given stack type. >+ * @return "true" if the event was removed, "false" otherwise. >+ */ >+ public boolean removeEvent(String key, LttngEvent event) { >+ Stack<LttngEvent> stack = fStacks.get(key); >+ >+ boolean removed = false; >+ >+ try { >+ /** >+ * TODO Correct this... Here, no matter what CPU or other content field, we always remove the last event >+ * added to the stack. Should be something like : return stack.remove(event); >+ */ >+ stack.pop(); >+ removed = true; >+ } catch (Exception e) { >+ e.printStackTrace(); >+ } >+ >+ // Remove the stack from the stack list if it is empty >+ if (stack.isEmpty()) { >+ fStacks.remove(key); >+ } >+ >+ return removed; >+ } >+ >+ /** >+ * Clears the stack content. >+ */ >+ public void clear() { >+ fStacks.clear(); >+ } >+ >+ /** >+ * Prints the content of the stack to the console. >+ */ >+ @SuppressWarnings("nls") >+ public void printContent() { >+ Collection<Stack<LttngEvent>> values = fStacks.values(); >+ Iterator<Stack<LttngEvent>> valueIt = values.iterator(); >+ >+ Set<String> keys = fStacks.keySet(); >+ Iterator<String> keyIt = keys.iterator(); >+ >+ while (valueIt.hasNext() && keyIt.hasNext()) { >+ Stack<LttngEvent> stack = valueIt.next(); >+ >+ System.out.println(" " + keyIt.next() + " [" + stack.size() + "] : " + stack); >+ } >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/EventsPair.java b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/EventsPair.java >new file mode 100644 >index 0000000..3a13edd >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/EventsPair.java >@@ -0,0 +1,29 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.core.util; >+ >+import java.util.Vector; >+ >+ >+/** >+ * Contains two lists of events name. The first list contains the events identified as starting request and the second list >+ * contains the events identified as ending request >+ */ >+public class EventsPair extends Pair<Vector<String>, Vector<String>> { >+ >+ public EventsPair() { >+ super(); >+ } >+ >+ public EventsPair(Vector<String> startingEvents, Vector<String> endingEvents) { >+ super(startingEvents, endingEvents); >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/Pair.java b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/Pair.java >new file mode 100644 >index 0000000..cebcf03 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/Pair.java >@@ -0,0 +1,121 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.core.util; >+ >+/** >+ * Pair utility class, encapsulates a pair of objects. >+ * >+ * @author Philippe Sawicki >+ * >+ * @param <A> >+ * The type of the first object. >+ * @param <B> >+ * The type of the second object. >+ */ >+public abstract class Pair<A, B> { >+ >+ /** >+ * A reference to the first object. >+ */ >+ protected A fFirst; >+ /** >+ * A reference to the second object. >+ */ >+ protected B fSecond; >+ >+ /** >+ * Constructor. >+ * @param first >+ * The pair's first object. >+ * @param second >+ * The pair's second object. >+ */ >+ public Pair(A first, B second) { >+ fFirst = first; >+ fSecond = second; >+ } >+ >+ /** >+ * Constructor. >+ */ >+ public Pair() { >+ this(null, null); >+ } >+ >+ /** >+ * Pair hash code. >+ */ >+ @Override >+ public int hashCode() { >+ int hashFirst = fFirst != null ? fFirst.hashCode() : 0; >+ int hashSecond = fSecond != null ? fSecond.hashCode() : 0; >+ >+ return (hashFirst + hashSecond) * hashSecond + hashFirst; >+ } >+ >+ /** >+ * Object comparison. >+ */ >+ @Override >+ @SuppressWarnings("unchecked") >+ public boolean equals(Object other) { >+ if (other instanceof Pair) { >+ Pair<A, B> otherPair = (Pair<A, B>) other; >+ return ((fFirst == otherPair.fFirst || (fFirst != null && otherPair.fFirst != null && fFirst.equals(otherPair.fFirst))) && (fSecond == otherPair.fSecond || (fSecond != null >+ && otherPair.fSecond != null && fSecond.equals(otherPair.fSecond)))); >+ } >+ return false; >+ } >+ >+ /** >+ * Object to string. >+ */ >+ @Override >+ public String toString() { >+ return "(" + fFirst + ", " + fSecond + ")"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ >+ } >+ >+ /** >+ * Returns a reference to the pair's first object. >+ * @return A reference to the pair's first object. >+ */ >+ public A getFirst() { >+ return fFirst; >+ } >+ >+ /** >+ * Sets the pair's first object. >+ * @param first >+ * The pair's first object. >+ */ >+ public void setFirst(A first) { >+ fFirst = first; >+ } >+ >+ /** >+ * Returns a reference to the pair's second object. >+ * @return A reference to the pair's second object. >+ */ >+ public B getSecond() { >+ return fSecond; >+ } >+ >+ /** >+ * Sets the pair's second object. >+ * @param second >+ * The pair's second object. >+ */ >+ public void setSecond(B second) { >+ fSecond = second; >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/AllLTTngUITests.java b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/AllLTTngUITests.java >index dcc3c10..ab6fe78 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/AllLTTngUITests.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/AllLTTngUITests.java >@@ -7,6 +7,7 @@ public class AllLTTngUITests { > public static Test suite() { > TestSuite suite = new TestSuite(AllLTTngUITests.class.getName()); > //$JUnit-BEGIN$ >+ suite.addTest(org.eclipse.linuxtools.lttng.ui.tests.distribution.AllTests.suite()); > suite.addTest(org.eclipse.linuxtools.lttng.ui.tests.histogram.AllTests.suite()); > //$JUnit-END$ > return suite; >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/AllTests.java b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/AllTests.java >new file mode 100644 >index 0000000..b44a4de >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/AllTests.java >@@ -0,0 +1,27 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.tests.distribution; >+ >+import junit.framework.Test; >+import junit.framework.TestSuite; >+ >+public class AllTests { >+ >+ public static Test suite() { >+ >+ TestSuite suite = new TestSuite(AllTests.class.getName()); >+ //$JUnit-BEGIN$ >+ suite.addTestSuite(LatencyGraphModelTest.class); >+ //$JUnit-END$ >+ return suite; >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/LatencyGraphModelTest.java b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/LatencyGraphModelTest.java >new file mode 100644 >index 0000000..36c382d >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/LatencyGraphModelTest.java >@@ -0,0 +1,582 @@ >+package org.eclipse.linuxtools.lttng.ui.tests.distribution; >+ >+import junit.framework.TestCase; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.Config; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.GraphScaledData; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.LatencyGraphModel; >+ >+@SuppressWarnings("nls") >+public class LatencyGraphModelTest extends TestCase { >+ >+ // ------------------------------------------------------------------------ >+ // Test data >+ // ------------------------------------------------------------------------ >+ >+ // ------------------------------------------------------------------------ >+ // Housekeeping >+ // ------------------------------------------------------------------------ >+ >+ @Override >+ public void setUp() throws Exception { >+ } >+ >+ @Override >+ public void tearDown() throws Exception { >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Tests >+ // ------------------------------------------------------------------------ >+ >+ public void testLatencyGraphModel() { >+ LatencyGraphModel model = new LatencyGraphModel(); >+ assertEquals("nbBuckets", Config.DEFAULT_NUMBER_OF_BUCKETS, model.getNbBuckets()); >+ assertEquals("currentTime", Config.INVALID_EVENT_TIME, model.getCurrentEventTime()); >+ } >+ >+ public void testLatencyGraphModelInt() { >+ LatencyGraphModel model = new LatencyGraphModel(100); >+ assertEquals("nbBuckets", 100, model.getNbBuckets()); >+ assertEquals("currentTime", Config.INVALID_EVENT_TIME, model.getCurrentEventTime()); >+ } >+ >+ >+ public void testGraphModelListener() { >+ final int nbBuckets = 2000; >+ final int nbEvents = 10 * nbBuckets + 256; >+ final int[] count = new int[2]; >+ count [0] = 0; >+ count [1] = 0; >+ >+ // Test add listener and call of listener >+ IGraphModelListener listener = new IGraphModelListener() { >+ >+ @Override >+ public void graphModelUpdated() { >+ count[0]++; >+ >+ } >+ >+ @Override >+ public void currentEventUpdated(long currentEventTime) { >+ count[1]++; >+ } >+ }; >+ >+ // Test that the listener interface is called every 10000 events. >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ model.addGraphModelListener(listener); >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i+1, i, i); >+ } >+ >+ assertEquals("listener", 2, count[0]); >+ >+ // Test that the listener interface is called when complete is called. >+ model.complete(); >+ assertEquals("listener", 3, count[0]); >+ >+ // Test that clear triggers call of listener interface >+ model.clear(); >+ assertEquals("listener", 4, count[0]); >+ >+ // Test that clear triggers call of listener interface >+ model.setCurrentEventNotifyListeners(100); >+ assertEquals("listener", 1, count[1]); >+ >+ // Test remove listener >+ count[0] = 0; >+ count[1] = 0; >+ model.removeGraphModelListener(listener); >+ >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i, i, i); >+ } >+ model.complete(); >+ assertEquals("listener", 0, count[1]); >+ >+ // Test that clear triggers call of listener interface >+ model.setCurrentEventNotifyListeners(100); >+ assertEquals("listener", 0, count[1]); >+ } >+ >+ public void testConstructor() { >+ final int nbBuckets = 2000; >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ GraphScaledData scaledData = model.scaleTo(100, 100, 1); >+ >+ // Verify model parameters >+ assertEquals("Horizontal bucket duration", 1, model.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 1, model.getVerBucketDuration()); >+ >+ assertEquals("Horizontal first bucket time", 0, model.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", 0, model.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket ", 0, model.getHorLastBucket()); >+ assertEquals("Vertical last bucket ", 0, model.getVerLastBucket()); >+ >+ assertEquals("Horizontal first time", 0, model.getHorFirstEventTime()); >+ assertEquals("Vertical first time", 0, model.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal last time", 0, model.getHorLastEventTime()); >+ assertEquals("Vertical last time", 0, model.getVerLastEventTime()); >+ >+ assertEquals("Horizontal time limit", 2000, model.getHorTimeLimit()); >+ assertEquals("Vertical time limit", 2000, model.getVerTimeLimit()); >+ >+ // Verify scaled data parameters >+ scaledData = model.scaleTo(101, 100, 1); >+ >+ assertEquals("barWidth", 1, scaledData.getBarWidth()); >+ assertEquals("height", 100, scaledData.getHeight()); >+ assertEquals("width", 101, scaledData.getWidth()); >+ >+ assertEquals(Config.INVALID_EVENT_TIME, scaledData.getCurrentEventTime()); >+ >+ assertEquals("Horizontal bucket duration", 1, scaledData.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 1, scaledData.getVerBucketDuration()); >+ >+ assertEquals("Horizontal bucket end time", 1, scaledData.getHorBucketEndTime(0)); >+ assertEquals("Vertical bucket end time", 1, scaledData.getVerBucketEndTime(0)); >+ >+ assertEquals("Horizontal bucket start time", 0, scaledData.getHorBucketStartTime(0)); >+ assertEquals("Vertical bucket start time", 0, scaledData.getVerBucketStartTime(0)); >+ >+ assertEquals("Horizontal first time", 0, scaledData.getHorFirstEventTime()); >+ assertEquals("Vertical first time", 0, scaledData.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal first bucket time", 0, scaledData.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", 0, scaledData.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket time", 0, scaledData.getHorLastBucketTime()); >+ assertEquals("Vertical last bucket time", 0, scaledData.getVerLastBucketTime()); >+ >+ assertEquals("Horizontal number of buckets", 101, scaledData.getHorNbBuckets()); >+ assertEquals("Vertical nubmer of buckets", 100, scaledData.getVerNbBuckets()); >+ >+ assertEquals("Horizontal getIndex", 100, scaledData.getHorBucketIndex(100)); >+ assertEquals("Vertical getIndex", 124, scaledData.getVerBucketIndex(124)); >+ >+ assertEquals("Horizontal last bucket", 0, scaledData.getHorLastBucket()); >+ assertEquals("Vertical last bucket", 0, scaledData.getVerLastBucket()); >+ >+ assertEquals("Horizontal last event time", 0, scaledData.getHorLastEventTime()); >+ assertEquals("Vertical last event time", 0, scaledData.getVerLastEventTime()); >+ } >+ >+ public void testClear() { >+ final int nbBuckets = 2000; >+ final int nbEvents = 10 * nbBuckets + 256; >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i+1, i, i); >+ } >+ // make sure that we actually counted something. >+ GraphScaledData scaledData = model.scaleTo(100, 100, 1); >+ >+ assertTrue(scaledData.getHorLastBucket() > 0); >+ >+ model.clear(); >+ >+ // Verify model parameters >+ assertEquals("Horizontal bucket duration", 1, model.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 1, model.getVerBucketDuration()); >+ >+ assertEquals("Horizontal first bucket time", 0, model.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", 0, model.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket ", 0, model.getHorLastBucket()); >+ assertEquals("Vertical last bucket ", 0, model.getVerLastBucket()); >+ >+ assertEquals("Horizontal first time", 0, model.getHorFirstEventTime()); >+ assertEquals("Vertical first time", 0, model.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal last time", 0, model.getHorLastEventTime()); >+ assertEquals("Vertical last time", 0, model.getVerLastEventTime()); >+ >+ assertEquals("Horizontal time limit", 2000, model.getHorTimeLimit()); >+ assertEquals("Vertical time limit", 2000, model.getVerTimeLimit()); >+ >+ // Verify scaled data parameters >+ scaledData = model.scaleTo(101, 100, 1); >+ >+ assertEquals("barWidth", 1, scaledData.getBarWidth()); >+ assertEquals("height", 100, scaledData.getHeight()); >+ assertEquals("width", 101, scaledData.getWidth()); >+ >+ assertEquals(Config.INVALID_EVENT_TIME, scaledData.getCurrentEventTime()); >+ >+ assertEquals("Horizontal bucket duration", 1, scaledData.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 1, scaledData.getVerBucketDuration()); >+ >+ assertEquals("Horizontal bucket end time", 1, scaledData.getHorBucketEndTime(0)); >+ assertEquals("Vertical bucket end time", 1, scaledData.getVerBucketEndTime(0)); >+ >+ assertEquals("Horizontal bucket start time", 0, scaledData.getHorBucketStartTime(0)); >+ assertEquals("Vertical bucket start time", 0, scaledData.getVerBucketStartTime(0)); >+ >+ assertEquals("Horizontal first time", 0, scaledData.getHorFirstEventTime()); >+ assertEquals("Vertical first time", 0, scaledData.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal first bucket time", 0, scaledData.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", 0, scaledData.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket time", 0, scaledData.getHorLastBucketTime()); >+ assertEquals("Vertical last bucket time", 0, scaledData.getVerLastBucketTime()); >+ >+ assertEquals("Horizontal getIndex", 100, scaledData.getHorBucketIndex(100)); >+ assertEquals("Vertical getIndex", 124, scaledData.getVerBucketIndex(124)); >+ >+ assertEquals("Horizontal number of buckets", 101, scaledData.getHorNbBuckets()); >+ assertEquals("Vertical nubmer of buckets", 100, scaledData.getVerNbBuckets()); >+ >+ assertEquals("Horizontal last bucket", 0, scaledData.getHorLastBucket()); >+ assertEquals("Vertical last bucket", 0, scaledData.getVerLastBucket()); >+ >+ assertEquals("Horizontal last event time", 0, scaledData.getHorLastEventTime()); >+ assertEquals("Vertical last event time", 0, scaledData.getVerLastEventTime()); >+ } >+ >+ public void testCountEvent() { >+ final int nbBuckets = 2000; >+ final int nbEvents = 10 * nbBuckets + 256; >+ final long hOffset = 100; >+ final long vOffset = 55; >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i + 1, hOffset + i, vOffset + i); >+ } >+ >+ // Verify model parameters >+ assertEquals("Horizontal bucket duration", 16, model.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 16, model.getVerBucketDuration()); >+ >+ assertEquals("Horizontal first bucket time", hOffset, model.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", vOffset, model.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket ", (nbEvents - 1)/16, model.getHorLastBucket()); >+ assertEquals("Vertical last bucket ", (nbEvents - 1)/16, model.getVerLastBucket()); >+ >+ assertEquals("Horizontal first time", hOffset, model.getHorFirstEventTime()); >+ assertEquals("Vertical first time", vOffset, model.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal last time", nbEvents + hOffset - 1, model.getHorLastEventTime()); >+ assertEquals("Vertical last time", nbEvents + vOffset - 1, model.getVerLastEventTime()); >+ >+ assertEquals("Horizontal time limit", 16 * nbBuckets + hOffset, model.getHorTimeLimit()); >+ assertEquals("Vertical time limit", 16 * nbBuckets + vOffset, model.getVerTimeLimit()); >+ >+ // Verify scaled data parameters >+ GraphScaledData scaledData = model.scaleTo(50, 100, 1); >+ >+ assertEquals("barWidth", 1, scaledData.getBarWidth()); >+ assertEquals("height", 100, scaledData.getHeight()); >+ assertEquals("width", 50, scaledData.getWidth()); >+ >+ assertEquals(Config.INVALID_EVENT_TIME, scaledData.getCurrentEventTime()); >+ >+ // nbBars = width / barWidth >+ // bucketsPerBar = lastBucket/nbBars + 1 >+ // scaled bucket duration = bucketsPerBar * model.bucketDuration >+ // for nbBuckets=2000 and nbEvents=20256 (means 20256 ns + offset) -> model.bucketDuration = 16 >+ assertEquals("Horizontal bucket duration", 416, scaledData.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 208, scaledData.getVerBucketDuration()); >+ >+ // startTime + scaledData.bucketDuration >+ assertEquals("Horizontal bucket end time", hOffset + 416, scaledData.getHorBucketEndTime(0)); >+ assertEquals("Vertical bucket end time", 55 + 208, scaledData.getVerBucketEndTime(0)); >+ >+ assertEquals("Horizontal bucket start time", 100, scaledData.getHorBucketStartTime(0)); >+ assertEquals("Vertical bucket start time", 55, scaledData.getVerBucketStartTime(0)); >+ >+ assertEquals("Horizontal first time", 100, scaledData.getHorFirstEventTime()); >+ assertEquals("Vertical first time", 55, scaledData.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal first bucket time", hOffset, scaledData.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", 55, scaledData.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket time", hOffset + 48 * 416, scaledData.getHorLastBucketTime()); >+ assertEquals("Vertical last bucket time", vOffset + 97 * 208, scaledData.getVerLastBucketTime()); >+ >+ assertEquals("Horizontal getIndex", 47, scaledData.getHorBucketIndex(20000)); >+ assertEquals("Vertical getIndex", 47, scaledData.getVerBucketIndex(10000)); >+ >+ // nb Buckets = nbBars >+ assertEquals("Horizontal number of buckets", 50, scaledData.getHorNbBuckets()); >+ assertEquals("Vertical nubmer of buckets", 100, scaledData.getVerNbBuckets()); >+ >+ assertEquals("Horizontal last bucket", 48, scaledData.getHorLastBucket()); >+ assertEquals("Vertical last bucket", 97, scaledData.getVerLastBucket()); >+ >+ // start time of last bucket >+ assertEquals("Horizontal last event time", hOffset + nbEvents - 1, scaledData.getHorLastEventTime()); >+ assertEquals("Vertical last event time", vOffset + nbEvents - 1 , scaledData.getVerLastEventTime()); >+ } >+ >+ public void testCountEvent2() { >+ >+ final int nbBuckets = 2000; >+ final int nbEvents = 10 * nbBuckets + 256; >+ final long offset = 100; >+ final int height = 100; >+ final int width = 100; >+ final int barWidth = 1; >+ >+ int[][] expectedResults = new int[width/barWidth][height/barWidth]; >+ >+ int total = 0; >+ >+ // Horizontally and vertically the same data is used >+ >+ // for nbBuckets=2000 and nbEvents=20256 (means 20256 ns + offset) -> model.bucketDuration = 16 >+ // nbBars = width / barWidth = 100 >+ // bucketsPerBar = lastBucket/nbBars + 1 = 13 >+ // scaled bucket duration = bucketsPerBar * model.bucketDuration = 13 * 16 >+ boolean isFinished = false; >+ for (int i = 0; i < width/barWidth; i++) { >+ if (isFinished) { >+ break; >+ } >+ for (int j = 0; j < height/barWidth; j++) { >+ if (i == j) { >+ int value = 13 * 16; >+ if (total + value > nbEvents) { >+ expectedResults[i][j] = nbEvents - total; >+ isFinished = true; >+ break; >+ } >+ else { >+ expectedResults[i][j] = value; >+ total += value; >+ } >+ } >+ } >+ } >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i+1, offset + i, offset + i); >+ } >+ >+ GraphScaledData scaledData = model.scaleTo(height, width, barWidth); >+ >+ for (int i = 0; i < scaledData.getHorLastBucket(); i++) { >+ for (int j = 0; j < scaledData.getVerLastBucket(); j++) { >+ assertEquals(expectedResults[i][j], scaledData.getEventCount(i, j)); >+ } >+ } >+ } >+ >+ public void testCountEvent3() { >+ // Test with barWidth > 1 >+ final int nbBuckets = 2000; >+ final int nbEvents = 10 * nbBuckets + 256; >+ final long offset = 100; >+ final int height = 100; >+ final int width = 100; >+ final int barWidth = 4; >+ >+ int[][] expectedResults = new int[width/barWidth][height/barWidth]; >+ >+ int total = 0; >+ >+ // Horizontally and vertically the same data is used >+ >+ // for nbBuckets=2000 and nbEvents=20256 (means 20256 ns + offset) -> model.bucketDuration = 16 >+ // nbBars = width / barWidth = 25 >+ // bucketsPerBar = lastBucket/nbBars + 1 = 51 >+ // scaled bucket duration = bucketsPerBar * model.bucketDuration = 51 * 16 >+ boolean isFinished = false; >+ for (int i = 0; i < width/barWidth; i++) { >+ if (isFinished) { >+ break; >+ } >+ for (int j = 0; j < height/barWidth; j++) { >+ if (i == j) { >+ int value = 51 * 16; >+ if (total + value > nbEvents) { >+ expectedResults[i][j] = nbEvents - total; >+ isFinished = true; >+ break; >+ } >+ else { >+ expectedResults[i][j] = value; >+ total += value; >+ } >+ } >+ } >+ } >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i+1, offset + i, offset + i); >+ } >+ >+ GraphScaledData scaledData = model.scaleTo(height, width, barWidth); >+ >+ for (int i = 0; i < scaledData.getHorLastBucket(); i++) { >+ for (int j = 0; j < scaledData.getVerLastBucket(); j++) { >+ assertEquals(expectedResults[i][j], scaledData.getEventCount(i, j)); >+ } >+ } >+ } >+ >+ public void testCountEventReverse1() { >+ // Depending on the number of buckets and events the start buckets can be different >+ // between forward and reserve times. However, the content is correct. >+ final int nbBuckets = 100; >+ final int nbEvents = 256; >+ final long hOffset = 100; >+ final long vOffset = 55; >+ final int height = 100; >+ final int width = 50; >+ final int barWidth = 1; >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i + 1, hOffset + i, vOffset + i); >+ } >+ >+ GraphScaledData scaledData = model.scaleTo(width, height, barWidth); >+ >+ model.clear(); >+ >+ for (int i = nbEvents - 1; i >= 0; i--) { >+ model.countEvent(nbEvents - i, hOffset + i, vOffset + i); >+ } >+ >+ GraphScaledData scaledDataReverse = model.scaleTo(50, 100, 1); >+ >+ long count = 0; >+ for (int i = 0; i <= scaledData.getHorLastBucket(); i++) { >+ for (int j = 0; j <= scaledData.getVerLastBucket(); j++) { >+ count += scaledData.getEventCount(i, j); >+ } >+ } >+ >+ long revCount = 0; >+ for (int i = 0; i <= scaledDataReverse.getHorLastBucket(); i++) { >+ for (int j = 0; j <= scaledDataReverse.getVerLastBucket(); j++) { >+ revCount += scaledDataReverse.getEventCount(i, j); >+ } >+ } >+ >+ assertEquals(count, revCount); >+ >+ // Make sure that both scaledData have the same content >+ assertTrue("barWidth", scaledData.getBarWidth() == scaledDataReverse.getBarWidth()); >+ assertTrue("height", scaledData.getHeight() == scaledDataReverse.getHeight()); >+ assertTrue("width", scaledData.getWidth() == scaledDataReverse.getWidth()); >+ >+ assertTrue(scaledData.getCurrentEventTime() == scaledDataReverse.getCurrentEventTime()); >+ >+ assertTrue("Horizontal bucket duration", scaledData.getHorBucketDuration() == scaledDataReverse.getHorBucketDuration()); >+ assertTrue("Vertical bucket duration", scaledData.getVerBucketDuration() == scaledDataReverse.getVerBucketDuration()); >+ >+ // startTime + scaledData.bucketDuration >+ assertTrue("Horizontal bucket end time", scaledData.getHorBucketEndTime(0) == scaledDataReverse.getHorBucketEndTime(0)); >+ assertTrue("Vertical bucket end time", scaledData.getVerBucketEndTime(0) == scaledDataReverse.getVerBucketEndTime(0)); >+ >+ assertTrue("Horizontal bucket start time", scaledData.getHorBucketStartTime(0) == scaledDataReverse.getHorBucketStartTime(0)); >+ assertTrue("Vertical bucket start time", scaledData.getVerBucketStartTime(0) == scaledDataReverse.getVerBucketStartTime(0)); >+ >+ assertTrue("Horizontal first time", scaledData.getHorFirstEventTime() == scaledDataReverse.getHorFirstEventTime()); >+ assertTrue("Vertical first time", scaledData.getVerFirstEventTime() == scaledDataReverse.getVerFirstEventTime()); >+ >+ assertTrue("Horizontal getIndex", scaledData.getHorBucketIndex(200) == scaledDataReverse.getHorBucketIndex(200)); >+ assertTrue("Vertical getIndex", scaledData.getVerBucketIndex(100) == scaledDataReverse.getVerBucketIndex(100)); >+ >+ assertTrue("Horizontal last bucket", scaledData.getHorNbBuckets() == scaledDataReverse.getHorNbBuckets()); >+ assertTrue("Vertical last bucket", scaledData.getVerNbBuckets() == scaledDataReverse.getVerNbBuckets()); >+ >+ assertTrue("Horizontal nubmer of buckets", scaledData.getHorLastBucket() == scaledDataReverse.getHorLastBucket()); >+ assertTrue("Vertical nubmer of buckets", scaledData.getVerLastBucket() == scaledDataReverse.getVerLastBucket()); >+ >+ // start time of last bucket >+ assertTrue("Horizontal last event time", scaledData.getHorLastEventTime() == scaledDataReverse.getHorLastEventTime()); >+ assertTrue("Vertical last event time", scaledData.getVerLastEventTime() == scaledDataReverse.getVerLastEventTime()); >+ } >+ >+ public void testCountEventReverse2() { >+ // Depending on the number of buckets and events the start buckets can be different >+ // between forward and reserve times. However, the content is correct. >+ final int nbBuckets = 100; >+ final int nbEvents = 256; >+ final long hOffset = 100; >+ final long vOffset = 55; >+ final int height = 100; >+ final int width = 50; >+ final int barWidth = 1; >+ >+ LatencyGraphModel model = new LatencyGraphModel(nbBuckets); >+ >+ for (int i = nbEvents - 1; i >= 0; i--) { >+ model.countEvent(nbEvents - i, hOffset + i, vOffset + i); >+ } >+ >+ // Verify model parameters >+ int expectedBucketDuration = 4; >+ assertEquals("Horizontal bucket duration", expectedBucketDuration, model.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", expectedBucketDuration, model.getVerBucketDuration()); >+ >+ assertEquals("Horizontal first bucket time", hOffset, model.getHorFirstBucketTime()); >+ assertEquals("Vertical first bucket time", vOffset, model.getVerFirstBucketTime()); >+ >+ assertEquals("Horizontal last bucket", (nbEvents -1)/expectedBucketDuration, model.getHorLastBucket()); >+ assertEquals("Vertical last bucket", (nbEvents -1)/expectedBucketDuration, model.getVerLastBucket()); >+ >+ assertEquals("Horizontal first time", hOffset, model.getHorFirstEventTime()); >+ assertEquals("Vertical first time", vOffset, model.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal last time", nbEvents + hOffset - 1, model.getHorLastEventTime()); >+ assertEquals("Vertical last time", nbEvents + vOffset - 1, model.getVerLastEventTime()); >+ >+ assertEquals("Horizontal time limit", expectedBucketDuration * nbBuckets + hOffset, model.getHorTimeLimit()); >+ assertEquals("Vertical time limit", expectedBucketDuration * nbBuckets + vOffset, model.getVerTimeLimit()); >+ >+ GraphScaledData scaledData = model.scaleTo(50, 100, 1); >+ >+ // Make sure that both scaledData have the same content >+ assertEquals("barWidth", barWidth, scaledData.getBarWidth()); >+ assertEquals("height", height, scaledData.getHeight()); >+ assertEquals("width", width, scaledData.getWidth()); >+ >+ assertEquals(-1, scaledData.getCurrentEventTime()); >+ >+ assertEquals("Horizontal bucket duration", 8, scaledData.getHorBucketDuration()); >+ assertEquals("Vertical bucket duration", 4, scaledData.getVerBucketDuration()); >+ >+ // startTime + scaledData.bucketDuration >+ assertEquals("Horizontal bucket end time", hOffset + 8, scaledData.getHorBucketEndTime(0)); >+ assertEquals("Vertical bucket end time", vOffset + 4, scaledData.getVerBucketEndTime(0)); >+ >+ assertEquals("Horizontal bucket start time", hOffset, scaledData.getHorBucketStartTime(0)); >+ assertEquals("Vertical bucket start time", vOffset, scaledData.getVerBucketStartTime(0)); >+ >+ assertEquals("Horizontal first time", hOffset, scaledData.getHorFirstEventTime()); >+ assertEquals("Vertical first time", vOffset, scaledData.getVerFirstEventTime()); >+ >+ assertEquals("Horizontal getIndex", 12, scaledData.getHorBucketIndex(200)); >+ assertEquals("Vertical getIndex", 11, scaledData.getVerBucketIndex(100)); >+ >+ // nb Buckets = nbBars >+ assertEquals("Horizontal number of buckets", 50, scaledData.getHorNbBuckets()); >+ assertEquals("Vertical number of buckets", 100, scaledData.getVerNbBuckets()); >+ >+ assertEquals("Horizontal last bucket", 31, scaledData.getHorLastBucket()); >+ assertEquals("Vertical last bucket", 63, scaledData.getVerLastBucket()); >+ >+ // start time of last bucket >+ assertEquals("Horizontal last event time", 355, scaledData.getHorLastEventTime()); >+ assertEquals("Vertical last event time", 310, scaledData.getVerLastEventTime()); >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/histogram/HistogramDataModelTest.java b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/histogram/HistogramDataModelTest.java >index e0e0f3f..249d34d 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/histogram/HistogramDataModelTest.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/histogram/HistogramDataModelTest.java >@@ -17,6 +17,7 @@ import junit.framework.TestCase; > > import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramDataModel; > import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramScaledData; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.IHistogramModelListener; > > /** > * <b><u>HistogramDataModelTest</u></b> >@@ -55,6 +56,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbBuckets() == HistogramDataModel.DEFAULT_NUMBER_OF_BUCKETS); > assertTrue(model.getNbEvents() == 0); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == 0); > assertTrue(model.getTimeLimit() == HistogramDataModel.DEFAULT_NUMBER_OF_BUCKETS); >@@ -71,6 +73,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == 0); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == 0); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -84,11 +87,12 @@ public class HistogramDataModelTest extends TestCase { > public void testClear() { > final int nbBuckets = 100; > HistogramDataModel model = new HistogramDataModel(nbBuckets); >- model.countEvent(-1); >+ model.countEvent(0, -1); > > assertTrue(model.getNbEvents() == 0); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == 0); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -102,11 +106,12 @@ public class HistogramDataModelTest extends TestCase { > public void testCountEvent_0() { > final int nbBuckets = 100; > HistogramDataModel model = new HistogramDataModel(nbBuckets); >- model.countEvent(-1); >+ model.countEvent(0, -1); > > assertTrue(model.getNbEvents() == 0); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == 0); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -118,7 +123,7 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == 0); > } >@@ -126,6 +131,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == 0); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == 0); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -136,9 +142,9 @@ public class HistogramDataModelTest extends TestCase { > final int maxHeight = 10; > > HistogramDataModel model = new HistogramDataModel(nbBuckets); >- model.countEvent(1); >+ model.countEvent(0, 1); > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > assertTrue(result.fData[0] == 1); > for (int i = 1; i < result.fData.length; i++) { > assertTrue(result.fData[i] == 0); >@@ -147,6 +153,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == 1); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 1); > assertTrue(model.getStartTime() == 1); > assertTrue(model.getEndTime() == 1); > assertTrue(model.getTimeLimit() == nbBuckets + 1); >@@ -158,10 +165,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbBuckets; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == 1); > } >@@ -169,6 +176,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbBuckets); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbBuckets - 1); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -180,11 +188,11 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbBuckets; i++) { >- model.countEvent(i); >- model.countEvent(i); >+ model.countEvent(i, i); >+ model.countEvent(i+1, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == 2); > } >@@ -192,6 +200,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == 2 * nbBuckets); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbBuckets - 1); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -204,10 +213,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = startTime; i < startTime + nbBuckets; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == 1); > } >@@ -215,6 +224,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbBuckets); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == startTime); > assertTrue(model.getStartTime() == startTime); > assertTrue(model.getEndTime() == startTime + nbBuckets - 1); > assertTrue(model.getTimeLimit() == startTime + nbBuckets); >@@ -228,15 +238,15 @@ public class HistogramDataModelTest extends TestCase { > public void testScaleTo_0() { > HistogramDataModel model = new HistogramDataModel(10); > try { >- model.scaleTo(10, 0); >+ model.scaleTo(10, 0, 1); > } > catch (AssertionError e1) { > try { >- model.scaleTo(0, 10); >+ model.scaleTo(0, 10, 1); > } > catch (AssertionError e2) { > try { >- model.scaleTo(0, 0); >+ model.scaleTo(0, 0, 1); > } > catch (AssertionError e3) { > return; >@@ -255,10 +265,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbEvents; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == expectedResult[i]); > } >@@ -266,6 +276,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbEvents); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbEvents - 1); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -279,10 +290,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbEvents; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == expectedResult[i]); > } >@@ -290,6 +301,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbEvents); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 1); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbEvents - 1); > assertTrue(model.getTimeLimit() == nbBuckets); >@@ -303,10 +315,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbEvents; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == expectedResult[i]); > } >@@ -314,6 +326,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbEvents); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 2); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbEvents - 1); > assertTrue(model.getTimeLimit() == 2 * nbBuckets); >@@ -327,10 +340,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbEvents; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight); >+ HistogramScaledData result = model.scaleTo(nbBuckets, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == expectedResult[i]); > } >@@ -338,6 +351,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbEvents); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 4); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbEvents - 1); > assertTrue(model.getTimeLimit() == 4 * nbBuckets); >@@ -351,10 +365,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbEvents; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(10, maxHeight); >+ HistogramScaledData result = model.scaleTo(10, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == expectedResult[i]); > } >@@ -362,7 +376,7 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbEvents); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 2); >- assertTrue(model.getStartTime() == 0); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getEndTime() == nbEvents - 1); > assertTrue(model.getTimeLimit() == 2 * nbBuckets); > } >@@ -375,10 +389,10 @@ public class HistogramDataModelTest extends TestCase { > > HistogramDataModel model = new HistogramDataModel(nbBuckets); > for (int i = 0; i < nbEvents; i++) { >- model.countEvent(i); >+ model.countEvent(i, i); > } > >- HistogramScaledData result = model.scaleTo(10, maxHeight); >+ HistogramScaledData result = model.scaleTo(10, maxHeight, 1); > for (int i = 0; i < result.fData.length; i++) { > assertTrue(result.fData[i] == expectedResult[i]); > } >@@ -386,9 +400,195 @@ public class HistogramDataModelTest extends TestCase { > assertTrue(model.getNbEvents() == nbEvents); > assertTrue(model.getNbBuckets() == nbBuckets); > assertTrue(model.getBucketDuration() == 4); >+ assertTrue(model.getFirstBucketTime() == 0); > assertTrue(model.getStartTime() == 0); > assertTrue(model.getEndTime() == nbEvents - 1); > assertTrue(model.getTimeLimit() == 4 * nbBuckets); > } >+ >+ public void testScaleTo_7() { >+ // verify scaleTo with barWidth > 1 >+ final int nbBuckets = 100; >+ final int maxHeight = 24; >+ final int width = 10; >+ final int barWidth = 4; >+ final int nbEvents = 2 * nbBuckets + 1; >+ >+ // (int)(width / barWith) = 2 >+ // -> 2 bars -> expected result needs two buckets (scaled data) >+ // >+ // buckets (in model) per bar = last bucket id / nbBars + 1 (plus 1 to cover all used buckets) >+ // -> buckets per bar = 50 / 2 + 1 = 26 >+ // -> first entry in expected result is 26 * 4 = 104 >+ // -> second entry in expected result is 22 * 4 + 9 = 97 >+ final int[] expectedResult = new int[] { 104, 97 }; >+ >+ HistogramDataModel model = new HistogramDataModel(nbBuckets); >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i, i); >+ } >+ >+ // verify scaled data >+ HistogramScaledData result = model.scaleTo(width, maxHeight, barWidth); >+ >+ assertEquals(4 * 26, result.fBucketDuration); >+ assertEquals(0, result.fCurrentBucket); >+ assertEquals(0, result.fFirstBucketTime); >+ assertEquals(0, result.fFirstEventTime); >+ assertEquals(1, result.fLastBucket); >+ assertEquals(104, result.fMaxValue); >+ assertEquals((double)maxHeight/104, result.fScalingFactor); >+ assertEquals(maxHeight, result.fHeight); >+ assertEquals(width, result.fWidth); >+ assertEquals(barWidth, result.fBarWidth); >+ >+ for (int i = 0; i < result.fData.length; i++) { >+ assertEquals(expectedResult[i], result.fData[i]); >+ } >+ >+ // verify model >+ assertEquals(nbEvents, model.getNbEvents()); >+ assertEquals(nbBuckets, model.getNbBuckets()); >+ assertEquals(4, model.getBucketDuration()); >+ assertEquals(0, model.getFirstBucketTime()); >+ assertEquals(0, model.getStartTime()); >+ assertEquals(nbEvents - 1, model.getEndTime()); >+ assertEquals(4 * nbBuckets, model.getTimeLimit()); >+ } > >+ public void testScaleToReverse_1() { >+ final int nbBuckets = 100; >+ final int maxHeight = 24; >+ final int width = 10; >+ final int barWidth = 1; >+ final int nbEvents = 2 * nbBuckets + 1; >+ >+ // (int)(width / barWith) = 10 >+ // -> 10 bars -> expected result needs 10 buckets (scaled data) >+ // >+ // buckets in (model) per bar = last bucket id / nbBars + 1 (plus 1 to cover all used buckets) >+ // -> buckets per bar = 50 / 10 + 1 = 6 >+ final int[] expectedResult = new int[] { 21, 24, 24, 24, 24, 24, 24, 24, 12, 0 }; >+ >+ HistogramDataModel model = new HistogramDataModel(nbBuckets); >+ for (int i = nbEvents - 1; i >= 0; i--) { >+ model.countEvent(i, i); >+ } >+ >+ // verify scaled data >+ HistogramScaledData result = model.scaleTo(width, maxHeight, barWidth); >+ >+ assertEquals(4 * 6, result.fBucketDuration); >+ assertEquals(0, result.fCurrentBucket); >+ assertEquals(-3, result.fFirstBucketTime); // negative is correct, can happen when reverse >+ assertEquals(0, result.fFirstEventTime); >+ assertEquals(9, result.fLastBucket); >+ assertEquals(24, result.fMaxValue); >+ assertEquals((double)maxHeight/24, result.fScalingFactor); >+ assertEquals(maxHeight, result.fHeight); >+ assertEquals(width, result.fWidth); >+ assertEquals(barWidth, result.fBarWidth); >+ >+ for (int i = 0; i < result.fData.length; i++) { >+ assertEquals(expectedResult[i], result.fData[i]); >+ } >+ >+ // verify model >+ assertEquals(nbEvents, model.getNbEvents()); >+ assertEquals(nbBuckets, model.getNbBuckets()); >+ assertEquals(4, model.getBucketDuration()); >+ assertEquals(-3, model.getFirstBucketTime()); >+ assertEquals(0, model.getStartTime()); >+ assertEquals(nbEvents - 1, model.getEndTime()); >+ assertEquals(-3 + 4 * nbBuckets, model.getTimeLimit()); >+ } >+ >+ >+ public void testScaleToReverse_2() { >+ final int nbBuckets = 100; >+ final int maxHeight = 24; >+ final int width = 10; >+ final int barWidth = 1; >+ >+ final int nbEvents = 2 * nbBuckets; >+ >+ HistogramDataModel model = new HistogramDataModel(nbBuckets); >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i, i); >+ } >+ >+ HistogramScaledData result = model.scaleTo(width, maxHeight, barWidth); >+ >+ model.clear(); >+ >+ for (int i = nbEvents -1; i >= 0; i--) { >+ model.countEvent(i, i); >+ } >+ >+ HistogramScaledData revResult = model.scaleTo(width, maxHeight, barWidth); >+ >+ assertEquals(nbEvents, model.getNbEvents()); >+ assertEquals(nbBuckets, model.getNbBuckets()); >+ assertEquals(2, model.getBucketDuration()); >+ assertEquals(0, model.getFirstBucketTime()); >+ assertEquals(0, model.getStartTime()); >+ assertEquals(nbEvents - 1, model.getEndTime()); >+ assertEquals(2 * nbBuckets, model.getTimeLimit()); >+ >+ // For the above number of events, result and revResult are exactly the same. >+ assertEquals(result.fBucketDuration, revResult.fBucketDuration); >+ assertEquals(result.fCurrentBucket, revResult.fCurrentBucket); >+ assertEquals(result.fFirstBucketTime, revResult.fFirstBucketTime); >+ assertEquals(result.fMaxValue, revResult.fMaxValue); >+ assertEquals(result.fScalingFactor, revResult.fScalingFactor); >+ assertEquals(result.fLastBucket, revResult.fLastBucket); >+ assertEquals(result.getBucketEndTime(0), revResult.getBucketEndTime(0)); >+ assertEquals(result.getBucketStartTime(0), revResult.getBucketStartTime(0)); >+ >+ for (int i = 0; i < result.fData.length; i++) { >+ assertTrue(result.fData[i] == revResult.fData[i]); >+ } >+ } >+ >+ public void testModelListener() { >+ final int nbBuckets = 2000; >+ final int nbEvents = 10 * nbBuckets + 256; >+ final int[] count = new int[1]; >+ count [0] = 0; >+ >+ // Test add listener and call of listener >+ IHistogramModelListener listener = new IHistogramModelListener() { >+ @Override >+ public void modelUpdated() { >+ count[0]++; >+ } >+ }; >+ >+ // Test that the listener interface is called every 16000 events. >+ HistogramDataModel model = new HistogramDataModel(nbBuckets); >+ model.addHistogramListener(listener); >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i+1, i); >+ } >+ >+ assertTrue(count[0] == 1); >+ >+ // Test that the listener interface is called when complete is called. >+ model.complete(); >+ assertTrue(count[0] == 2); >+ >+ // Test that clear triggers call of listener interface >+ model.clear(); >+ assertTrue(count[0] == 3); >+ >+ // Test remove listener >+ count[0] = 0; >+ model.removeHistogramListener(listener); >+ >+ for (int i = 0; i < nbEvents; i++) { >+ model.countEvent(i, i); >+ } >+ model.complete(); >+ assertTrue(count[0] == 0); >+ } > } >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF b/lttng/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF >index e3fe166..8cf8896 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF >@@ -38,8 +38,13 @@ Export-Package: org.eclipse.linuxtools.lttng.ui;x-friends:="org.eclipse.linuxtoo > org.eclipse.linuxtools.lttng.ui.views.controlflow;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", > org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", > org.eclipse.linuxtools.lttng.ui.views.controlflow.model;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", >+ org.eclipse.linuxtools.lttng.ui.views.distribution.model, > org.eclipse.linuxtools.lttng.ui.views.events;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", > org.eclipse.linuxtools.lttng.ui.views.histogram;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", >+ org.eclipse.linuxtools.lttng.ui.views.latency;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", >+ org.eclipse.linuxtools.lttng.ui.views.latency.dialogs;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", >+ org.eclipse.linuxtools.lttng.ui.views.latency.listeners;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", >+ org.eclipse.linuxtools.lttng.ui.views.latency.model;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", > org.eclipse.linuxtools.lttng.ui.views.project;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", > org.eclipse.linuxtools.lttng.ui.views.project.dialogs;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", > org.eclipse.linuxtools.lttng.ui.views.project.handlers;x-friends:="org.eclipse.linuxtools.lttng.ui.tests", >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/add_button.gif b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/add_button.gif >new file mode 100644 >index 0000000000000000000000000000000000000000..ae9543c6e76539c99f5f0ffd5c172045bd3b63b0 >GIT binary patch >literal 308 >zcmZ?wbhEHb<YC}pSgOrnS{7na6>d=(Ze15;Qy1mX8t2lT<l2+$3M9LeU3-$eCZ~H% >z&hVd=6EG_$WMN_G!orY+1rf_jLl+gstf`FOP#wFbvUf{x@0O5hJ42`K3|nv@V&Q>^ >zHOHgY9FJamJZkN+sI|wVk6ueSb}ixP)r4bLfn?%^+sU^crQUj&`rv8Wf69R3PZmZ7 >z273k_1|R_WiGeNf!2A#4nqh4oi@ZvGxHL7V9MzoSqI$xU<&#CFfB%QWib69zo?TjT >yC!xh@0iVW`pEtzYTAVgM%rWEQU}yJWm6T!)v1gGGXYOL`W$I#>%HZM1U=09-MWlfM > >literal 0 >HcmV?d00001 > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/decreasebar_button.gif b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/decreasebar_button.gif >new file mode 100644 >index 0000000000000000000000000000000000000000..3d9202508cac6c0a8918e205cf8bc81d959f9859 >GIT binary patch >literal 211 >zcmZ?wbhEHb<YC}pIKsg2J|pW*Y~nK)zn1|K_jGI?S-74R)wnFJdsE5e-{1Ftf871^ >z@$kPNcYi;f{^!-ozaJ0pZ4q0QFYvj#;%j5=$Ks;@|Nk@K1&Tje7#SEu8FWCZKz1^) >z1|+D41zYxJsIC=~>J9Pf75Eb7z}I1VWlv+m0w&KZGJPi!EE^0&wjNJr6y#9g&h$Ol >nAhNHOV^i81fpaZhOD+m4-s1>dVrF%NfAQ=S2h0~ZF<1it>l{xw > >literal 0 >HcmV?d00001 > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/delete_button.gif b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/delete_button.gif >new file mode 100644 >index 0000000000000000000000000000000000000000..6bc0689f13d69327d28c8c9908f07d3596ce2c07 >GIT binary patch >literal 337 >zcmZ?wbhEHb<YnMtSZc^{+}QL>Vab=`lFvmYpNmUxXz4%DF}bf}d|cDunVH>FGrOY- >z+D{EEKZPcINzVS9ob?$<req(LP(LQAaa2<Mn1arykc6YcsvqrxKG+9-@`(885pgB8 >z<o=u$r(!+N<;9%}cRLl~b~3{4YDdk<0Ovc)7MygqJLztJ!rlJ3t>uHn=&y~n$8D`1 >z2l;<(sQc1T_xQ+>|D*uLpDc_F4E78<3_t+#69Ze`0r@k=za)E=`F$j^TDv>~xmmO) >z#%Nz!{zY-`rlt2eTm@G6ta5z7^0zQT@WkPd9)*2w4T~;rP+_QW<KU5&lH%cLlo6Ha >w?d2|alM(J^6=Ic;6e*V#pD8XQD>F}0T-HFGZGrn@c5&|&6W6S_cVw^z02)-GrvLx| > >literal 0 >HcmV?d00001 > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/increasebar_button.gif b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/increasebar_button.gif >new file mode 100644 >index 0000000000000000000000000000000000000000..aa58227d1a3e22127420c189e2f2c68ff21ca0fe >GIT binary patch >literal 208 >zcmZ?wbhEHb<YC}pIKsg2J|pW*Y~nK)zn1|K_jGI?S-74R)wnFJdsE5e-{1Ftf871^ >z@$kPNcYi;f{^!-ozaJ0pZ4q0QFYvj#;%j5=$Ks;@|Nk@K1&Tje7#SEu8FWCZKz1^) >z`X;D`1zYxJsICpNauN~UDGF3!vN(W=mC++PJXu4bneoWO8IEH8>@EroF5(lsS~xXD >h6u8{NL^2&XTJBYdG%5&~MLj8qSk6<yti{4$4FJiyML+-m > >literal 0 >HcmV?d00001 > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/warning.gif b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/warning.gif >new file mode 100644 >index 0000000000000000000000000000000000000000..7285660618e70cb44bfd305ce276d2080046fd00 >GIT binary patch >literal 999 >zcmeHGO>5Lp6uo5z`vkFR8A~jqPHL@;v|vP}X*bgd);<)q3zczGiB_uUW<bR0LTLJd >zX5mK`3Q-V@b`wxADrjUV8eGUjH(8Yj(&BUXz=cm&*Ysbw@NhWX3+HSOoU!pkL)O_2 >z=l}&dC_o*+F^FsE)v8{%OrR7dsO8YA<5&&HX*#yoAf9V_p6NHhZxFu;elu6yZ(2bU >z0@n!KYTy}xXNN9?Ue0RhLm1S<kVYOvo)!i5*e7uSaR^BSNvx*{NmGqQCW|eW23c%n >zDaleJV`0XkEF(Myo;p0!I8Q|aA|WCL!H8g{V3uIEU{r7rLKlL|1Y`=5>5^HJ*)ju} >zS(4k5Q^|eBKyjkDt~gcsD?kZD2~UYYiAYJJWT+HXN+BRJzzmQBikt+6h7wTbs-pr_ >z8mj!5K-EAca6Lc}HAEfJK(r8TM2a|pcnPtA*hF*@J;dCs@IU^g28=(&Hh?oQus((L >zO#t}-uSsd?=~zei;D$ZrPv>a&meQ|*^3t>RVBkuBU+`v*-nB;glUD1+<TkCi{pEv- >z(|d2%)e_Xcd@qjAU7uNbyjrWxA2`*sa{PDKv2v*}`P?{Y7e4No{_$?~L~CB(SL-32 >zi(&i2q03W!@blxwt($kgTKn9!ut_&ZTGyuSsj<S~$(t=>wdgGr`rq$2-+r6DwR<Kx >vY*r@Q?)M*EUR$d5E}ZWf9@=~Q&g}e!a__|>i?!ip_iJb6_M;m{1xEe?<OZ?n > >literal 0 >HcmV?d00001 > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/icons/eview16/graph.gif b/lttng/org.eclipse.linuxtools.lttng.ui/icons/eview16/graph.gif >new file mode 100644 >index 0000000000000000000000000000000000000000..fc187dc2d00511012016f905b4bfe2cb69a489c0 >GIT binary patch >literal 197 >zcmZ?wbhEHb6krfwIKsdnpT1Z=eUW0u64mTw8oA4L@>duZuQDxLV_C7zu4aQ%-A1>j >z&F)Q`yjr$+w`}oi+ve8}L|X$pwg+}@59!(w*0XcgtXcp6|7XAf6o0ZXGBAiU=z!!w >zb~3O!Jy7jS$?W1RnzPhMYR!o$u6t%2dAXta=8>jL`eG8UdSXvF4VpA2dj^(#snA-w >cRQZb4UXKm8H)JU3#cSNzvNTDroq@p`01%2s=l}o! > >literal 0 >HcmV?d00001 > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties b/lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties >index 5d6ea9d..2211985 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties >@@ -14,6 +14,7 @@ controlflow.view.name = Control Flow > resources.view.name = Resources > statistics.view.name = Statistics > histogram.view.name = Histogram >+latency.view.name = Latency View > > wizard.category.name = LTTng > project.new.wizard.name = LTTng Project >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/plugin.xml b/lttng/org.eclipse.linuxtools.lttng.ui/plugin.xml >index 15bd8f1..988f3e8 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/plugin.xml >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/plugin.xml >@@ -90,6 +90,15 @@ > name="%histogram.view.name" > restorable="true"> > </view> >+ <view >+ allowMultiple="false" >+ category="org.eclipse.linuxtools.lttng.ui.views.category" >+ class="org.eclipse.linuxtools.lttng.ui.views.latency.LatencyView" >+ icon="icons/eview16/graph.gif" >+ id="org.eclipse.linuxtools.lttng.ui.views.latency" >+ name="%latency.view.name" >+ restorable="true"> >+ </view> > </extension> > <extension > point="org.eclipse.ui.newWizards"> >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/BaseDistributionData.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/BaseDistributionData.java >new file mode 100644 >index 0000000..ef3ee33 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/BaseDistributionData.java >@@ -0,0 +1,142 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.distribution.model; >+ >+ >+/** >+ * <b><u>BaseDistributionData</u></b> >+ * <p> >+ */ >+public class BaseDistributionData { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ public final static int OUT_OF_RANGE_BUCKET = -1; >+ >+ /** >+ * Number of buckets >+ */ >+ protected final int fNbBuckets; >+ >+ /** >+ * Duration of each bucket >+ */ >+ protected long fBucketDuration; >+ >+ /** >+ * Bucket index of last event time >+ */ >+ protected int fLastBucket; >+ >+ /** >+ * Timestamp of the first bucket. (could be negative when analyzing events with descending time!!!) >+ */ >+ protected long fFirstBucketTime; >+ >+ /** >+ * Timestamp of the first event >+ */ >+ protected long fFirstEventTime; >+ >+ /** >+ * Timestamp of the last event >+ */ >+ protected long fLastEventTime; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ public BaseDistributionData(int nbBuckets) { >+ fNbBuckets = nbBuckets; >+ clear(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ public int getNbBuckets() { >+ return fNbBuckets; >+ } >+ >+ public long getBucketDuration() { >+ return fBucketDuration; >+ } >+ >+ public void setBucketDuration(long bucketDuration) { >+ fBucketDuration = bucketDuration; >+ } >+ >+ public int getLastBucket() { >+ return fLastBucket; >+ } >+ >+ public void setLastBucket(int lastBucket) { >+ fLastBucket = lastBucket; >+ } >+ >+ public long getFirstBucketTime() { >+ return fFirstBucketTime; >+ } >+ >+ public void setFirstBucketTime(long firstBucketTime) { >+ fFirstBucketTime = firstBucketTime; >+ } >+ >+ public long getLastBucketTime() { >+ return getBucketStartTime(fLastBucket); >+ } >+ >+ public long getFirstEventTime() { >+ return fFirstEventTime; >+ } >+ >+ public void setFirstEventTime(long firstEventTime) { >+ fFirstEventTime = firstEventTime; >+ } >+ >+ public long getLastEventTime() { >+ return fLastEventTime; >+ } >+ >+ public void setLastEventTime(long lastEventTime) { >+ fLastEventTime = lastEventTime; >+ } >+ >+ public long getBucketStartTime(int index) { >+ return fFirstBucketTime + index * fBucketDuration; >+ } >+ >+ public long getBucketEndTime(int index) { >+ return getBucketStartTime(index) + fBucketDuration; >+ } >+ >+ public int getIndex(long time) { >+ return (int)((time - fFirstBucketTime) / fBucketDuration); >+ } >+ >+ public boolean isIndexValid(int index) { >+ return ((index >= 0) && (index <= fNbBuckets - 1)); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ public void clear() { >+ fFirstBucketTime = 0; >+ fFirstEventTime = 0; >+ fLastEventTime = 0; >+ fLastBucket = 0; >+ fBucketDuration = 1; // 1ns >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/DistributionData.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/DistributionData.java >new file mode 100644 >index 0000000..75e3286 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/DistributionData.java >@@ -0,0 +1,179 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.distribution.model; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.Config; >+ >+/** >+ * <b><u>DistributionData</u></b> >+ * <p> >+ * The algorithm is based on the algorithm for the Histogram. The difference is that >+ * it supports two dimensions. For more details about the model principle >+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramDataModel >+ * <p> >+ */ >+abstract public class DistributionData extends BaseDistributionData { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Flag to indicate if given timestamp is the first one to count >+ */ >+ protected boolean fIsFirst; >+ >+ /** >+ * reference to fBuckets >+ */ >+ protected final int [][] fBuckets; >+ >+ /** >+ * Time limit (current available longest time) >+ */ >+ protected long fTimeLimit; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ public DistributionData(int[][] buckets) { >+ this(Config.DEFAULT_NUMBER_OF_BUCKETS, buckets); >+ } >+ >+ public DistributionData(int nbBuckets, int[][] buckets) { >+ super(nbBuckets); >+ fBuckets = buckets; >+ clear(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ public long getTimeLimit() { >+ return fTimeLimit; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.BaseDistributionData#clear() >+ */ >+ @Override >+ public void clear() { >+ super.clear(); >+ fIsFirst = true; >+ updateEndTime(); >+ } >+ >+ public boolean isFirst() { >+ return fIsFirst; >+ } >+ >+ public int countEvent(long timestamp) { >+ >+ // Set the start/end time if not already done >+ if (fIsFirst) { >+ fIsFirst = false; >+ fFirstBucketTime = timestamp; >+ fFirstEventTime = timestamp; >+ >+ updateEndTime(); >+ } >+ >+ // save first event time if necessary >+ if (timestamp < fFirstEventTime) { >+ fFirstEventTime = timestamp; >+ } >+ >+ // save last event time if necessary >+ if (fLastEventTime < timestamp) { >+ fLastEventTime = timestamp; >+ } >+ >+ >+ if (timestamp >= fFirstBucketTime) { >+ // Compact as needed >+ while (timestamp >= fTimeLimit) { >+ mergeBuckets(); >+ } >+ >+ } else { >+ >+ // Get offset for buckets adjustment >+ int offset = getOffset(timestamp); >+ >+ // Compact as needed >+ while (fLastBucket + offset >= fNbBuckets) { >+ mergeBuckets(); >+ offset = getOffset(timestamp); >+ } >+ >+ // Move buckets with offset (to right) >+ moveBuckets(offset); >+ >+ // Adjust start/end time and index >+ fLastBucket = fLastBucket + offset; >+ fFirstBucketTime = fFirstBucketTime - offset * fBucketDuration; >+ updateEndTime(); >+ } >+ >+ // Increment the right bucket >+ int index = (int) ((timestamp - fFirstBucketTime) / fBucketDuration); >+ >+ if (fLastBucket < index) { >+ fLastBucket = index; >+ } >+ >+ return index; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Abstract >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Moves content of buckets with the given offset in positive direction. >+ * It has to be implemented accordingly in the relevant sub-classes for >+ * horizontal and vertical direction. >+ * >+ * @param buckets - 2-dimensional array of buckets >+ * @param offset - offset to move >+ */ >+ abstract protected void moveBuckets(int offset); >+ >+ /** >+ * Merges buckets if end time is exceeded. It has to be implemented >+ * accordingly in the relevant sub-classes for horizontal and >+ * vertical direction. >+ * @param buckets >+ */ >+ abstract protected void mergeBuckets(); >+ >+ // ------------------------------------------------------------------------ >+ // Helper Functions >+ // ------------------------------------------------------------------------ >+ protected int getOffset(long timestamp) { >+ int offset = (int) ((fFirstBucketTime - timestamp) / fBucketDuration); >+ if ((fFirstBucketTime - timestamp) % fBucketDuration != 0) { >+ offset++; >+ } >+ return offset; >+ } >+ >+ protected void updateEndTime() { >+ fTimeLimit = fFirstBucketTime + fNbBuckets * fBucketDuration; >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/HorDistributionData.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/HorDistributionData.java >new file mode 100644 >index 0000000..766384f >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/HorDistributionData.java >@@ -0,0 +1,70 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.distribution.model; >+ >+/** >+ * <b><u>HorDistributionData</u></b> >+ * <p> >+ * Implementation of DistributionData for horizontal direction. >+ */ >+public class HorDistributionData extends DistributionData { >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ public HorDistributionData(int nbBuckets, int[][] buckets) { >+ super(nbBuckets, buckets); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Abstract function implementation >+ // ------------------------------------------------------------------------ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.DistributionData#moveBuckets(int) >+ */ >+ @Override >+ protected void moveBuckets(int offset) { >+ for (int j = 0; j < fNbBuckets; j++) { >+ >+ for(int i = fNbBuckets - 1; i >= offset; i--) { >+ fBuckets[i][j] = fBuckets[i-offset][j]; >+ } >+ >+ for (int i = 0; i < offset; i++) { >+ fBuckets[i][j] = 0; >+ } >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.DistributionData#mergeBuckets() >+ */ >+ @Override >+ protected void mergeBuckets() { >+ >+ for (int y = 0; y < fNbBuckets; y++) { >+ for (int i = 0; i < fNbBuckets / 2; i++) { >+ fBuckets[i][y] = fBuckets[2 * i][y] + fBuckets[2 * i + 1][y]; >+ } >+ >+ for (int i = fNbBuckets / 2; i < fNbBuckets; i++) { >+ fBuckets[i][y] = 0; >+ } >+ } >+ fBucketDuration = fBucketDuration * 2; >+ updateEndTime(); >+ fLastBucket = fNbBuckets / 2 - 1; >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/IBaseDistributionModel.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/IBaseDistributionModel.java >new file mode 100644 >index 0000000..5c61a9e >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/IBaseDistributionModel.java >@@ -0,0 +1,25 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+ >+package org.eclipse.linuxtools.lttng.ui.views.distribution.model; >+ >+public interface IBaseDistributionModel { >+ /** >+ * Interface to complete the model >+ */ >+ public void complete(); >+ >+ /** >+ * Interface to clear the model >+ */ >+ public void clear(); >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/VerDistributionData.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/VerDistributionData.java >new file mode 100644 >index 0000000..e44398c >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/VerDistributionData.java >@@ -0,0 +1,69 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.distribution.model; >+ >+/** >+ * <b><u>VerDistributionData</u></b> >+ * >+ * Implementation of DistributionData for vertical direction. >+ * <p> >+ */ >+public class VerDistributionData extends DistributionData { >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ public VerDistributionData(int nbBuckets, int[][] buckets) { >+ super(nbBuckets, buckets); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Abstract function implementation >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.DistributionData#moveBuckets(int) >+ */ >+ @Override >+ protected void moveBuckets(int offset) { >+ for (int j = 0; j < fNbBuckets; j++) { >+ >+ for(int i = fNbBuckets - 1; i >= offset; i--) { >+ fBuckets[j][i] = fBuckets[j][i-offset]; >+ } >+ >+ for (int i = 0; i < offset; i++) { >+ fBuckets[j][i] = 0; >+ } >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.DistributionData#mergeBuckets() >+ */ >+ @Override >+ protected void mergeBuckets() { >+ for (int x = 0; x < fNbBuckets; x++) { >+ for (int i = 0; i < fNbBuckets / 2; i++) { >+ fBuckets[x][i] = fBuckets[x][2 * i] + fBuckets[x][2 * i + 1]; >+ } >+ for (int i = fNbBuckets / 2; i < fNbBuckets; i++) { >+ fBuckets[x][i] = 0; >+ } >+ } >+ fBucketDuration = fBucketDuration * 2; >+ updateEndTime(); >+ fLastBucket = fNbBuckets / 2 - 1; >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/FullTraceHistogram.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/FullTraceHistogram.java >index d7e0345..176cf8d 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/FullTraceHistogram.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/FullTraceHistogram.java >@@ -8,6 +8,7 @@ > * > * Contributors: > * Francois Chouinard - Initial API and implementation >+ * Bernd Hufmann - Changed to updated histogram data model > *******************************************************************************/ > > package org.eclipse.linuxtools.lttng.ui.views.histogram; >@@ -75,7 +76,7 @@ public class FullTraceHistogram extends Histogram implements MouseMoveListener { > fRangeStartTime = startTime; > fRangeDuration = duration; > fZoom.setNewRange(fRangeStartTime, fRangeDuration); >- refresh(); >+ fDataModel.complete(); > } > > @Override >@@ -131,7 +132,7 @@ public class FullTraceHistogram extends Histogram implements MouseMoveListener { > newStart = newEnd - fZoom.getDuration(); > } > fRangeStartTime = newStart; >- refresh(); >+ fDataModel.complete(); > } > } > >@@ -166,7 +167,7 @@ public class FullTraceHistogram extends Histogram implements MouseMoveListener { > long bucketSpan = fScaledData.fBucketDuration; > int rangeWidth = (int) (fRangeDuration / bucketSpan); > >- int left = (int) ((fRangeStartTime - fDataModel.getStartTime()) / bucketSpan); >+ int left = (int) ((fRangeStartTime - fDataModel.getFirstBucketTime()) / bucketSpan); > int right = left + rangeWidth; > int center = (left + right) / 2; > int height = fCanvas.getSize().y - 2; >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/Histogram.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/Histogram.java >index b763260..dc665ab 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/Histogram.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/Histogram.java >@@ -8,6 +8,7 @@ > * > * Contributors: > * Francois Chouinard - Initial API and implementation >+ * Bernd Hufmann - Changed to updated histogram data model > *******************************************************************************/ > > package org.eclipse.linuxtools.lttng.ui.views.histogram; >@@ -69,15 +70,12 @@ import org.eclipse.swt.widgets.Text; > * <li>number of events in that time range > * </ul> > */ >-public abstract class Histogram implements ControlListener, PaintListener, KeyListener, MouseListener, MouseTrackListener { >+public abstract class Histogram implements ControlListener, PaintListener, KeyListener, MouseListener, MouseTrackListener, IHistogramModelListener { > > // ------------------------------------------------------------------------ > // Constants > // ------------------------------------------------------------------------ > >- // Histogram refresh frequency >- private final static int REFRESH_FREQUENCY = HistogramDataModel.DEFAULT_NUMBER_OF_BUCKETS; >- > // Histogram colors > private final Color fBackgroundColor = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE); > private final Color fCurrentEventColor = Display.getCurrent().getSystemColor(SWT.COLOR_RED); >@@ -86,6 +84,8 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > > // Timestamp scale (nanosecond) > public static final byte TIME_SCALE = -9; >+ >+ public static final int HISTOGRAM_BAR_WIDTH = 1; > > // ------------------------------------------------------------------------ > // Attributes >@@ -118,6 +118,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > > createWidget(parent); > fDataModel = new HistogramDataModel(); >+ fDataModel.addHistogramListener(this); > clear(); > > fCanvas.addControlListener(this); >@@ -129,6 +130,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > > public void dispose() { > fHistoBarColor.dispose(); >+ fDataModel.removeHistogramListener(this); > } > > private void createWidget(Composite parent) { >@@ -238,7 +240,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > // ------------------------------------------------------------------------ > > public long getStartTime() { >- return fDataModel.getStartTime(); >+ return fDataModel.getFirstBucketTime(); > } > > public long getEndTime() { >@@ -248,6 +250,10 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > public long getTimeLimit() { > return fDataModel.getTimeLimit(); > } >+ >+ public HistogramDataModel getDataModel() { >+ return fDataModel; >+ } > > // ------------------------------------------------------------------------ > // Operations >@@ -261,7 +267,6 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > public void clear() { > fDataModel.clear(); > fScaledData = null; >- refresh(); > } > > /** >@@ -269,12 +274,8 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > * > * @param timestamp > */ >- public void countEvent(long timestamp) { >- fDataModel.countEvent(timestamp); >- if (fDataModel.getNbEvents() % REFRESH_FREQUENCY == 0) { >- refresh(); >- refresh(); // This is intentional. Exercise left to the reader :-) >- } >+ public void countEvent(long eventCount, long timestamp) { >+ fDataModel.countEvent(eventCount, timestamp); > } > > /** >@@ -284,8 +285,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > */ > public void setCurrentEvent(long timestamp) { > fCurrentEventTime = (timestamp > 0) ? timestamp : 0; >- fDataModel.setCurrentEvent(timestamp); >- refresh(); >+ fDataModel.setCurrentEventNotifyListeners(timestamp); > } > > /** >@@ -297,7 +297,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > public synchronized long getTimestamp(int offset) { > assert offset > 0 && offset < fScaledData.fWidth; > try { >- return fDataModel.getStartTime() + fScaledData.fBucketDuration * offset; >+ return fDataModel.getFirstBucketTime() + fScaledData.fBucketDuration * offset; > } catch (Exception e) { > return 0; // TODO: Fix that racing condition (NPE) > } >@@ -310,9 +310,9 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > * @return the offset of the corresponding bucket (-1 if invalid) > */ > public synchronized int getOffset(long timestamp) { >- if (timestamp < fDataModel.getStartTime() || timestamp > fDataModel.getEndTime()) >+ if (timestamp < fDataModel.getFirstBucketTime() || timestamp > fDataModel.getEndTime()) > return -1; >- return (int) ((timestamp - fDataModel.getStartTime()) / fScaledData.fBucketDuration); >+ return (int) ((timestamp - fDataModel.getFirstBucketTime()) / fScaledData.fBucketDuration); > } > > /** >@@ -370,7 +370,8 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > /** > * Refresh the histogram display > */ >- protected void refresh() { >+ @Override >+ public void modelUpdated() { > if (!fCanvas.isDisposed() && fCanvas.getDisplay() != null) { > fCanvas.getDisplay().asyncExec(new Runnable() { > @Override >@@ -382,10 +383,10 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > if (canvasWidth <= 0 || canvasHeight <= 0) > return; > fDataModel.setCurrentEvent(fCurrentEventTime); >- fScaledData = fDataModel.scaleTo(canvasWidth, canvasHeight); >+ fScaledData = fDataModel.scaleTo(canvasWidth, canvasHeight, HISTOGRAM_BAR_WIDTH); > fCanvas.redraw(); > // Display histogram and update X-,Y-axis labels >- fTimeRangeStartText.setText(HistogramUtils.nanosecondsToString(fDataModel.getStartTime())); >+ fTimeRangeStartText.setText(HistogramUtils.nanosecondsToString(fDataModel.getFirstBucketTime())); > fTimeRangeEndText.setText(HistogramUtils.nanosecondsToString(fDataModel.getEndTime())); > fMaxNbEventsText.setText(Long.toString(fScaledData.fMaxValue)); > // The Y-axis area might need to be re-sized >@@ -540,8 +541,12 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > } > > private String formatToolTipLabel(int index) { >- long startTime = fDataModel.getStartTime() + fScaledData.fCurrentBucket * fScaledData.fBucketDuration; >- long endTime = startTime + fScaledData.fBucketDuration; >+ long startTime = fScaledData.getBucketStartTime(fScaledData.fCurrentBucket); >+ // negative values are possible if time values came into the model in decreasing order >+ if (startTime < 0) { >+ startTime = 0; >+ } >+ long endTime = fScaledData.getBucketEndTime(fScaledData.fCurrentBucket); > int nbEvents = (index >= 0) ? fScaledData.fData[index] : 0; > > StringBuffer buffer = new StringBuffer(); >@@ -561,12 +566,11 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi > > @Override > public void controlMoved(ControlEvent event) { >- refresh(); >+ fDataModel.complete(); > } > > @Override > public void controlResized(ControlEvent event) { >- refresh(); >+ fDataModel.complete(); > } >- > } >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramDataModel.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramDataModel.java >index 36c6fb7..28b944e 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramDataModel.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramDataModel.java >@@ -8,12 +8,15 @@ > * > * Contributors: > * Francois Chouinard - Initial API and implementation >+ * Bernd Hufmann - Implementation of new interfaces /listeners and support for >+ * time stamp in any order > *******************************************************************************/ > > package org.eclipse.linuxtools.lttng.ui.views.histogram; > > import java.util.Arrays; > >+import org.eclipse.core.runtime.ListenerList; > import org.eclipse.linuxtools.lttng.core.exceptions.EventOutOfSequenceException; > import org.eclipse.linuxtools.lttng.ui.LTTngUILogger; > >@@ -41,6 +44,15 @@ import org.eclipse.linuxtools.lttng.ui.LTTngUILogger; > * <i>timespan</i> (<i>timespan'</i> = <i>n</i> * <i>d'</i>, where <i>d'</i> = > * 2<i>d</i>). This compaction happens as needed as the trace is read. > * <p> >+ * The model allows for timestamps in not increasing order. The timestamps can >+ * be fed to the model in any order. If an event has a timestamp less than the >+ * <i>basetime</i>, the buckets will be moved to the right to account for the >+ * new smaller timestamp. The new <i>basetime</i> is a multiple of the bucket >+ * duration smaller then the previous <i>basetime</i>. Note that the <i>basetime</i> >+ * might not be anymore a timestamp of an event. If necessary, the buckets will >+ * be compacted before moving to the right. This might be necessary to not >+ * loose any event counts at the end of the buckets array. >+ * <p> > * The mapping from the model to the UI is performed by the <i>scaleTo()</i> > * method. By keeping the number of buckets <i>n</i> relatively large with > * respect to to the number of pixels in the actual histogram, we should achieve >@@ -51,7 +63,7 @@ import org.eclipse.linuxtools.lttng.ui.LTTngUILogger; > * <p> > * TODO: Cut-off eccentric values? TODO: Support for going back in time? > */ >-public class HistogramDataModel { >+public class HistogramDataModel implements IHistogramDataModel { > > // ------------------------------------------------------------------------ > // Constants >@@ -60,6 +72,8 @@ public class HistogramDataModel { > // The default number of buckets > public static final int DEFAULT_NUMBER_OF_BUCKETS = 16 * 1000; > >+ public static final int REFRESH_FREQUENCY = DEFAULT_NUMBER_OF_BUCKETS; >+ > // // The ratio where an eccentric value will be truncated > // private static final int MAX_TO_AVERAGE_CUTOFF_RATIO = 5; > >@@ -75,15 +89,15 @@ public class HistogramDataModel { > private int fLastBucket; > > // Timestamps >+ private long fFirstBucketTime; // could be negative when analyzing events with descending order!!! > private long fFirstEventTime; > private long fLastEventTime; > private long fCurrentEventTime; > private long fTimeLimit; >- >- // ------------------------------------------------------------------------ >- // Constructors >- // ------------------------------------------------------------------------ >- >+ >+ // private listener lists >+ private final ListenerList fModelListeners; >+ > public HistogramDataModel() { > this(DEFAULT_NUMBER_OF_BUCKETS); > } >@@ -91,6 +105,7 @@ public class HistogramDataModel { > public HistogramDataModel(int nbBuckets) { > fNbBuckets = nbBuckets; > fBuckets = new long[nbBuckets]; >+ fModelListeners = new ListenerList(); > clear(); > } > >@@ -100,10 +115,16 @@ public class HistogramDataModel { > fBucketDuration = other.fBucketDuration; > fNbEvents = other.fNbEvents; > fLastBucket = other.fLastBucket; >+ fFirstBucketTime = other.fFirstBucketTime; > fFirstEventTime = other.fFirstEventTime; > fLastEventTime = other.fLastEventTime; > fCurrentEventTime = other.fCurrentEventTime; > fTimeLimit = other.fTimeLimit; >+ fModelListeners = new ListenerList(); >+ Object[] listeners = other.fModelListeners.getListeners(); >+ for (Object listener : listeners) { >+ fModelListeners.add(listener); >+ } > } > > // ------------------------------------------------------------------------ >@@ -121,11 +142,15 @@ public class HistogramDataModel { > public long getBucketDuration() { > return fBucketDuration; > } >+ >+ public long getFirstBucketTime() { >+ return fFirstBucketTime; >+ } > > public long getStartTime() { > return fFirstEventTime; > } >- >+ > public long getEndTime() { > return fLastEventTime; > } >@@ -137,23 +162,55 @@ public class HistogramDataModel { > public long getTimeLimit() { > return fTimeLimit; > } >+ >+ // ------------------------------------------------------------------------ >+ // Listener handling >+ // ------------------------------------------------------------------------ >+ >+ public void addHistogramListener(IHistogramModelListener listener) { >+ fModelListeners.add(listener); >+ } >+ >+ public void removeHistogramListener(IHistogramModelListener listener) { >+ fModelListeners.remove(listener); >+ } > >+ private void fireModelUpdateNotification() { >+ fireModelUpdateNotification(0); >+ } >+ >+ private void fireModelUpdateNotification(long count) { >+ if (count % REFRESH_FREQUENCY == 0) { >+ Object[] listeners = fModelListeners.getListeners(); >+ for (int i = 0; i < listeners.length; i++) { >+ IHistogramModelListener listener = (IHistogramModelListener) listeners[i]; >+ listener.modelUpdated(); >+ } >+ } >+ } >+ > // ------------------------------------------------------------------------ > // Operations > // ------------------------------------------------------------------------ >+ @Override >+ public void complete() { >+ fireModelUpdateNotification(); >+ } > > /** > * Clear the histogram model. > */ >+ @Override > public void clear() { > Arrays.fill(fBuckets, 0); > fNbEvents = 0; >- fFirstEventTime = 0; >+ fFirstBucketTime = 0; > fLastEventTime = 0; > fCurrentEventTime = 0; > fLastBucket = 0; > fBucketDuration = 1; // 1ns > updateEndTime(); >+ fireModelUpdateNotification(); > } > > /** >@@ -166,62 +223,107 @@ public class HistogramDataModel { > } > > /** >+ * Sets the current event time >+ * >+ * @param timestamp >+ */ >+ public void setCurrentEventNotifyListeners(long timestamp) { >+ fCurrentEventTime = timestamp; >+ fireModelUpdateNotification(); >+ } >+ >+ /** > * Add event to the correct bucket, compacting the if needed. > * > * @param timestamp the timestamp of the event to count > */ >- public void countEvent(long timestamp) { >+ @Override >+ public void countEvent(long eventCount, long timestamp) { >+ >+ // Validate >+ if (timestamp < 0) { >+ String message = "Negative time value"; //$NON-NLS-1$ >+ EventOutOfSequenceException exception = new EventOutOfSequenceException(message); >+ LTTngUILogger.logError(message, exception); >+ return; >+ } >+ > // Set the start/end time if not already done > if (fLastBucket == 0 && fBuckets[0] == 0 && timestamp > 0) { >+ fFirstBucketTime = timestamp; > fFirstEventTime = timestamp; > updateEndTime(); > } >+ >+ if (timestamp < fFirstEventTime) { >+ fFirstEventTime = timestamp; >+ } >+ > if (fLastEventTime < timestamp) { > fLastEventTime = timestamp; > } >+ >+ if (timestamp >= fFirstBucketTime) { > >- // Compact as needed >- while (timestamp >= fTimeLimit) { >- mergeBuckets(); >- } >+ // Compact as needed >+ while (timestamp >= fTimeLimit) { >+ mergeBuckets(); >+ } > >- // Validate >- if (timestamp < fFirstEventTime) { >- String message = "Out of order timestamp. Going back in time?"; //$NON-NLS-1$ >- EventOutOfSequenceException exception = new EventOutOfSequenceException(message); >- LTTngUILogger.logError(message, exception); >- return; >- } >+ } else { >+ >+ // get offset for adjustment >+ int offset = getOffset(timestamp); >+ >+ // Compact as needed >+ while(fLastBucket + offset >= fNbBuckets) { >+ mergeBuckets(); >+ offset = getOffset(timestamp); >+ } >+ >+ moveBuckets(offset); >+ >+ fLastBucket = fLastBucket + offset; > >+ fFirstBucketTime = fFirstBucketTime - offset*fBucketDuration; >+ updateEndTime(); >+ } >+ > // Increment the right bucket >- int index = (int) ((timestamp - fFirstEventTime) / fBucketDuration); >+ int index = (int) ((timestamp - fFirstBucketTime) / fBucketDuration); > fBuckets[index]++; > fNbEvents++; > if (fLastBucket < index) > fLastBucket = index; >+ >+ fireModelUpdateNotification(eventCount); > } > > /** >- * Scale the model data to the width and height requested. >+ * Scale the model data to the width, height and bar width requested. > * > * @param width > * @param height >+ * @param bar width > * @return the result array of size [width] and where the highest value > * doesn't exceed [height] > */ >- public HistogramScaledData scaleTo(int width, int height) { >+ @Override >+ public HistogramScaledData scaleTo(int width, int height, int barWidth) { > // Basic validation >- if (width <= 0 || height <= 0) >- throw new AssertionError("Invalid histogram dimensions (" + width + "x" + height + ")"); >+ if (width <= 0 || height <= 0 || barWidth <= 0) >+ throw new AssertionError("Invalid histogram dimensions (" + width + "x" + height + ", barWidth=" + barWidth + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ > > // The result structure >- HistogramScaledData result = new HistogramScaledData(width, height); >+ HistogramScaledData result = new HistogramScaledData(width, height, barWidth); > > // Scale horizontally > result.fMaxValue = 0; >- int bucketsPerBar = fLastBucket / width + 1; >+ >+ int nbBars = width / barWidth; >+ int bucketsPerBar = fLastBucket / nbBars + 1; > result.fBucketDuration = bucketsPerBar * fBucketDuration; >- for (int i = 0; i < width; i++) { >+ for (int i = 0; i < nbBars; i++) { > int count = 0; > for (int j = i * bucketsPerBar; j < (i + 1) * bucketsPerBar; j++) { > if (fNbBuckets <= j) >@@ -240,11 +342,13 @@ public class HistogramDataModel { > } > > // Set the current event index in the scaled histogram >- if (fCurrentEventTime >= fFirstEventTime && fCurrentEventTime <= fLastEventTime) >- result.fCurrentBucket = (int) ((fCurrentEventTime - fFirstEventTime) / fBucketDuration) / bucketsPerBar; >+ if (fCurrentEventTime >= fFirstBucketTime && fCurrentEventTime <= fLastEventTime) >+ result.fCurrentBucket = (int) ((fCurrentEventTime - fFirstBucketTime) / fBucketDuration) / bucketsPerBar; > else > result.fCurrentBucket = HistogramScaledData.OUT_OF_RANGE_BUCKET; > >+ result.fFirstBucketTime = fFirstBucketTime; >+ result.fFirstEventTime = fFirstEventTime; > return result; > } > >@@ -253,7 +357,7 @@ public class HistogramDataModel { > // ------------------------------------------------------------------------ > > private void updateEndTime() { >- fTimeLimit = fFirstEventTime + fNbBuckets * fBucketDuration; >+ fTimeLimit = fFirstBucketTime + fNbBuckets * fBucketDuration; > } > > private void mergeBuckets() { >@@ -265,5 +369,23 @@ public class HistogramDataModel { > updateEndTime(); > fLastBucket = fNbBuckets / 2 - 1; > } >+ >+ private void moveBuckets(int offset) { >+ for(int i = fNbBuckets - 1; i >= offset; i--) { >+ fBuckets[i] = fBuckets[i-offset]; >+ } >+ >+ for (int i = 0; i < offset; i++) { >+ fBuckets[i] = 0; >+ } >+ } >+ >+ private int getOffset(long timestamp) { >+ int offset = (int) ((fFirstBucketTime - timestamp) / fBucketDuration); >+ if ((fFirstBucketTime - timestamp) % fBucketDuration != 0) { >+ offset++; >+ } >+ return offset; >+ } > > } >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java >index 2b88329..120d243 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java >@@ -30,22 +30,22 @@ public class HistogramRequest extends TmfEventRequest<LttngEvent> { > // Attributes > // ------------------------------------------------------------------------ > >- private final Histogram fHistogram; >+ protected final HistogramDataModel fHistogram; > > // ------------------------------------------------------------------------ > // Constructor > // ------------------------------------------------------------------------ > >- public HistogramRequest(Histogram histogram, TmfTimeRange range, int rank, int nbEvents, ITmfDataRequest.ExecutionType execType) { >+ public HistogramRequest(HistogramDataModel histogram, TmfTimeRange range, int rank, int nbEvents, ITmfDataRequest.ExecutionType execType) { > super(LttngEvent.class, range, rank, nbEvents, LttngConstants.DEFAULT_BLOCK_SIZE, execType); > fHistogram = histogram; > } > >- public HistogramRequest(Histogram histogram, TmfTimeRange range, ITmfDataRequest.ExecutionType execType) { >+ public HistogramRequest(HistogramDataModel histogram, TmfTimeRange range, ITmfDataRequest.ExecutionType execType) { > this(histogram, range, 0, ALL_DATA, execType); > } > >- public HistogramRequest(Histogram histogram, TmfTimeRange range, int rank, ITmfDataRequest.ExecutionType execType) { >+ public HistogramRequest(HistogramDataModel histogram, TmfTimeRange range, int rank, ITmfDataRequest.ExecutionType execType) { > this(histogram, range, rank, ALL_DATA, execType); > } > >@@ -58,19 +58,19 @@ public class HistogramRequest extends TmfEventRequest<LttngEvent> { > super.handleData(event); > if (event != null) { > long timestamp = event.getTimestamp().getValue(); >- fHistogram.countEvent(timestamp); >+ fHistogram.countEvent(getNbRead(), timestamp); > } > } > > @Override > public void handleCompleted() { >- fHistogram.refresh(); >+ fHistogram.complete(); > super.handleCompleted(); > } > > @Override > public void handleCancel() { >- fHistogram.refresh(); >+ fHistogram.clear(); > super.handleCancel(); > } > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramScaledData.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramScaledData.java >index 8260b4f..b1e6a1f 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramScaledData.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramScaledData.java >@@ -8,6 +8,7 @@ > * > * Contributors: > * Francois Chouinard - Initial API and implementation >+ * Bernd Hufmann - Added setter and getter > *******************************************************************************/ > > package org.eclipse.linuxtools.lttng.ui.views.histogram; >@@ -33,38 +34,67 @@ public class HistogramScaledData { > > public int fWidth; > public int fHeight; >+ public int fBarWidth; > public int[] fData; > public long fBucketDuration; > public long fMaxValue; > public int fCurrentBucket; > public int fLastBucket; > public double fScalingFactor; >+ public long fFirstBucketTime; >+ public long fFirstEventTime; > > // ------------------------------------------------------------------------ > // Constructor > // ------------------------------------------------------------------------ > >- public HistogramScaledData(int width, int height) { >+ public HistogramScaledData(int width, int height, int barWidth) { > fWidth = width; > fHeight = height; >- fData = new int[width]; >+ fBarWidth = barWidth; >+ fData = new int[width/fBarWidth]; > Arrays.fill(fData, 0); > fBucketDuration = 1; > fMaxValue = 0; > fCurrentBucket = 0; > fLastBucket = 0; > fScalingFactor = 1; >+ fFirstBucketTime = 0; > } > > public HistogramScaledData(HistogramScaledData other) { > fWidth = other.fWidth; > fHeight = other.fHeight; >+ fBarWidth = other.fBarWidth; > fData = Arrays.copyOf(other.fData, fWidth); > fBucketDuration = other.fBucketDuration; > fMaxValue = other.fMaxValue; > fCurrentBucket = other.fCurrentBucket; > fLastBucket = other.fLastBucket; > fScalingFactor = other.fScalingFactor; >+ fFirstBucketTime = other.fFirstBucketTime; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Setter and Getter >+ // ------------------------------------------------------------------------ >+ public long getFirstBucketTime() { >+ return fFirstBucketTime; > } > >+ public void setFirstBucketTime(long firstEventTime) { >+ fFirstBucketTime = firstEventTime; >+ } >+ >+ public long getLastBucketTime() { >+ return getBucketStartTime(fLastBucket); >+ } >+ >+ public long getBucketStartTime(int index) { >+ return fFirstBucketTime + index * fBucketDuration; >+ } >+ >+ public long getBucketEndTime(int index) { >+ return getBucketStartTime(index) + fBucketDuration; >+ } > } >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java >index 32f9dc1..62bc957 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java >@@ -265,8 +265,7 @@ public class HistogramView extends TmfView { > public void updateCurrentEventTime(long newTime) { > if (fCurrentExperiment != null) { > TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(newTime, TIME_SCALE), TmfTimestamp.BigCrunch); >- HistogramRequest request = new HistogramRequest(fTimeRangeHistogram, timeRange, 0, 1, >- ExecutionType.FOREGROUND) { >+ HistogramRequest request = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, 0, 1, ExecutionType.FOREGROUND) { > @Override > public void handleData(LttngEvent event) { > if (event != null) { >@@ -445,7 +444,7 @@ public class HistogramView extends TmfView { > > fTimeRangeHistogram.clear(); > fTimeRangeHistogram.setTimeRange(startTime, endTime - startTime); >- fTimeRangeRequest = new HistogramRequest(fTimeRangeHistogram, timeRange, ExecutionType.FOREGROUND); >+ fTimeRangeRequest = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, ExecutionType.FOREGROUND); > fCurrentExperiment.sendRequest(fTimeRangeRequest); > } > >@@ -453,8 +452,8 @@ public class HistogramView extends TmfView { > if (fFullTraceRequest != null && !fFullTraceRequest.isCompleted()) { > fFullTraceRequest.cancel(); > } >- fFullTraceRequest = new HistogramRequest(fFullTraceHistogram, fullRange, >- (int) fFullTraceHistogram.fDataModel.getNbEvents(), ExecutionType.BACKGROUND); >+ fFullTraceRequest = new HistogramRequest(fFullTraceHistogram.getDataModel(), fullRange, (int) fFullTraceHistogram.fDataModel.getNbEvents(), >+ ExecutionType.BACKGROUND); > fCurrentExperiment.sendRequest(fFullTraceRequest); > } > >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramDataModel.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramDataModel.java >new file mode 100644 >index 0000000..35606f3 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramDataModel.java >@@ -0,0 +1,38 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.histogram; >+ >+/** >+ * <b><u>IHistogramDataModel</u></b> >+ * <p> >+ */ >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.IBaseDistributionModel; >+ >+public interface IHistogramDataModel extends IBaseDistributionModel { >+ /** >+ * Add event to the correct bucket, compacting the if needed. >+ * >+ * @param timestamp the timestamp of the event to count >+ */ >+ public void countEvent(long eventCount, long timestamp); >+ >+ /** >+ * Scale the model data to the width, height and bar width requested. >+ * >+ * @param width >+ * @param height >+ * @param bar width >+ * @return the result array of size [width] and where the highest value >+ * doesn't exceed [height] considering the bar width [barWidth] >+ */ >+ public HistogramScaledData scaleTo(int width, int height, int barWidth); >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramModelListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramModelListener.java >new file mode 100644 >index 0000000..d980a17 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramModelListener.java >@@ -0,0 +1,23 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.histogram; >+ >+/** >+ * <b><u>IHistogramModelListener</u></b> >+ * <p> >+ */ >+public interface IHistogramModelListener { >+ /** >+ * Method to notify listeners about model updates >+ */ >+ public void modelUpdated(); >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeRangeHistogram.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeRangeHistogram.java >index 1ed5f7e..85a0061 100644 >--- a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeRangeHistogram.java >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeRangeHistogram.java >@@ -1,6 +1,6 @@ > /******************************************************************************* >- * Copyright (c) 2011 Ericsson > * >+ * Copyright (c) 2011 Ericsson > * 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 >@@ -8,6 +8,7 @@ > * > * Contributors: > * Francois Chouinard - Initial API and implementation >+ * Bernd Hufmann - Changed to updated histogram data model > *******************************************************************************/ > > package org.eclipse.linuxtools.lttng.ui.views.histogram; >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/AbstractViewer.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/AbstractViewer.java >new file mode 100644 >index 0000000..75597d6 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/AbstractViewer.java >@@ -0,0 +1,255 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency; >+ >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.IBaseDistributionModel; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractMouseListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractMouseTrackListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.ZoomListener; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.SWTException; >+import org.eclipse.swt.widgets.Canvas; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Display; >+ >+/** >+ * <b><u>AbstractViewer</u></b> >+ * <p> >+ * Abstract viewer. >+ * >+ * @author Philippe Sawicki >+ */ >+public abstract class AbstractViewer extends Canvas { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Parent composite node. >+ */ >+ protected Composite fParent; >+ >+ /** >+ * Paint listener. >+ */ >+ protected AbstractPaintListener fPaintListener; >+ >+ /** >+ * Zoom listener, to zoom in and out of a graph using the scroll wheel. >+ */ >+ protected ZoomListener fZoomListener; >+ >+ /** >+ * Tool tip listener. >+ */ >+ protected AbstractMouseTrackListener fMouseTraceListener; >+ >+ /** >+ * Mouse listener >+ */ >+ protected AbstractMouseListener fMouseListener; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parent >+ * The parent composite node. >+ * @param style >+ * The SWT style to use to render the view. >+ */ >+ public AbstractViewer(Composite parent, int style) { >+ super(parent, style); >+ >+ fParent = parent; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Abstract interface >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Clears the view. >+ */ >+ abstract public void clear(); >+ >+ /** >+ * Clears the background of the view but keeps min and max values. >+ */ >+ abstract public void clearBackground(); >+ >+ /** >+ * Method to increase bar width >+ */ >+ abstract public void increaseBarWidth(); >+ >+ /** >+ * Method to decrease bar width >+ */ >+ abstract public void decreaseBarWidth(); >+ >+ /** >+ * Return data model >+ */ >+ abstract public IBaseDistributionModel getModel(); >+ >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Returns the zoom factor for the canvas. >+ * @return The zoom factor for the canvas. >+ */ >+ public int getZoomFactor() { >+ if (fZoomListener != null) { >+ return fZoomListener.getZoomFactor(); >+ } else { >+ return 1; >+ } >+ } >+ >+ /** >+ * Returns the zoom increment for the canvas. >+ * @return The zoom increment for the canvas. >+ */ >+ public int getZoomIncrement() { >+ if (fZoomListener != null) { >+ return fZoomListener.getZoomIncrement(); >+ } else { >+ return 1; >+ } >+ } >+ >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Draw horizontal label each "nbTicks" ticks. >+ * @param nbTicks >+ * The draw interval. >+ */ >+ public void setDrawLabelEachNTicks(int nbTicks) { >+ fPaintListener.setDrawLabelEachNTicks(nbTicks); >+ } >+ >+ /** >+ * Sets the title of the graph. >+ * @param graphTitle >+ * The title of the graph. >+ */ >+ public void setGraphTitle(String graphTitle) { >+ fPaintListener.setGraphTitle(graphTitle); >+ } >+ >+ /** >+ * Sets the horizontal axis label. >+ * @param xLabel >+ * The horizontal axis label. >+ * @param offset >+ * The horizontal axis draw offset (in pixels). >+ */ >+ public void setXAxisLabel(String xLabel, int offset) { >+ fPaintListener.setXAxisLabel(xLabel, offset); >+ } >+ >+ /** >+ * Sets the vertical axis label. >+ * @param yLabel >+ * The vertical axis label. >+ */ >+ public void setYAxisLabel(String yLabel) { >+ fPaintListener.setYAxisLabel(yLabel); >+ } >+ >+ /** >+ * Asks for the view to be redrawn, synchronously or asynchronously. >+ * @param asyncRedraw >+ * If "true", the view will be redrawn asynchronously, otherwise it will be redraw synchronously. >+ */ >+ public void askForRedraw(boolean asyncRedraw) { >+ if (asyncRedraw == true) { >+ Display.getDefault().asyncExec(new Runnable() { >+ @Override >+ public void run() { >+ try { >+ redraw(); >+ } catch (SWTException e) { >+ // ... >+ } >+ } >+ }); >+ } else { >+ Display.getDefault().syncExec(new Runnable() { >+ @Override >+ public void run() { >+ try { >+ redraw(); >+ } catch (SWTException e) { >+ // ... >+ } >+ } >+ }); >+ } >+ } >+ >+ /** >+ * Asks for the view to be redrawn (asynchronously). >+ */ >+ public void askForRedraw() { >+ askForRedraw(true); >+ } >+ >+ /** >+ * Redraws the title after a zoom to display the new zoom factor. >+ */ >+ public void redrawTitle() { >+ fPaintListener.paintGraphTitle(); >+ } >+ >+ /** >+ * Removes the view's listeners before disposing of it. >+ */ >+ @Override >+ public void dispose() { >+ try { >+ if (fPaintListener != null) { >+ removePaintListener(fPaintListener); >+ fPaintListener = null; >+ } >+ if (fZoomListener != null) { >+ removeListener(SWT.MouseWheel, fZoomListener); >+ fZoomListener = null; >+ } >+ if (fMouseTraceListener != null) { >+ removeListener(SWT.MouseMove, fMouseTraceListener); >+ fMouseTraceListener = null; >+ } >+ } catch (SWTException e) { >+ // This exception will be thrown if the user closes the view >+ // while it is receiving data from the Analyzer. >+ >+ // ... >+ } >+ >+ super.dispose(); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/GraphViewer.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/GraphViewer.java >new file mode 100644 >index 0000000..2598543 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/GraphViewer.java >@@ -0,0 +1,158 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.GraphMouseListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.GraphPaintListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.TimePointerListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphDataModel; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.LatencyGraphModel; >+import org.eclipse.swt.widgets.Composite; >+ >+/** >+ * <b><u>GraphViewer</u></b> >+ * <p> >+ * Graph viewer. >+ * >+ * @author Philippe Sawicki >+ */ >+public class GraphViewer extends AbstractViewer implements IGraphModelListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Latency graph model >+ */ >+ private LatencyGraphModel fModel; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parent The parent composite node. >+ * @param style The SWT style to use to render the view. >+ */ >+ public GraphViewer(Composite parent, int style) { >+ super(parent, style); >+ >+ // Register the paint listener >+ fPaintListener = new GraphPaintListener(this); >+ addPaintListener(fPaintListener); >+ >+ // Register the mouse track listener >+ fMouseTraceListener = new TimePointerListener(this, (GraphPaintListener)fPaintListener); >+ addMouseTrackListener(fMouseTraceListener); >+ >+ // Register mouse listener >+ fMouseListener = new GraphMouseListener(this, (GraphPaintListener)fPaintListener); >+ addMouseListener(fMouseListener); >+ >+ fModel = new LatencyGraphModel(); >+ fModel.addGraphModelListener(this); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#dispose() >+ */ >+ @Override >+ public void dispose() { >+ fModel.removeGraphModelListener(this); >+ fPaintListener.dispose(); >+ super.dispose(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#clear() >+ */ >+ @Override >+ public void clear() { >+ fPaintListener.clear(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#clearBackground() >+ */ >+ @Override >+ public void clearBackground() { >+ fPaintListener.clear(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#increaseBarWidth() >+ */ >+ @Override >+ public void increaseBarWidth() { >+ fPaintListener.increaseBarWitdh(); >+ graphModelUpdated(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#decreaseBarWidth() >+ */ >+ @Override >+ public void decreaseBarWidth() { >+ fPaintListener.decreaseBarWitdh(); >+ graphModelUpdated(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#getModel() >+ */ >+ @Override >+ public IGraphDataModel getModel() { >+ return fModel; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener#graphModelUpdated() >+ */ >+ @Override >+ public void graphModelUpdated() { >+ if (!isDisposed() && getDisplay() != null) { >+ getDisplay().asyncExec(new Runnable() { >+ @Override >+ public void run() { >+ if (!isDisposed()) { >+ redraw(); >+ } >+ } >+ }); >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener#currentEventUpdated() >+ */ >+ @Override >+ public void currentEventUpdated(long currentEventTime) { >+ graphModelUpdated(); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/HistogramViewer.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/HistogramViewer.java >new file mode 100644 >index 0000000..96860d3 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/HistogramViewer.java >@@ -0,0 +1,157 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency; >+ >+import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramDataModel; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.IHistogramDataModel; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.IHistogramModelListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.HistogramPaintListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.TooltipListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.listeners.ZoomListener; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.widgets.Composite; >+ >+/** >+ * <b><u>HistogramViewer</u></b> >+ * <p> >+ * >+ * Histogram viewer. >+ * >+ * @author Philippe Sawicki >+ */ >+public class HistogramViewer extends AbstractViewer implements IHistogramModelListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Usable width for data plotting. >+ */ >+ protected int fUsableWidth; >+ >+ /** >+ * Latency histogram model. >+ */ >+ private HistogramDataModel fModel; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parent The parent composite node. >+ * @param style The SWT style to use to render the view. >+ */ >+ public HistogramViewer(Composite parent, int style) { >+ super(parent, style); >+ >+ // Register the paint listener >+ fPaintListener = new HistogramPaintListener(this); >+ addPaintListener(fPaintListener); >+ >+ // Register the zoom listener >+ fZoomListener = new ZoomListener(this); >+ addListener(SWT.MouseWheel, fZoomListener); >+ >+ // Register the mouse click listener >+ fMouseTraceListener = new TooltipListener(this, (HistogramPaintListener)fPaintListener); >+ addMouseTrackListener(fMouseTraceListener); >+ >+ fModel = new HistogramDataModel(); >+ fModel.addHistogramListener(this); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#dispose() >+ */ >+ @Override >+ public void dispose() { >+ fModel.removeHistogramListener(this); >+ fPaintListener.dispose(); >+ super.dispose(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#clear() >+ */ >+ @Override >+ public void clear() { >+ fPaintListener.clear(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#clearBackground() >+ */ >+ @Override >+ public void clearBackground() { >+ fPaintListener.clear(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#increaseBarWidth() >+ */ >+ @Override >+ public void increaseBarWidth() { >+ fPaintListener.increaseBarWitdh(); >+ modelUpdated(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#decreaseBarWidth() >+ */ >+ @Override >+ public void decreaseBarWidth() { >+ fPaintListener.decreaseBarWitdh(); >+ modelUpdated(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer#getModel() >+ */ >+ @Override >+ public IHistogramDataModel getModel() { >+ return fModel; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.IHistogramModelListener#modelUpdated() >+ */ >+ @Override >+ public void modelUpdated() { >+ >+ if (!isDisposed() && getDisplay() != null) { >+ getDisplay().asyncExec(new Runnable() { >+ @Override >+ public void run() { >+ if (!isDisposed()) { >+ redraw(); >+ } >+ } >+ }); >+ } >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/LatencyView.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/LatencyView.java >new file mode 100644 >index 0000000..dcb227e >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/LatencyView.java >@@ -0,0 +1,477 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency; >+ >+import org.eclipse.jface.action.Action; >+import org.eclipse.jface.action.IMenuManager; >+import org.eclipse.jface.action.IToolBarManager; >+import org.eclipse.jface.action.Separator; >+import org.eclipse.linuxtools.lttng.core.event.LttngEvent; >+import org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.AddDialog; >+import org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.DeleteDialog; >+import org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.ListDialog; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.Config; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.LatencyController; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.LatencyGraphModel; >+import org.eclipse.linuxtools.tmf.core.event.TmfEvent; >+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; >+import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp; >+import org.eclipse.linuxtools.tmf.core.experiment.TmfExperiment; >+import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest; >+import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest.ExecutionType; >+import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentDisposedSignal; >+import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal; >+import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal; >+import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal; >+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; >+import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal; >+import org.eclipse.linuxtools.tmf.ui.views.TmfView; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.events.ControlEvent; >+import org.eclipse.swt.events.ControlListener; >+import org.eclipse.swt.layout.FillLayout; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.ui.IActionBars; >+import org.eclipse.ui.plugin.AbstractUIPlugin; >+ >+/** >+ * <b><u>LatencyView</u></b> >+ * <p> >+ * TmfView displaying the latency views (i.e. the two latency charts). >+ * >+ * @author Philippe Sawicki >+ */ >+public class LatencyView extends TmfView implements IGraphModelListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ // The initial window span (in nanoseconds) >+ public static long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec >+ >+ /** >+ * The view's unique ID. >+ */ >+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.latency.LatencyView"; //$NON-NLS-1$ >+ >+ /** >+ * A reference to the currently selected experiment. >+ */ >+ protected TmfExperiment<LttngEvent> fExperiment = null; >+ >+ /** >+ * Parent composite. >+ */ >+ protected Composite fParent; >+ >+ /** >+ * Graph view. >+ */ >+ protected GraphViewer fGraphViewer; >+ >+ /** >+ * Histogram view. >+ */ >+ protected HistogramViewer fHistogramViewer; >+ >+ /** >+ * Action executed when the user wants to see the list of matching events. >+ */ >+ protected Action fListMatchingEvents; >+ >+ /** >+ * Action executed when the user wants to add matching events. >+ */ >+ protected Action fAddMatchingEvents; >+ >+ /** >+ * Action executed when the user wants to delete matching events. >+ */ >+ protected Action fDeleteMatchingEvents; >+ >+ /** >+ * Action executed when the user wants to increase the width of the histogram bars. >+ */ >+ protected Action fIncreaseBarWidth; >+ >+ /** >+ * Action executed when the user wants to decrease the width of the histogram bars. >+ */ >+ protected Action fDecreaseBarWidth; >+ >+ /** >+ * The current histogram window time range. >+ */ >+ protected TmfTimeRange fTimeRange = null; >+ >+ /** >+ * Controller of the latency model which is responsible to retrieve data from the trace >+ */ >+ final private LatencyController fController; >+ >+ /** >+ * Flag to notify that TimeSyncSignal was received and is being processed. >+ */ >+ private boolean fSyncSignalReceived = false; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ */ >+ public LatencyView() { >+ super(Messages.LatencyView_ViewName); >+ fController = LatencyController.getInstance(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Create the UI controls of this view. >+ * >+ * @param parent >+ * The composite parent of this view. >+ */ >+ @Override >+ public void createPartControl(Composite parent) { >+ // Save the parent >+ fParent = parent; >+ >+ makeActions(); >+ contributeToActionBars(); >+ >+ // Add a control listener to handle the view resize events (to redraw the canvas) >+ fParent.addControlListener(new ControlListener() { >+ @Override >+ public void controlMoved(ControlEvent event) { >+ fHistogramViewer.clearBackground(); >+ fGraphViewer.clearBackground(); >+ fController.handleCompleted(); >+ } >+ >+ @Override >+ public void controlResized(ControlEvent event) { >+ fHistogramViewer.clearBackground(); >+ fGraphViewer.clearBackground(); >+ fController.handleCompleted(); >+ } >+ }); >+ >+ // /////////////////////////////////////////////////////////////////////////////////// >+ // Layout for the whole view, other elements will be in a child composite of this one >+ // Contains : >+ // Composite layoutSelectionWindow >+ // Composite layoutTimesSpinner >+ // Composite layoutExperimentHistogram >+ // /////////////////////////////////////////////////////////////////////////////////// >+ Composite layoutFullView = new Composite(fParent, SWT.FILL); >+ FillLayout gridFullView = new FillLayout(); >+ gridFullView.marginHeight = 0; >+ gridFullView.marginWidth = 0; >+ layoutFullView.setLayout(gridFullView); >+ >+ // Create the graph views >+ fGraphViewer = new GraphViewer(layoutFullView, SWT.DOUBLE_BUFFERED); >+ fGraphViewer.setDrawLabelEachNTicks(2); >+ fGraphViewer.setGraphTitle(Messages.LatencyView_Graphs_Graph_Title); >+ fGraphViewer.setXAxisLabel(Messages.LatencyView_Graphs_Graph_XAxisLabel, 40); >+ fGraphViewer.setYAxisLabel(Messages.LatencyView_Graphs_Graph_YAxisLabel); >+ >+ fHistogramViewer = new HistogramViewer(layoutFullView, SWT.DOUBLE_BUFFERED); >+ fHistogramViewer.setDrawLabelEachNTicks(2); >+ fHistogramViewer.setGraphTitle(Messages.LatencyView_Graphs_Histogram_Title); >+ fHistogramViewer.setXAxisLabel(Messages.LatencyView_Graphs_Histogram_XAxisLabel, 55); >+ fHistogramViewer.setYAxisLabel(Messages.LatencyView_Graphs_Histogram_YAxisLabel); >+ >+ fController.registerModel(fGraphViewer.getModel()); >+ fController.registerModel(fHistogramViewer.getModel()); >+ >+ ((LatencyGraphModel)fGraphViewer.getModel()).addGraphModelListener(this); >+ >+ @SuppressWarnings("unchecked") >+ TmfExperiment<TmfEvent> experiment = (TmfExperiment<TmfEvent>) TmfExperiment.getCurrentExperiment(); >+ if (experiment != null) { >+ >+ TmfTimeRange experimentTRange = experiment.getTimeRange(); >+ >+ if (experimentTRange != TmfTimeRange.Null) { >+ TmfExperimentSelectedSignal<TmfEvent> signal = new TmfExperimentSelectedSignal<TmfEvent>(this, experiment); >+ experimentSelected(signal); >+ } >+ } >+ } >+ >+ @SuppressWarnings("nls") >+ @Override >+ public String toString() { >+ return "["+ Messages.LatencyView_ViewName+"]"; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Signal handlers >+ // ------------------------------------------------------------------------ >+ >+ @SuppressWarnings("unchecked") >+ @TmfSignalHandler >+ public void experimentSelected(TmfExperimentSelectedSignal<TmfEvent> signal) { >+ // Clear the views >+ fGraphViewer.clear(); >+ fHistogramViewer.clear(); >+ >+ if (fParent != null) { >+ // Update the trace reference >+ fExperiment = (TmfExperiment<LttngEvent>) signal.getExperiment(); >+ >+ fTimeRange = TmfTimeRange.Null; >+ TmfTimeRange experimentTRange = fExperiment.getTimeRange(); >+ >+ if (!experimentTRange.equals(TmfTimeRange.Null)) { >+ fTimeRange = new TmfTimeRange(experimentTRange.getStartTime(), >+ new TmfTimestamp(experimentTRange.getStartTime().getValue() + INITIAL_WINDOW_SPAN, experimentTRange.getStartTime().getScale(), experimentTRange.getStartTime().getPrecision())); >+ fController.refreshModels(fExperiment, fTimeRange); >+ } >+ } >+ } >+ @TmfSignalHandler >+ public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) { >+ if (fTimeRange == TmfTimeRange.Null && signal.getExperiment().equals(fExperiment)) { >+ TmfTimeRange experimentTRange = signal.getRange(); >+ >+ if (experimentTRange != TmfTimeRange.Null) { >+ fTimeRange = new TmfTimeRange(experimentTRange.getStartTime(), >+ new TmfTimestamp(experimentTRange.getStartTime().getValue() + INITIAL_WINDOW_SPAN, experimentTRange.getStartTime().getScale(), experimentTRange.getStartTime().getPrecision())); >+ fController.refreshModels(fExperiment, fTimeRange); >+ } >+ } >+ } >+ >+ @TmfSignalHandler >+ public void experimentDisposed(TmfExperimentDisposedSignal<TmfEvent> signal) { >+ fTimeRange = TmfTimeRange.Null; >+ fExperiment = null; >+ fController.clear(); >+ } >+ >+ /** >+ * Called when the LatencyView is closed: disposes of the canvas and unregisters models from views. >+ */ >+ @Override >+ public void dispose() { >+ fController.dispose(); >+ fController.deregisterModel(fGraphViewer.getModel()); >+ fController.deregisterModel(fHistogramViewer.getModel()); >+ ((LatencyGraphModel)fGraphViewer.getModel()).removeGraphModelListener(this); >+ >+ fGraphViewer.dispose(); >+ fHistogramViewer.dispose(); >+ >+ super.dispose(); >+ } >+ >+ /** >+ * Method called when synchronization is active and that the user select an event. >+ * >+ * The models will be updated with the new current selected time. >+ * >+ * @param signal >+ * Signal received from the framework. Contain the event. >+ */ >+ @TmfSignalHandler >+ public void currentTimeUpdated(TmfTimeSynchSignal signal) { >+ if (signal.getSource() != this) { >+ fSyncSignalReceived = true; >+ fController.setCurrentEventTime(signal.getCurrentTime().getValue()); >+ fSyncSignalReceived = false; >+ } >+ } >+ >+ /** >+ * Method called when synchronization is active and that the user changed the current time range. >+ >+ * The models will be updated with the new time range. >+ * >+ * @param signal >+ * Signal received from the framework. Contain the new time range. >+ */ >+ @TmfSignalHandler >+ public void synchToTimeRange(TmfRangeSynchSignal signal) { >+ if (signal.getSource() != this) { >+ // Erase the graph views >+ fGraphViewer.clear(); >+ fHistogramViewer.clear(); >+ >+ TmfTimestamp startTime = signal.getCurrentRange().getStartTime(); >+ TmfTimestamp endTime = signal.getCurrentRange().getEndTime(); >+ fTimeRange = new TmfTimeRange(startTime, endTime); >+ >+ fController.refreshModels(fExperiment, fTimeRange); >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener#graphModelUpdated() >+ */ >+ @Override >+ public void graphModelUpdated() { >+ // Nothing to do - update of viewers will be done in the viewers >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphModelListener#currentEventUpdated(long) >+ */ >+ @Override >+ public void currentEventUpdated(final long currentEventTime) { >+ if (fExperiment != null && >+ !fSyncSignalReceived && // Don't broadcast the current time that was received just before with a time sync signal >+ currentEventTime != Config.INVALID_EVENT_TIME) { >+ >+ // Queue update in the event request queue >+ TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(currentEventTime, Config.TIME_SCALE), TmfTimestamp.BigCrunch); >+ TmfEventRequest<LttngEvent> request = new TmfEventRequest<LttngEvent>(LttngEvent.class, timeRange, 0, 1, ExecutionType.FOREGROUND) { >+ @Override >+ public void handleCompleted() { >+ broadcast(new TmfTimeSynchSignal(this, new TmfTimestamp(currentEventTime, Config.TIME_SCALE))); >+ } >+ }; >+ fExperiment.sendRequest(request); >+ } >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Helper functions >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Fills the local pull down menu. >+ * @param manager >+ * The menu manager. >+ */ >+ private void fillLocalPullDown(IMenuManager manager) { >+ manager.add(new Separator()); >+ manager.add(fIncreaseBarWidth); >+ manager.add(fDecreaseBarWidth); >+ manager.add(new Separator()); >+ manager.add(fListMatchingEvents); >+ manager.add(fAddMatchingEvents); >+ manager.add(fDeleteMatchingEvents); >+ manager.add(new Separator()); >+ } >+ >+ /** >+ * Fills the local toolbar. >+ * @param manager >+ * The toolbar manager >+ */ >+ private void fillLocalToolBar(IToolBarManager manager) { >+ manager.add(new Separator()); >+ manager.add(fIncreaseBarWidth); >+ manager.add(fDecreaseBarWidth); >+ manager.add(new Separator()); >+ manager.add(fListMatchingEvents); >+ manager.add(fAddMatchingEvents); >+ manager.add(fDeleteMatchingEvents); >+ manager.add(new Separator()); >+ } >+ >+ /** >+ * Creates the actions required by the dialog events. >+ */ >+ private void makeActions() { >+ // Increase the histogram bar width >+ fIncreaseBarWidth = new Action() { >+ @Override >+ public void run() { >+ fHistogramViewer.increaseBarWidth(); >+ fGraphViewer.increaseBarWidth(); >+ } >+ }; >+ String tooltipText = Messages.LatencyView_Action_IncreaseBarWidth_Tooltip; >+ fIncreaseBarWidth.setText(tooltipText); >+ fIncreaseBarWidth.setToolTipText(tooltipText); >+ fIncreaseBarWidth.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages.LatencyView_tmf_UI, "icons/elcl16/increasebar_button.gif")); //$NON-NLS-1$ >+ >+ // Decrease the histogram bar width >+ fDecreaseBarWidth = new Action() { >+ @Override >+ public void run() { >+ fHistogramViewer.decreaseBarWidth(); >+ fGraphViewer.decreaseBarWidth(); >+ } >+ }; >+ tooltipText = Messages.LatencyView_Action_DecreaseBarWidth_Tooltip; >+ fDecreaseBarWidth.setText(tooltipText); >+ fDecreaseBarWidth.setToolTipText(tooltipText); >+ fDecreaseBarWidth.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages.LatencyView_tmf_UI, "icons/elcl16/decreasebar_button.gif")); //$NON-NLS-1$ >+ >+ // List matching events dialog >+ fListMatchingEvents = new Action() { >+ @Override >+ public void run() { >+ ListDialog listDialog = new ListDialog(fParent.getShell(), Messages.LatencyView_Dialogs_ListEvents_Title, Messages.LatencyView_Dialogs_ListEvents_Message); >+ listDialog.create(); >+ listDialog.open(); >+ } >+ }; >+ tooltipText = Messages.LatencyView_Action_ListEvents_Tooltip; >+ fListMatchingEvents.setText(tooltipText); >+ fListMatchingEvents.setToolTipText(tooltipText); >+ fListMatchingEvents.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages.LatencyView_tmf_UI, "icons/eview16/events_view.gif")); //$NON-NLS-1$ >+ >+ // Add matching events dialog >+ fAddMatchingEvents = new Action() { >+ @Override >+ public void run() { >+ AddDialog addDialog = new AddDialog(fParent.getShell(), Messages.LatencyView_Dialogs_AddEvents_Title, Messages.LatencyView_Dialogs_AddEvents_Message); >+ addDialog.create(); >+ addDialog.open(); >+ } >+ }; >+ tooltipText = Messages.LatencyView_Action_AddEvents_Tooltip; >+ fAddMatchingEvents.setText(tooltipText); >+ fAddMatchingEvents.setToolTipText(tooltipText); >+ fAddMatchingEvents.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages.LatencyView_tmf_UI, "icons/elcl16/add_button.gif")); //$NON-NLS-1$ >+ >+ // Remove matching events dialog >+ fDeleteMatchingEvents = new Action() { >+ @Override >+ public void run() { >+ DeleteDialog deleteDialog = new DeleteDialog(fParent.getShell(), Messages.LatencyView_Dialogs_DeleteEvents_Title, >+ Messages.LatencyView_Dialogs_DeleteEvents_Message); >+ deleteDialog.create(); >+ deleteDialog.open(); >+ } >+ }; >+ tooltipText = Messages.LatencyView_Action_DeleteEvents_Tooltip; >+ fDeleteMatchingEvents.setText(tooltipText); >+ fDeleteMatchingEvents.setToolTipText(tooltipText); >+ fDeleteMatchingEvents.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages.LatencyView_tmf_UI, "icons/elcl16/delete_button.gif")); //$NON-NLS-1$ >+ } >+ >+ /** >+ * Build the toolbar and menu by adding action buttons for dialogs. >+ */ >+ private void contributeToActionBars() { >+ IActionBars bars = getViewSite().getActionBars(); >+ fillLocalPullDown(bars.getMenuManager()); >+ fillLocalToolBar(bars.getToolBarManager()); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/Messages.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/Messages.java >new file mode 100644 >index 0000000..85cffa9 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/Messages.java >@@ -0,0 +1,85 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Updated >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency; >+ >+import org.eclipse.osgi.util.NLS; >+ >+/** >+ * Returns localized strings from the resource bundle (i.e. "messages.properties"). >+ * >+ * @author Philippe Sawicki >+ */ >+public class Messages { >+ >+ public static String LatencyView_ViewName; >+ public static String LatencyView_Action_IncreaseBarWidth_Tooltip; >+ public static String LatencyView_Action_DecreaseBarWidth_Tooltip; >+ public static String LatencyView_Action_AddEvents_Tooltip; >+ public static String LatencyView_Action_DeleteEvents_Tooltip; >+ public static String LatencyView_Action_ListEvents_Tooltip; >+ public static String LatencyView_Dialogs_AddEvents_Title; >+ public static String LatencyView_Dialogs_AddEvents_Message; >+ public static String LatencyView_Dialogs_AddEvents_Buttons_Add; >+ public static String LatencyView_Dialogs_AddEvents_Buttons_Close; >+ public static String LatencyView_Dialogs_AddEvents_Columns_Start; >+ public static String LatencyView_Dialogs_AddEvents_Columns_End; >+ public static String LatencyView_Dialogs_AddEvents_Columns_List_Trigger; >+ public static String LatencyView_Dialogs_AddEvents_Columns_List_End; >+ public static String LatencyView_Dialogs_AddEvents_Errors_NoSelection; >+ public static String LatencyView_Dialogs_AddEvents_Errors_StartNotSelected; >+ public static String LatencyView_Dialogs_AddEvents_Errors_EndNotSelected; >+ public static String LatencyView_Dialogs_AddEvents_Errors_SameSelected; >+ public static String LatencyView_Dialogs_AddEvents_Errors_AlreadyMatched; >+ public static String LatencyView_Dialogs_AddEvents_Errors_StartAlreadyMatched; >+ public static String LatencyView_Dialogs_AddEvents_Errors_EndAlreadyMatched; >+ public static String LatencyView_Dialogs_AddEvents_Errors_StartAsEnd; >+ public static String LatencyView_Dialogs_AddEvents_Errors_EndAsStart; >+ public static String LatencyView_Dialogs_DeleteEvents_Title; >+ public static String LatencyView_Dialogs_DeleteEvents_Message; >+ public static String LatencyView_Dialogs_DeleteEvents_Buttons_Close; >+ public static String LatencyView_Dialogs_DeleteEvents_Buttons_Delete; >+ public static String LatencyView_Dialogs_DeleteEvents_Confirm_Title; >+ public static String LatencyView_Dialogs_DeleteEvents_Confirm_Message; >+ public static String LatencyView_Dialogs_ListEvents_Title; >+ public static String LatencyView_Dialogs_ListEvents_Message; >+ public static String LatencyView_Dialogs_ListEvents_Buttons_Close; >+ public static String LatencyView_Dialogs_ListEvents_Buttons_Reset; >+ public static String LatencyView_Dialogs_ListEvents_Columns_Trigger; >+ public static String LatencyView_Dialogs_ListEvents_Columns_End; >+ public static String LatencyView_Dialogs_ListEvents_Confirm_Title; >+ public static String LatencyView_Dialogs_ListEvents_Confirm_Message; >+ public static String LatencyView_Graphs_Graph_Title; >+ public static String LatencyView_Graphs_Graph_XAxisLabel; >+ public static String LatencyView_Graphs_Graph_YAxisLabel; >+ public static String LatencyView_Graphs_Histogram_Title; >+ public static String LatencyView_Graphs_Histogram_XAxisLabel; >+ public static String LatencyView_Graphs_Histogram_YAxisLabel; >+ public static String LatencyView_msgSlogan; >+ public static String LatencyView_tmf_UI; >+ public static String LatencyView_ClippingWarning; >+ >+ >+ /** >+ * Bundle name. >+ */ >+ private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng.ui.views.latency.messages"; //$NON-NLS-1$ >+ >+ static { >+ // initialize resource bundle >+ NLS.initializeMessages(BUNDLE_NAME, Messages.class); >+ } >+ >+ private Messages() { >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AbstractDialog.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AbstractDialog.java >new file mode 100644 >index 0000000..2551eae >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AbstractDialog.java >@@ -0,0 +1,240 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new messages file, fixed warnings >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.dialogs; >+ >+import java.util.Vector; >+ >+import org.eclipse.jface.dialogs.IDialogSettings; >+import org.eclipse.jface.dialogs.IMessageProvider; >+import org.eclipse.jface.dialogs.TitleAreaDialog; >+import org.eclipse.linuxtools.lttng.core.latency.analyzer.EventMatcher; >+import org.eclipse.linuxtools.lttng.core.util.EventsPair; >+import org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.LatencyController; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Control; >+import org.eclipse.swt.widgets.Display; >+import org.eclipse.swt.widgets.Shell; >+ >+/** >+ * <b><u>AbstractDialog</u></b> >+ * <p> >+ * Includes the main functions shared by all the different dialogs. >+ * >+ * @author Philippe Sawicki >+ */ >+public abstract class AbstractDialog extends TitleAreaDialog { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * The dialog window title. >+ */ >+ protected String fDialogTitle; >+ /** >+ * The dialog window message. >+ */ >+ protected String fDialogMessage; >+ >+ /** >+ * The code returned by the dialog when the user closes the "Add" dialog. >+ */ >+ public static final int ADD = 53445; >+ /** >+ * The code returned by the dialog when the user closes the "Delete" dialog. >+ */ >+ public static final int DELETE = ADD + 1; >+ /** >+ * The code returned by the dialog when the user resets the latency pair to default. >+ */ >+ public static final int RESET = DELETE + 1; >+ >+ /** >+ * String ID of the number of pairs saved in the settings file. >+ */ >+ protected static final String LATENCY_NB_MATCH_PAIRS = "NB_LATENCY_MATCH_PAIRS"; //$NON-NLS-1$ >+ /** >+ * String ID of the start event pairs saved in the settings file. >+ */ >+ protected static final String LATENCY_PAIRS_START = "LATENCY_PAIRS_START"; //$NON-NLS-1$ >+ /** >+ * String ID of the end event pairs saved in the settings file. >+ */ >+ protected static final String LATENCY_PAIRS_END = "LATENCY_PAIRS_END"; //$NON-NLS-1$ >+ >+ /** >+ * Dialog settings, saves the event pairs across sessions. >+ */ >+ protected IDialogSettings fSettings; >+ >+ /** >+ * Do the graphs canvas need to be redrawn due to latency pairs changes ? >+ */ >+ protected boolean fRedrawGraphs = false; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parentShell >+ * The parent shell. >+ * @param title >+ * The dialog window's title. >+ * @param message >+ * The dialog window's message. >+ */ >+ public AbstractDialog(Shell parentShell, String title, String message) { >+ super(parentShell); >+ fDialogTitle = title; >+ fDialogMessage = message; >+ >+ fSettings = LTTngUiPlugin.getDefault().getDialogSettings(); >+ } >+ >+ /** >+ * Constructor >+ * @param parentShell >+ * The parent shell. >+ * @param title >+ * The dialog window's title. >+ */ >+ @SuppressWarnings("nls") >+ public AbstractDialog(Shell parentShell, String title) { >+ this(parentShell, title, ""); >+ } >+ >+ /** >+ * Constructor. >+ * @param parentShell >+ * The parent shell. >+ */ >+ @SuppressWarnings("nls") >+ public AbstractDialog(Shell parentShell) { >+ this(parentShell, "", ""); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Creates the dialog. >+ * >+ * <b>Note :</b> Since there is an issue with the table's vertical scroll bar, this dialog "resize" is necessary to >+ * ensure a minimal height for the window. >+ */ >+ @Override >+ public void create() { >+ super.create(); >+ // Set the title >+ setTitle(fDialogTitle); >+ // Set the message >+ setMessage(fDialogMessage, IMessageProvider.INFORMATION); >+ >+ // Position the dialog at the center of the screen >+ int windowWidth = Display.getCurrent().getPrimaryMonitor().getBounds().width; >+ int windowHeight = Display.getCurrent().getPrimaryMonitor().getBounds().height; >+ int dialogWidth = getShell().getSize().x; >+ int dialogHeight = windowHeight / 2; >+ >+ int x = (windowWidth - dialogWidth) / 2; >+ int y = (windowHeight - dialogHeight) / 2; >+ >+ getShell().setSize(getShell().getSize().x, dialogHeight); >+ getShell().setLocation(x, y); >+ } >+ >+ /** >+ * Formats the "#" of the event in the table by adding "00" before it. >+ * @param number >+ * The number to format. >+ * @param max >+ * The maximum number of event pairs in the list. >+ * @return The formatted string. >+ */ >+ @SuppressWarnings("nls") >+ protected String formatListNumber(int number, int max) { >+ return String.format("%0" + max + "d", number); >+ } >+ >+ /** >+ * Returns the match pairs saved in the settings file. >+ * @return The match pairs saved in the settings file. >+ */ >+ protected EventsPair getMatchPairs() { >+ try { >+ // Check if the settings file has already some data (i.e. try provoking an exception) >+ fSettings.getInt(LATENCY_NB_MATCH_PAIRS); >+ >+ String[] starts = fSettings.getArray(LATENCY_PAIRS_START); >+ String[] ends = fSettings.getArray(LATENCY_PAIRS_END); >+ >+ EventMatcher.getInstance().resetMatches(); >+ for (int i = 0; i < starts.length; i++) { >+ EventMatcher.getInstance().addMatch(starts[i], ends[i]); >+ } >+ >+ return EventMatcher.getInstance().getEvents(); >+ } catch (NumberFormatException e) { >+ return EventMatcher.getInstance().getEvents(); >+ } >+ } >+ >+ /** >+ * Saves the event match pairs to a settings file. >+ * @param start >+ * The start event types. >+ * @param end >+ * The end event types. >+ */ >+ protected void saveMatchPairs(Vector<String> start, Vector<String> end) { >+ fSettings.put(LATENCY_NB_MATCH_PAIRS, start.size()); >+ fSettings.put(LATENCY_PAIRS_START, start.toArray(new String[] {})); >+ fSettings.put(LATENCY_PAIRS_END, end.toArray(new String[] {})); >+ } >+ >+ /** >+ * Ask the LatencyView to send a new analysis request to the views, so that they can be redrawn. >+ */ >+ protected void redrawGraphs() { >+ LatencyController.getInstance().refreshModels(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected abstract Control createDialogArea(Composite parent); >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected abstract void createButtonsForButtonBar(Composite parent); >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.jface.dialogs.Dialog#isResizable() >+ */ >+ @Override >+ protected boolean isResizable() { >+ return true; >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AddDialog.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AddDialog.java >new file mode 100644 >index 0000000..aee1ef9 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AddDialog.java >@@ -0,0 +1,488 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new messages file, fixed warnings >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.dialogs; >+ >+import java.util.Vector; >+ >+import org.eclipse.linuxtools.lttng.core.latency.analyzer.EventMatcher; >+import org.eclipse.linuxtools.lttng.core.util.EventsPair; >+import org.eclipse.linuxtools.lttng.ui.views.latency.Messages; >+import org.eclipse.swt.SWT; >+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.Control; >+import org.eclipse.swt.widgets.Event; >+import org.eclipse.swt.widgets.Listener; >+import org.eclipse.swt.widgets.Shell; >+import org.eclipse.swt.widgets.Table; >+import org.eclipse.swt.widgets.TableColumn; >+import org.eclipse.swt.widgets.TableItem; >+ >+/** >+ * <b><u>AddDialog</u></b> >+ * <p> >+ * Add dialog, lets the user add custom start/end event pairs. >+ * >+ * @author Philippe Sawicki >+ */ >+public class AddDialog extends AbstractDialog { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * The dialog's start table. >+ */ >+ protected Table fStartTable; >+ >+ /** >+ * The dialog's end table. >+ */ >+ protected Table fEndTable; >+ >+ /** >+ * The dialog's list table. >+ */ >+ protected Table fListTable; >+ >+ /** >+ * Start table columns. >+ */ >+ protected TableColumn[] fStartColumns; >+ >+ /** >+ * End table columns. >+ */ >+ protected TableColumn[] fEndColumns; >+ >+ /** >+ * List table columns. >+ */ >+ protected TableColumn[] fListColumns; >+ >+ /** >+ * Start table column names (header titles). >+ */ >+ protected static final String[] START_COLUMN_NAMES = { "", Messages.LatencyView_Dialogs_AddEvents_Columns_Start }; //$NON-NLS-1$ >+ >+ /** >+ * End table column names (header titles). >+ */ >+ protected static final String[] END_COLUMN_NAMES = { "", Messages.LatencyView_Dialogs_AddEvents_Columns_End }; //$NON-NLS-1$ >+ >+ /** >+ * List table column names (header titles). >+ */ >+ protected static final String[] LIST_COLUMN_NAMES = { >+ "#", //$NON-NLS-1$ >+ Messages.LatencyView_Dialogs_AddEvents_Columns_List_Trigger, >+ Messages.LatencyView_Dialogs_AddEvents_Columns_List_End }; >+ >+ /** >+ * Column widths. >+ */ >+ protected static final int[] COLUMN_WIDTHS = { 25, 250, 250 }; >+ >+ /** >+ * Possible event types. >+ */ >+ protected Vector<String> fEventTypes = new Vector<String>(); >+ >+ /** >+ * Start event types. >+ */ >+ protected Vector<String> fEventStartTypes; >+ >+ /** >+ * End event types. >+ */ >+ protected Vector<String> fEventEndTypes; >+ >+ /** >+ * Selected start type. >+ */ >+ protected String fStartType; >+ >+ /** >+ * Selected end type. >+ */ >+ protected String fEndType; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parentShell >+ * The parent shell. >+ * @param title >+ * The dialog's window title. >+ * @param message >+ * The dialog's window message. >+ */ >+ public AddDialog(Shell parentShell, String title, String message) { >+ super(parentShell, title, message); >+ >+ // Get the possible events from the list >+ fEventTypes = EventMatcher.getInstance().getTypeList(); >+ >+ // Get the list of start and end types from the EventMatcher >+ EventsPair pair = getMatchPairs(); >+ fEventStartTypes = pair.getFirst(); >+ fEventEndTypes = pair.getSecond(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Creates the start table's columns (i.e. the table header). >+ */ >+ protected void createStartColumns() { >+ fStartColumns = new TableColumn[START_COLUMN_NAMES.length]; >+ for (int i = 0; i < START_COLUMN_NAMES.length; i++) { >+ fStartColumns[i] = new TableColumn(fStartTable, SWT.LEFT); >+ fStartColumns[i].setText(START_COLUMN_NAMES[i]); >+ fStartColumns[i].setWidth(COLUMN_WIDTHS[i]); >+ } >+ } >+ >+ /** >+ * Creates the end table's columns (i.e. the table header). >+ */ >+ protected void createEndColumns() { >+ fEndColumns = new TableColumn[END_COLUMN_NAMES.length]; >+ for (int i = 0; i < END_COLUMN_NAMES.length; i++) { >+ fEndColumns[i] = new TableColumn(fEndTable, SWT.LEFT); >+ fEndColumns[i].setText(END_COLUMN_NAMES[i]); >+ fEndColumns[i].setWidth(COLUMN_WIDTHS[i]); >+ } >+ } >+ >+ /** >+ * Creates the list table's columns (i.e. the table header). >+ */ >+ protected void createListColumns() { >+ fListColumns = new TableColumn[LIST_COLUMN_NAMES.length]; >+ for (int i = 0; i < LIST_COLUMN_NAMES.length; i++) { >+ fListColumns[i] = new TableColumn(fListTable, SWT.LEFT); >+ fListColumns[i].setText(LIST_COLUMN_NAMES[i]); >+ fListColumns[i].setWidth(COLUMN_WIDTHS[i]); >+ } >+ } >+ >+ /** >+ * Creates the start column list. >+ * @param parent >+ * The parent composite. >+ */ >+ protected void createStartColumn(Composite parent) { >+ final int style = SWT.SINGLE | SWT.CHECK | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL; >+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); >+ fStartTable = new Table(parent, style); >+ fStartTable.setLayoutData(layoutData); >+ >+ // Some cosmetic enhancements >+ fStartTable.setHeaderVisible(true); >+ fStartTable.setLinesVisible(true); >+ >+ createStartColumns(); >+ >+ for (int i = 0; i < fEventTypes.size(); i++) { >+ TableItem item = new TableItem(fStartTable, SWT.RIGHT); >+ >+ String[] columns = { fEventTypes.get(i), fEventTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ fStartTable.setItemCount(fEventTypes.size()); >+ >+ fStartTable.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ if (event.detail == SWT.CHECK) { >+ TableItem[] items = fStartTable.getItems(); >+ for (TableItem item : items) { >+ if (item != event.item) { >+ item.setChecked(false); >+ } >+ } >+ } >+ } >+ }); >+ } >+ >+ /** >+ * Creates the end column list. >+ * @param parent >+ * The parent composite. >+ */ >+ protected void createEndColumn(Composite parent) { >+ final int style = SWT.SINGLE | SWT.CHECK | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL; >+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); >+ fEndTable = new Table(parent, style); >+ fEndTable.setLayoutData(layoutData); >+ >+ // Some cosmetic enhancements >+ fEndTable.setHeaderVisible(true); >+ fEndTable.setLinesVisible(true); >+ >+ createEndColumns(); >+ >+ for (int i = 0; i < fEventTypes.size(); i++) { >+ TableItem item = new TableItem(fEndTable, SWT.RIGHT); >+ >+ String[] columns = { fEventTypes.get(i), fEventTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ fEndTable.setItemCount(fEventTypes.size()); >+ >+ fEndTable.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ if (event.detail == SWT.CHECK) { >+ TableItem[] items = fEndTable.getItems(); >+ for (TableItem item : items) { >+ if (item != event.item) { >+ item.setChecked(false); >+ } >+ } >+ } >+ } >+ }); >+ } >+ >+ /** >+ * Creates the list column for already existing event pairs. >+ * @param parent >+ * The parent composite. >+ */ >+ protected void createListColumn(Composite parent) { >+ final int style = SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL; >+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); >+ layoutData.horizontalSpan = 2; >+ fListTable = new Table(parent, style); >+ fListTable.setLayoutData(layoutData); >+ >+ // Some cosmetic enhancements >+ fListTable.setHeaderVisible(true); >+ fListTable.setLinesVisible(true); >+ >+ createListColumns(); >+ >+ for (int i = 0; i < fEventStartTypes.size(); i++) { >+ TableItem item = new TableItem(fListTable, SWT.RIGHT); >+ >+ String max = String.valueOf(fEventStartTypes.size()); >+ String number = formatListNumber(i + 1, max.length()); >+ >+ String[] columns = { number, fEventStartTypes.get(i), fEventEndTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ fListTable.setItemCount(103); >+ fListTable.remove(fEventTypes.size(), 103 - 1); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.AbstractDialog#createDialogArea(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected Control createDialogArea(Composite parent) { >+ GridLayout layout = new GridLayout(2, true); >+ parent.setLayout(layout); >+ >+ createStartColumn(parent); >+ createEndColumn(parent); >+ createListColumn(parent); >+ >+ return parent; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.AbstractDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected void createButtonsForButtonBar(Composite parent) { >+ GridData gridData = new GridData(); >+ gridData.verticalAlignment = GridData.FILL; >+ gridData.horizontalSpan = 1; >+ gridData.grabExcessHorizontalSpace = true; >+ gridData.grabExcessVerticalSpace = true; >+ gridData.horizontalAlignment = SWT.RIGHT; >+ >+ parent.setLayoutData(gridData); >+ >+ // Create the "Add" button >+ Button addButton = createButton(parent, ADD, Messages.LatencyView_Dialogs_AddEvents_Buttons_Add, false); >+ addButton.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ if (isValidInput()) { >+ // Add the event pair to the EventMatcher and save the pairs >+ EventMatcher.getInstance().addMatch(fStartType, fEndType); >+ fEventStartTypes.add(fStartType); >+ fEventEndTypes.add(fEndType); >+ saveMatchPairs(fEventStartTypes, fEventEndTypes); >+ >+ EventsPair pairs = EventMatcher.getInstance().getEvents(); >+ fEventStartTypes = pairs.getFirst(); >+ fEventEndTypes = pairs.getSecond(); >+ >+ fListTable.removeAll(); >+ >+ for (int i = 0; i < fEventStartTypes.size(); i++) { >+ TableItem item = new TableItem(fListTable, SWT.RIGHT); >+ >+ String max = String.valueOf(fEventStartTypes.size()); >+ String number = formatListNumber(i + 1, max.length()); >+ >+ String[] columns = { number, fEventStartTypes.get(i), fEventEndTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ saveMatchPairs(fEventStartTypes, fEventEndTypes); >+ } >+ >+ fRedrawGraphs = true; >+ } >+ }); >+ >+ // Create the "Close" button >+ Button closeButton = createButton(parent, CANCEL, Messages.LatencyView_Dialogs_AddEvents_Buttons_Close, false); >+ closeButton.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ setReturnCode(CANCEL); >+ >+ if (fRedrawGraphs == true) >+ redrawGraphs(); >+ >+ close(); >+ } >+ }); >+ } >+ >+ /** >+ * Validate the list before adding event pairs. >+ * @return "true" if the input is valid, "false" otherwise. >+ */ >+ protected boolean isValidInput() { >+ // Remove the previous error message >+ setErrorMessage(null); >+ >+ boolean valid = true; >+ >+ // Check if an item from the start list is selected >+ TableItem[] items = fStartTable.getItems(); >+ fStartType = null; >+ boolean startHasSelectedItem = false; >+ for (int i = 0; i < items.length && !startHasSelectedItem; i++) { >+ if (items[i].getChecked() == true) { >+ fStartType = items[i].getText(); >+ startHasSelectedItem = true; >+ } >+ } >+ >+ // Check if an item from the end list is selected >+ items = fEndTable.getItems(); >+ fEndType = null; >+ boolean endHasSelectedItem = false; >+ for (int i = 0; i < items.length && !endHasSelectedItem; i++) { >+ if (items[i].getChecked() == true) { >+ fEndType = items[i].getText(); >+ endHasSelectedItem = true; >+ } >+ } >+ >+ // Print error message if needed. >+ if (!startHasSelectedItem && !endHasSelectedItem) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_NoSelection); >+ valid = false; >+ } else if (!startHasSelectedItem) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_StartNotSelected); >+ valid = false; >+ } else if (!endHasSelectedItem) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_EndNotSelected); >+ valid = false; >+ } >+ >+ // Check if the same item is selected in both lists >+ if (startHasSelectedItem && endHasSelectedItem) { >+ if (fStartType.equalsIgnoreCase(fEndType)) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_SameSelected); >+ valid = false; >+ } >+ } >+ >+ // Check if the selected item is already in the list >+ if (startHasSelectedItem && endHasSelectedItem) { >+ EventsPair pairs = getMatchPairs(); >+ Vector<String> startEvents = pairs.getFirst(); >+ Vector<String> endEvents = pairs.getSecond(); >+ >+ boolean startAlreadyUsed = false; >+ boolean endAlreadyUsed = false; >+ boolean startAsEndAlreadyUsed = false; >+ boolean endAsStartAlreadyUsed = false; >+ >+ if (startEvents.contains(fStartType)) { >+ startAlreadyUsed = true; >+ } >+ if (endEvents.contains(fEndType)) { >+ endAlreadyUsed = true; >+ } >+ if (startEvents.contains(fEndType)) { >+ endAsStartAlreadyUsed = true; >+ } >+ if (endEvents.contains(fStartType)) { >+ startAsEndAlreadyUsed = true; >+ } >+ >+ if (startAlreadyUsed && endAlreadyUsed) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_AlreadyMatched); >+ valid = false; >+ } else if (startAlreadyUsed) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_StartAlreadyMatched); >+ valid = false; >+ } else if (endAlreadyUsed) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_EndAlreadyMatched); >+ valid = false; >+ } >+ >+ if (startAsEndAlreadyUsed) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_StartAsEnd); >+ valid = false; >+ } >+ if (endAsStartAlreadyUsed) { >+ setErrorMessage(Messages.LatencyView_Dialogs_AddEvents_Errors_EndAsStart); >+ valid = false; >+ } >+ } >+ >+ return valid; >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/DeleteDialog.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/DeleteDialog.java >new file mode 100644 >index 0000000..c975688 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/DeleteDialog.java >@@ -0,0 +1,155 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new messages file, fixed warnings >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.dialogs; >+ >+import org.eclipse.jface.dialogs.MessageDialog; >+import org.eclipse.linuxtools.lttng.core.latency.analyzer.EventMatcher; >+import org.eclipse.linuxtools.lttng.ui.views.latency.Messages; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.layout.GridData; >+import org.eclipse.swt.widgets.Button; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Event; >+import org.eclipse.swt.widgets.Listener; >+import org.eclipse.swt.widgets.Shell; >+import org.eclipse.swt.widgets.TableItem; >+ >+/** >+ * <b><u>DeleteDialog</u></b> >+ * <p> >+ * Remove dialog, lets the user remove start/end event pairs. >+ * >+ * @author Philippe Sawicki >+ */ >+public class DeleteDialog extends ListDialog { >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parentShell >+ * The parent shell. >+ * @param title >+ * The dialog's window title. >+ * @param message >+ * The dialog's window message. >+ */ >+ public DeleteDialog(Shell parentShell, String title, String message) { >+ super(parentShell, title, message); >+ >+ // Set the table style >+ fStyle = SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.ListDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected void createButtonsForButtonBar(Composite parent) { >+ GridData gridData = new GridData(); >+ gridData.verticalAlignment = GridData.FILL; >+ gridData.horizontalSpan = 1; >+ gridData.grabExcessHorizontalSpace = true; >+ gridData.grabExcessVerticalSpace = true; >+ gridData.horizontalAlignment = SWT.RIGHT; >+ >+ parent.setLayoutData(gridData); >+ >+ // Create the "Delete" button >+ Button deleteButton = createButton(parent, DELETE, Messages.LatencyView_Dialogs_DeleteEvents_Buttons_Delete, false); >+ deleteButton.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ TableItem selectedItem = fTable.getSelection()[0]; >+ if (selectedItem == null) >+ return; >+ >+ int[] selectedIndices = fTable.getSelectionIndices(); >+ >+ String deletePairs = ""; //$NON-NLS-1$ >+ for (int i = 0; i < selectedIndices.length; i++) { >+ int index = selectedIndices[i]; >+ deletePairs += "\t* " + fEventStartTypes.get(index) + " / " + fEventEndTypes.get(index); //$NON-NLS-1$ //$NON-NLS-2$ >+ >+ if (i < selectedIndices.length - 1) { >+ deletePairs += "\n"; //$NON-NLS-1$ >+ } >+ } >+ >+ boolean confirmDeletion = MessageDialog.openQuestion(getShell(), Messages.LatencyView_Dialogs_DeleteEvents_Confirm_Title, >+ Messages.LatencyView_Dialogs_DeleteEvents_Confirm_Message + "\n\n" + deletePairs); //$NON-NLS-1$ >+ >+ if (confirmDeletion) { >+ // Remove the events starting from the end of the list, otherwise the TableItem elements will lose >+ // their index from the table and may trigger an exception when removing an index that is no longer >+ // valid. >+ for (int i = selectedIndices.length - 1; i >= 0; i--) { >+ int selectedIndex = selectedIndices[i]; >+ EventMatcher.getInstance().removeMatch(fEventStartTypes.get(selectedIndex), fEventEndTypes.get(selectedIndex)); >+ >+ fTable.remove(selectedIndex); >+ >+ // Update the list of events >+ fEventStartTypes.remove(selectedIndex); >+ fEventEndTypes.remove(selectedIndex); >+ } >+ >+ // Save the events pairs in the settings file so it can be retrieved in the next session >+ saveMatchPairs(fEventStartTypes, fEventEndTypes); >+ >+ fTable.setItemCount(fEventStartTypes.size()); >+ >+ TableItem[] newItems = fTable.getItems(); >+ fTable.removeAll(); >+ for (int i = 0; i < newItems.length; i++) { >+ TableItem item = new TableItem(fTable, SWT.RIGHT); >+ >+ String max = String.valueOf(fEventStartTypes.size()); >+ String number = formatListNumber(i + 1, max.length()); >+ >+ String[] columns = { number, fEventStartTypes.get(i), fEventEndTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ fRedrawGraphs = true; >+ } >+ } >+ }); >+ >+ // Create the "Close" button >+ Button closeButton = createButton(parent, CANCEL, Messages.LatencyView_Dialogs_AddEvents_Buttons_Close, false); >+ closeButton.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ // Remember the user's list >+ saveMatchPairs(fEventStartTypes, fEventEndTypes); >+ >+ setReturnCode(CANCEL); >+ >+ if (fRedrawGraphs == true) >+ redrawGraphs(); >+ >+ close(); >+ } >+ }); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/ListDialog.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/ListDialog.java >new file mode 100644 >index 0000000..fd99352 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/ListDialog.java >@@ -0,0 +1,252 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new messages file, fixed warnings >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.dialogs; >+ >+import java.util.Vector; >+ >+import org.eclipse.jface.dialogs.MessageDialog; >+import org.eclipse.linuxtools.lttng.core.latency.analyzer.EventMatcher; >+import org.eclipse.linuxtools.lttng.core.util.EventsPair; >+import org.eclipse.linuxtools.lttng.ui.views.latency.Messages; >+import org.eclipse.swt.SWT; >+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.Control; >+import org.eclipse.swt.widgets.Event; >+import org.eclipse.swt.widgets.Listener; >+import org.eclipse.swt.widgets.Shell; >+import org.eclipse.swt.widgets.Table; >+import org.eclipse.swt.widgets.TableColumn; >+import org.eclipse.swt.widgets.TableItem; >+ >+/** >+ * <b><u>ListDialog</u></b> >+ * <p> >+ * List dialog, shows the list of start/end event pairs. >+ * >+ * @author Philippe Sawicki >+ */ >+public class ListDialog extends AbstractDialog { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * The dialog's table. >+ */ >+ protected Table fTable; >+ >+ /** >+ * Start event types. >+ */ >+ protected Vector<String> fEventStartTypes; >+ >+ /** >+ * End event types. >+ */ >+ protected Vector<String> fEventEndTypes; >+ >+ /** >+ * Table columns >+ */ >+ protected TableColumn[] fColumns; >+ >+ /** >+ * Column names (header titles). >+ */ >+ protected static final String[] COLUMN_NAMES = { "#", Messages.LatencyView_Dialogs_ListEvents_Columns_Trigger, Messages.LatencyView_Dialogs_ListEvents_Columns_End }; //$NON-NLS-1$ >+ >+ /** >+ * Column widths. >+ */ >+ protected static final int[] COLUMN_WIDTHS = { 25, 250, 250 }; >+ >+ /** >+ * The table style. >+ */ >+ protected int fStyle; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param parentShell >+ * The parent shell. >+ * @param title >+ * The dialog's window title. >+ * @param message >+ * The dialog's window message. >+ */ >+ public ListDialog(Shell parentShell, String title, String message) { >+ super(parentShell, title, message); >+ >+ // Set the table style >+ fStyle = SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL; >+ >+ // Get the list of start and end types from the EventMatcher >+ EventsPair pair = getMatchPairs(); >+ fEventStartTypes = pair.getFirst(); >+ fEventEndTypes = pair.getSecond(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Creates the table's column (i.e. the table header). >+ */ >+ protected void createColumns() { >+ fColumns = new TableColumn[COLUMN_NAMES.length]; >+ for (int i = 0; i < COLUMN_NAMES.length; i++) { >+ fColumns[i] = new TableColumn(fTable, SWT.LEFT); >+ fColumns[i].setText(COLUMN_NAMES[i]); >+ fColumns[i].setWidth(COLUMN_WIDTHS[i]); >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.AbstractDialog#createDialogArea(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected Control createDialogArea(Composite parent) { >+ GridLayout layout = new GridLayout(1, true); >+ parent.setLayout(layout); >+ >+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); >+ fTable = new Table(parent, fStyle); >+ fTable.setLayoutData(layoutData); >+ >+ // Some cosmetic enhancements >+ fTable.setHeaderVisible(true); >+ fTable.setLinesVisible(true); >+ >+ createColumns(); >+ >+ for (int i = 0; i < fEventStartTypes.size(); i++) { >+ TableItem item = new TableItem(fTable, SWT.RIGHT); >+ >+ String max = String.valueOf(fEventStartTypes.size()); >+ String number = formatListNumber(i + 1, max.length()); >+ >+ String[] columns = { number, fEventStartTypes.get(i), fEventEndTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ return parent; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.dialogs.AbstractDialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) >+ */ >+ @Override >+ protected void createButtonsForButtonBar(Composite parent) { >+ GridData gridData = new GridData(); >+ gridData.verticalAlignment = GridData.FILL; >+ gridData.horizontalSpan = 1; >+ gridData.grabExcessHorizontalSpace = true; >+ gridData.grabExcessVerticalSpace = true; >+ gridData.horizontalAlignment = SWT.RIGHT; >+ >+ parent.setLayoutData(gridData); >+ >+ // Create the "Reset" button >+ Button resetButton = createButton(parent, RESET, Messages.LatencyView_Dialogs_ListEvents_Buttons_Reset, false); >+ resetButton.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ boolean confirmDeletion = MessageDialog.openQuestion(getShell(), Messages.LatencyView_Dialogs_ListEvents_Confirm_Title, >+ Messages.LatencyView_Dialogs_ListEvents_Confirm_Message); >+ >+ if (confirmDeletion) { >+ EventMatcher.getInstance().resetMatches(); >+ >+ fTable.removeAll(); >+ >+ Vector<String> defaultStarts = new Vector<String>(); >+ Vector<String> defaultEnds = new Vector<String>(); >+ >+ defaultStarts.add(EventMatcher.PAGE_FAULT_GET_USER_ENTRY); >+ defaultEnds.add(EventMatcher.PAGE_FAULT_GET_USER_EXIT); >+ defaultStarts.add(EventMatcher.TASKLET_LOW_ENTRY); >+ defaultEnds.add(EventMatcher.TASKLET_LOW_EXIT); >+ defaultStarts.add(EventMatcher.PAGE_FAULT_ENTRY); >+ defaultEnds.add(EventMatcher.PAGE_FAULT_EXIT); >+ defaultStarts.add(EventMatcher.SYSCALL_ENTRY); >+ defaultEnds.add(EventMatcher.SYSCALL_EXIT); >+ defaultStarts.add(EventMatcher.IRQ_ENTRY); >+ defaultEnds.add(EventMatcher.IRQ_EXIT); >+ defaultStarts.add(EventMatcher.READ); >+ defaultEnds.add(EventMatcher.WRITE); >+ defaultStarts.add(EventMatcher.OPEN); >+ defaultEnds.add(EventMatcher.CLOSE); >+ defaultStarts.add(EventMatcher.BUFFER_WAIT_START); >+ defaultEnds.add(EventMatcher.BUFFER_WAIT_END); >+ defaultStarts.add(EventMatcher.START_COMMIT); >+ defaultEnds.add(EventMatcher.END_COMMIT); >+ defaultStarts.add(EventMatcher.WAIT_ON_PAGE_START); >+ defaultEnds.add(EventMatcher.WAIT_ON_PAGE_END); >+ >+ saveMatchPairs(defaultStarts, defaultEnds); >+ >+ for (int i = 0; i < defaultStarts.size(); i++) { >+ EventMatcher.getInstance().addMatch(defaultStarts.get(i), defaultEnds.get(i)); >+ } >+ >+ // Get the list of start and end types from the EventMatcher >+ EventsPair pair = getMatchPairs(); >+ fEventStartTypes = pair.getFirst(); >+ fEventEndTypes = pair.getSecond(); >+ >+ for (int i = 0; i < fEventStartTypes.size(); i++) { >+ TableItem item = new TableItem(fTable, SWT.RIGHT); >+ >+ String max = String.valueOf(fEventStartTypes.size()); >+ String number = formatListNumber(i + 1, max.length()); >+ >+ String[] columns = { number, fEventStartTypes.get(i), fEventEndTypes.get(i) }; >+ >+ item.setText(columns); >+ } >+ >+ fTable.setItemCount(fEventStartTypes.size()); >+ >+ fRedrawGraphs = true; >+ } >+ } >+ }); >+ >+ // Create the "Close" button >+ Button closeButton = createButton(parent, CANCEL, Messages.LatencyView_Dialogs_ListEvents_Buttons_Close, false); >+ closeButton.addListener(SWT.Selection, new Listener() { >+ @Override >+ public void handleEvent(Event event) { >+ setReturnCode(CANCEL); >+ >+ if (fRedrawGraphs == true) >+ redrawGraphs(); >+ >+ close(); >+ } >+ }); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseListener.java >new file mode 100644 >index 0000000..3d3b1a0 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseListener.java >@@ -0,0 +1,80 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.swt.events.MouseEvent; >+import org.eclipse.swt.events.MouseListener; >+ >+/** >+ * <b><u>AbstractMouseListener</u></b> >+ * <p> >+ */ >+public abstract class AbstractMouseListener implements MouseListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Mouse x-coordinate. >+ */ >+ protected int fMouseX; >+ >+ /** >+ * Mouse y-coordinate. >+ */ >+ protected int fMouseY; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent) >+ */ >+ @Override >+ public void mouseDoubleClick(MouseEvent e) { >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent) >+ */ >+ @Override >+ public void mouseDown(MouseEvent e) { >+ fMouseX = e.x; >+ fMouseY = e.y; >+ display(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent) >+ */ >+ @Override >+ public void mouseUp(MouseEvent e) { >+ } >+ >+ /** >+ * Callback to display information at the current x-y position >+ */ >+ protected abstract void display(); >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseTrackListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseTrackListener.java >new file mode 100644 >index 0000000..b4e53fe >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseTrackListener.java >@@ -0,0 +1,77 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Changed implemented interface to MouseTraceListener >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.swt.events.MouseEvent; >+import org.eclipse.swt.events.MouseTrackListener; >+ >+/** >+ * <b><u>AbstractMouseListener</u></b> >+ * <p> >+ * AbstractMouseListener, base class for the canvas mouse listener. >+ * >+ * @author Philippe Sawicki >+ */ >+public abstract class AbstractMouseTrackListener implements MouseTrackListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Mouse x-coordinate. >+ */ >+ protected int fMouseX; >+ /** >+ * Mouse y-coordinate. >+ */ >+ protected int fMouseY; >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent) >+ */ >+ @Override >+ public void mouseEnter(MouseEvent event) { >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent) >+ */ >+ @Override >+ public void mouseExit(MouseEvent event) { >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent) >+ */ >+ @Override >+ public void mouseHover(MouseEvent event) { >+ fMouseX = event.x; >+ fMouseY = event.y; >+ display(); >+ } >+ >+ /** >+ * Tooltip display callback. >+ */ >+ protected abstract void display(); >+ >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractPaintListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractPaintListener.java >new file mode 100644 >index 0000000..ae7be22 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractPaintListener.java >@@ -0,0 +1,735 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design, display improvements >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.Config; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.events.PaintEvent; >+import org.eclipse.swt.events.PaintListener; >+import org.eclipse.swt.graphics.Color; >+import org.eclipse.swt.graphics.Font; >+import org.eclipse.swt.graphics.GC; >+import org.eclipse.swt.graphics.Image; >+import org.eclipse.swt.graphics.Point; >+import org.eclipse.swt.graphics.Rectangle; >+import org.eclipse.swt.widgets.Display; >+ >+/** >+ * <b><u>AbstractPaintListener</u></b> >+ * <p> >+ * Abstract paint listener. Draws the graphs on the view canvas. >+ * >+ * @author Philippe Sawicki >+ */ >+public abstract class AbstractPaintListener implements PaintListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Default colors and fonts >+ */ >+ protected final Color DEFAULT_DATA_COLOR = new Color(Display.getDefault(), 74, 112, 139); >+ protected final static Color DEFAULT_LABEL_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_BLACK); >+ protected final static Color DEFAULT_TEXT_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY); >+ protected final static Color DEFAULT_DATA_BACKGROUND_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE); >+ protected final static Color DEFAULT_CURRENT_EVENT_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_RED); >+ >+ protected final Font DEFAULT_TITLE_FONT = new Font(Display.getDefault(), "Arial", 10, SWT.BOLD); //$NON-NLS-1$ >+ protected final Font DEFAULT_VALUES_FONT = new Font(Display.getDefault(), "Arial", 7, SWT.NORMAL); //$NON-NLS-1$ >+ protected final Font DEFAULT_LABEL_FONT = new Font(Display.getDefault(), "Arial", 8, SWT.NORMAL); //$NON-NLS-1$ >+ >+ /** >+ * A reference to the listener's view. >+ */ >+ protected AbstractViewer fViewer; >+ >+ /** >+ * Graph title >+ */ >+ protected String fGraphTitle; >+ >+ /** >+ * X-axis label. >+ */ >+ protected String fXAxisLabel; >+ >+ /** >+ * Y-axis label. >+ */ >+ protected String fYAxisLabel; >+ >+ /** >+ * Horizontal offset for the x-axis label. >+ */ >+ protected int fXAxisLabelOffset; >+ >+ /** >+ * Vertical offset for the horizontal axis offset. >+ */ >+ protected int fHorizontalAxisYOffset = 20; >+ >+ /** >+ * Graph padding. >+ */ >+ protected int fPadding = Config.GRAPH_PADDING; >+ >+ /** >+ * Graph client area. >+ */ >+ protected Rectangle fClientArea = new Rectangle(0, 0, 1, 1); >+ >+ /** >+ * Foreground color. >+ */ >+ protected Color fForegroundColor; >+ >+ /** >+ * Background color. >+ */ >+ protected Color fBackgroundColor; >+ >+ /** >+ * Data plotting color. >+ */ >+ protected Color fDataColor; >+ >+ /** >+ * Axis label color. >+ */ >+ protected Color fLabelColor; >+ >+ /** >+ * Text color. >+ */ >+ protected Color fTextColor; >+ >+ /** >+ * Data background color. >+ */ >+ protected Color fDataBackgroundColor; >+ >+ /** >+ * Color for current event time line. >+ */ >+ protected Color fCurrentEventColor; >+ >+ /** >+ * Original canvas font. >+ */ >+ protected Font fOriginalFont; >+ >+ /** >+ * Font for the title of the graph. >+ */ >+ protected Font fTitleFont; >+ >+ /** >+ * Font for the values on the horizontal and vertical axis. >+ */ >+ protected Font fValuesFont; >+ >+ /** >+ * Font for the horizontal and vertical labels. >+ */ >+ protected Font fLabelFont; >+ >+ /** >+ * Horizontal offset for the axis arrow. >+ */ >+ protected final int ARROW_DELTA_X = 10; >+ >+ /** >+ * Vertical offset for the axis arrow. >+ */ >+ protected final int ARROW_DELTA_Y = 4; >+ >+ /** >+ * Max horizontal distance between ticks. >+ */ >+ protected final int MAX_WIDTH_BETWEEN_TICKS = 40; >+ >+ /** >+ * Max vertical distance between ticks. >+ */ >+ protected final int MAX_HEIGHT_BETWEEN_TICKS = 30; >+ >+ /** >+ * Max characters that can be displayed on the vertical axis. >+ */ >+ protected final int MAX_CHAR_VERTICAL_DISPLAY = 5; >+ >+ /** >+ * Draw label each "drawLabelEachNTicks_" ticks. >+ */ >+ protected int fDrawLabelEachNTicks = 1; >+ >+ /** >+ * Image drawn on the canvas. >+ */ >+ protected Image fImage; >+ >+ /** >+ * Paint canvas, where the values are plotted. >+ */ >+ protected GC fAxisImage; >+ >+ /** >+ * Is the paint listener initialized ? >+ */ >+ protected boolean fInitialized = false; >+ >+ /** >+ * Draw area. >+ */ >+ protected Rectangle fDrawArea; >+ >+ /** >+ * Right padding (in pixels). >+ */ >+ protected int fPaddingRight = Config.GRAPH_PADDING; >+ >+ /** >+ * Top padding (in pixels). >+ */ >+ protected int fPaddingTop = Config.GRAPH_PADDING; >+ >+ /** >+ * Vertical axis offset (in pixels). >+ */ >+ protected int fVerticalAxisOffset = 2 * Config.GRAPH_PADDING; >+ >+ /** >+ * Vertical axis factor for values (10^delta). When values larger than MAX_CHAR_VERTICAL_DISPLAY. >+ */ >+ protected int fDelta = 0; >+ >+ /** >+ * The barWidth of a bar >+ */ >+ protected int fBarWith = Config.DEFAULT_HISTOGRAM_BAR_WIDTH; >+ >+ /** >+ * Minimum value on horizontal axis >+ */ >+ protected long fXMin = -1; >+ >+ /** >+ * Maximum value on horizontal axis >+ */ >+ protected long fXMax = -1; >+ >+ /** >+ * Minimum value on vertical axis >+ */ >+ protected long fYMin = -1; >+ >+ /** >+ * Maximum value on vertical axis >+ */ >+ protected long fYMax = -1; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the listener's view. >+ */ >+ public AbstractPaintListener(AbstractViewer view) { >+ fViewer = view; >+ fDataColor = DEFAULT_DATA_COLOR; >+ fLabelColor = DEFAULT_LABEL_COLOR; >+ fTextColor = DEFAULT_TEXT_COLOR; >+ fDataBackgroundColor = DEFAULT_DATA_BACKGROUND_COLOR; >+ fCurrentEventColor = DEFAULT_CURRENT_EVENT_COLOR; >+ >+ fTitleFont = DEFAULT_TITLE_FONT; >+ fValuesFont = DEFAULT_VALUES_FONT; >+ fLabelFont = DEFAULT_LABEL_FONT; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Returns the draw area height. >+ * @return The draw area height. >+ */ >+ public double getHeight() { >+ return (fClientArea.height - 2.0 * fPadding - fHorizontalAxisYOffset - fPaddingTop); >+ } >+ >+ /** >+ * Returns the histogram's draw area width. >+ * @return The histogram's draw area width. >+ */ >+ public double getWidth() { >+ return (fClientArea.width - 2.0 * fPadding - fVerticalAxisOffset - fPaddingRight); // width of the plot area; >+ } >+ >+ /** >+ * Returns the histogram's draw area padding. >+ * @return The histogram's draw area padding. >+ */ >+ public int getPadding() { >+ return fPadding; >+ } >+ >+ /** >+ * Returns the histogram's draw area top padding. >+ * @return The histogram's draw area top padding. >+ */ >+ public int getPaddingTop() { >+ return fPaddingTop; >+ } >+ >+ /** >+ * Returns the histogram's vertical axis offset. >+ * @return The histogram's vertical axis offset. >+ */ >+ public int getVerticalAxisOffset() { >+ return fVerticalAxisOffset; >+ } >+ >+ /** >+ * Returns the histogram's horizontal axis offset. >+ * @return The histogram's horizontal axis offset. >+ */ >+ public int getHorizontalAxisYOffset() { >+ return fHorizontalAxisYOffset; >+ } >+ >+ /** >+ * Returns the horizontal minimum value >+ * @return The horizontal minimum value. >+ */ >+ public long getXMin() { >+ return fXMin; >+ } >+ >+ /** >+ * Returns the horizontal maximum value >+ * @return The horizontal maximum value. >+ */ >+ public long getXMax() { >+ return fXMax; >+ } >+ >+ /** >+ * Returns the horizontal minimum value >+ * @return The horizontal minimum value. >+ */ >+ public long getYMin() { >+ return fYMin; >+ } >+ >+ /** >+ * Returns the vertical maximum value >+ * @return The vertical maximum value. >+ */ >+ public long getYMax() { >+ return fYMax; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Disposes local resources (e.g. colors or fonts) >+ */ >+ public void dispose() { >+ DEFAULT_DATA_COLOR.dispose(); >+ DEFAULT_TITLE_FONT.dispose(); >+ DEFAULT_VALUES_FONT.dispose(); >+ DEFAULT_LABEL_FONT.dispose(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent) >+ */ >+ @Override >+ public void paintControl(PaintEvent e) { >+ fClientArea = fViewer.getClientArea(); >+ >+ fForegroundColor = e.gc.getForeground(); >+ fBackgroundColor = e.gc.getBackground(); >+ fOriginalFont = e.gc.getFont(); >+ >+ scale(); >+ >+ if (!fInitialized) { >+ fImage = new Image(Display.getDefault(), fViewer.getBounds()); >+ >+ fAxisImage = new GC(fImage); >+ >+ fAxisImage.setForeground(fForegroundColor); >+ fAxisImage.setBackground(fBackgroundColor); >+ fAxisImage.fillRectangle(fImage.getBounds()); >+ >+ fInitialized = true; >+ } >+ >+ paintGraphTitle(); >+ paintBackground(); >+ paintHorizontalAxis(); >+ paintVerticalAxis(); >+ paintContent(); >+ >+ e.gc.drawImage(fImage, 0, 0); >+ } >+ >+ /** >+ * Paints the title of the graph. >+ */ >+ public void paintGraphTitle() { >+ if (fGraphTitle != null) { >+ fAxisImage.setFont(fTitleFont); >+ fAxisImage.setForeground(fLabelColor); >+ fAxisImage.setBackground(fBackgroundColor); >+ >+ int zoomFactor = fViewer.getZoomFactor() / fViewer.getZoomIncrement() + 1; >+ int labelWidth = fAxisImage.stringExtent(fGraphTitle).x; >+ // Draws the zoom factor in the title only if there is one >+ if (fViewer.getZoomFactor() > 1) >+ fAxisImage.drawText(fGraphTitle + " (" + zoomFactor + "x)", (fViewer.getBounds().width - fPadding - labelWidth) / 2, 0); //$NON-NLS-1$ //$NON-NLS-2$ >+ else >+ fAxisImage.drawText(fGraphTitle, (fViewer.getBounds().width - fPadding - labelWidth) / 2, 0); >+ } >+ } >+ >+ /** >+ * Paints the background of the draw area. >+ */ >+ public void paintBackground() { >+ fAxisImage.setBackground(fDataBackgroundColor); >+ >+ fAxisImage.fillRectangle(fPadding + fVerticalAxisOffset, fPadding + fPaddingTop, (int)getWidth() + 1, (int)getHeight()); >+ } >+ >+ /** >+ * Paints the horizontal axis. >+ */ >+ public void paintHorizontalAxis() { >+ fAxisImage.setForeground(fForegroundColor); >+ >+ int y = fClientArea.height - fPadding - fHorizontalAxisYOffset; >+ >+ fAxisImage.drawLine(fClientArea.x + fPadding + fVerticalAxisOffset, y, fClientArea.width - fPadding, y); >+ >+ paintHorizontalArrow(fClientArea.width - fPadding, y); >+ // Draw the axis graphic details only if there are some data points (i.e. do not draw the axis graphic details >+ // if the window timerange is so small that no latency can be computed, or if there are no matching events in >+ // the timerange (for example, when an experiment has many traces with a large time gap between the logged >+ // events sets). >+ if (fXMin != Long.MAX_VALUE && fXMax != Long.MIN_VALUE && fXMin != fXMax) { >+ paintHorizontalTicks(y); >+ paintHorizontalAxisValues(y + 30); >+ } >+ paintHorizontalAxisLabel(y + fHorizontalAxisYOffset - 5); >+ } >+ >+ /** >+ * Paints the vertical axis. >+ */ >+ public void paintVerticalAxis() { >+ fAxisImage.setForeground(fForegroundColor); >+ >+ int x = fClientArea.x + fPadding + fVerticalAxisOffset; >+ >+ fAxisImage.drawLine(x, fPadding, x, fClientArea.height - fPadding - fHorizontalAxisYOffset); >+ >+ paintVerticalArrow(x, fClientArea.y + fPadding); >+ // Draw the axis graphic details only if there are some data points (i.e. do not draw the axis graphic details >+ // if the window timerange is so small that no latency can be computed, or if there are no matching events in >+ // the timerange (for example, when an experiment has many traces with a large time gap between the logged >+ // events sets). >+ if (fXMin != Long.MAX_VALUE && fXMax != Long.MIN_VALUE && fXMin != fXMax) { >+ paintVerticalTicks(x); >+ paintVerticalAxisValues(x); >+ } >+ paintVerticalAxisLabel(x); >+ } >+ >+ /** >+ * Paints the arrow on the horizontal axis. >+ * @param x >+ * The x-coordinate of the point where the arrow points. >+ * @param y >+ * The y-coordinate of the point where the arrow points. >+ */ >+ public void paintHorizontalArrow(int x, int y) { >+ // Arrow top line >+ fAxisImage.drawLine(x - ARROW_DELTA_X, y - ARROW_DELTA_Y, x, y); >+ // Arrow bottom line >+ fAxisImage.drawLine(x - ARROW_DELTA_X, y + ARROW_DELTA_Y, x, y); >+ } >+ >+ /** >+ * Paints the arrow on the vertical axis. >+ * @param x >+ * The x-coordinate of the point where the arrow points. >+ * @param y >+ * The y-coordinate of the point where the arrow points. >+ */ >+ public void paintVerticalArrow(int x, int y) { >+ // Arrow left line >+ fAxisImage.drawLine(x - ARROW_DELTA_Y, y + ARROW_DELTA_X, x, y); >+ // Arrow right line >+ fAxisImage.drawLine(x + ARROW_DELTA_Y, y + ARROW_DELTA_X, x, y); >+ } >+ >+ /** >+ * Paints the horizontal ticks. >+ * @param y >+ * The y coordinate where to draw the axis. >+ */ >+ public void paintHorizontalTicks(int y) { >+ if (fXMin >= 0L && fXMin >= 0L) { >+ int nbTicks = (int)(getWidth()) / MAX_WIDTH_BETWEEN_TICKS + 1; >+ >+ for (int i = 0; i < nbTicks; i++) { >+ if (i % fDrawLabelEachNTicks == 0) { >+ int x = i * MAX_WIDTH_BETWEEN_TICKS + fPadding + fVerticalAxisOffset; >+ fAxisImage.drawLine(x, y, x, y + 3); >+ } >+ } >+ } >+ } >+ >+ /** >+ * Paints the horizontal axis values. >+ * @param y >+ * The y coordinate where to draw the axis. >+ */ >+ public void paintHorizontalAxisValues(int y) { >+ if (fXMin >= 0L && fXMax >= 0L) { >+ fAxisImage.setForeground(fTextColor); >+ fAxisImage.setBackground(fBackgroundColor); >+ >+ double width = getWidth(); >+ int nbTicks = ((int)getWidth()) / MAX_WIDTH_BETWEEN_TICKS + 1; >+ >+ for (int i = 0; i < nbTicks; i++) { >+ if (i % fDrawLabelEachNTicks == 0) { >+ int x = i * MAX_WIDTH_BETWEEN_TICKS + fPadding + fVerticalAxisOffset; >+ >+ long currentValue = (i * MAX_WIDTH_BETWEEN_TICKS)* (long)((fXMax - fXMin) / width) + fXMin; >+ String currentLabel = formatStringForHorizontalAxis(currentValue); >+ >+ fAxisImage.setFont(fValuesFont); >+ fAxisImage.drawText(currentLabel, x, y - 24); >+ } >+ } >+ } >+ } >+ >+ /** >+ * Paints the horizontal axis label. >+ * @param y >+ * The y-coordinate where to draw the label. >+ */ >+ public void paintHorizontalAxisLabel(int y) { >+ if (fXAxisLabel != null) { >+ fAxisImage.setFont(fLabelFont); >+ fAxisImage.setForeground(fLabelColor); >+ >+ int labelWidth = fAxisImage.stringExtent(fXAxisLabel).x; >+ >+ fAxisImage.drawText(fXAxisLabel, fClientArea.width - fPadding - labelWidth, y); >+ } >+ } >+ >+ /** >+ * Paints the vertical axis ticks. >+ * @param x >+ * The x-coordinate where to draw the ticks. >+ */ >+ public void paintVerticalTicks(int x) { >+ if (fYMin != 0L && fYMin != 0L) { >+ int nbTicks = (int)(getHeight() / MAX_HEIGHT_BETWEEN_TICKS + 1); >+ >+ for (int i = 0; i < nbTicks; i++) { >+ int y = fClientArea.height - fPadding - fHorizontalAxisYOffset - i * MAX_HEIGHT_BETWEEN_TICKS; >+ fAxisImage.drawLine(x - 3, y, x, y); >+ } >+ } >+ } >+ >+ /** >+ * Paints the vertical axis values. >+ * @param x >+ * The x-coordinate where to draw the values. >+ */ >+ public void paintVerticalAxisValues(int x) { >+ if (fYMin >= 0L && fYMax >= 0L) { >+ fAxisImage.setForeground(fTextColor); >+ fAxisImage.setBackground(fBackgroundColor); >+ >+ double height = getHeight(); >+ int nbTicks = (int)(height / MAX_HEIGHT_BETWEEN_TICKS + 1); >+ >+ // System.out.println("nbTicks = " + nbTicks); >+ >+ for (int i = 0; i < nbTicks; i++) { >+ int y = fClientArea.height - fPadding - fHorizontalAxisYOffset - i * MAX_HEIGHT_BETWEEN_TICKS; >+ >+ long currentValue = (i * MAX_HEIGHT_BETWEEN_TICKS)* (long)((fYMax - fYMin) / height) + fYMin; >+ String currentLabel = formatStringForVerticalAxis(currentValue); >+ >+ fAxisImage.setFont(fValuesFont); >+ >+ Point textDimensions = fAxisImage.stringExtent(currentLabel); >+ fAxisImage.drawText(currentLabel, x - textDimensions.x - 5, y - textDimensions.y / 2); >+ } >+ } >+ } >+ >+ /** >+ * Increases the bar width. >+ */ >+ public void increaseBarWitdh() { >+ fBarWith = fBarWith << 1; >+ if (fBarWith > Config.MAX_HISTOGRAM_BAR_WIDTH) { >+ fBarWith = Config.MAX_HISTOGRAM_BAR_WIDTH; >+ } >+ } >+ >+ /** >+ * Decreases the bar width. >+ */ >+ public void decreaseBarWitdh() { >+ fBarWith = fBarWith >> 1; >+ if (fBarWith < Config.MIN_HISTOGRAM_BAR_WIDTH) { >+ fBarWith = Config.MIN_HISTOGRAM_BAR_WIDTH; >+ } >+ } >+ >+ >+ /** >+ * Paints the vertical axis label. >+ * @param x >+ * The x-coordinate where to draw the label. >+ */ >+ public void paintVerticalAxisLabel(int x) { >+ if (fYAxisLabel != null) { >+ fAxisImage.setFont(fLabelFont); >+ fAxisImage.setForeground(fLabelColor); >+ fAxisImage.setBackground(fBackgroundColor); >+ >+ if (fDelta >= 1) >+ fAxisImage.drawText(fYAxisLabel + " (x10^" + fDelta + ")", x + 10, fHorizontalAxisYOffset - 5); //$NON-NLS-1$//$NON-NLS-2$ >+ else >+ fAxisImage.drawText(fYAxisLabel, x + 10, fPadding); >+ } >+ } >+ >+ /** >+ * Adds points to the graph and draws them to the canvas. >+ * @param points >+ * The buffer of points to draw. >+ * @param nbPoints >+ * The number of points in the buffer. >+ */ >+ abstract public String formatToolTipLabel(int x, int y); >+ >+ /** >+ * Method to be implemented to scale the model data to the actual screen size. >+ */ >+ abstract public void scale(); >+ >+ /** >+ * Called for drawing elements after points are added to the graph. >+ */ >+ abstract public void paintContent(); >+ >+ /** >+ * Clears the image and prepares it for redrawing. >+ */ >+ public void clear() { >+ fInitialized = false; >+ fXMin = -1; >+ fXMax = -1; >+ fYMin = -1; >+ fYMax = -1; >+ } >+ >+ /** >+ * Draw horizontal label each "nbTicks" ticks. >+ * @param nbTicks >+ * The draw interval. >+ */ >+ public void setDrawLabelEachNTicks(int nbTicks) { >+ fDrawLabelEachNTicks = nbTicks; >+ } >+ >+ /** >+ * Sets the title of the graph. >+ * @param graphTitle >+ * The title of the graph. >+ */ >+ public void setGraphTitle(String graphTitle) { >+ fGraphTitle = graphTitle; >+ } >+ >+ /** >+ * Sets the horizontal axis label. >+ * @param xAxisLabel >+ * The horizontal axis label. >+ * @param offset >+ * The horizontal axis draw offset (in pixels). >+ */ >+ public void setXAxisLabel(String xAxisLabel, int offset) { >+ fXAxisLabel = xAxisLabel; >+ fXAxisLabelOffset = offset; >+ } >+ >+ /** >+ * Sets the vertical axis label. >+ * @param yAxisLabel >+ * The vertical axis label. >+ */ >+ public void setYAxisLabel(String yAxisLabel) { >+ fYAxisLabel = yAxisLabel; >+ } >+ >+ /** >+ * Returns a string representing the given value. >+ * >+ * @param value >+ * The numeric value to convert to String. >+ * @return The String-formatted value. >+ */ >+ public String formatStringForHorizontalAxis(long value) { >+ return String.valueOf(value); >+ } >+ >+ /** >+ * Returns a string representing the given value. >+ * >+ * @param value >+ * The numeric value to convert to String. >+ * @return The String-formatted value. >+ */ >+ public String formatStringForVerticalAxis(long value) { >+ return String.valueOf(value); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphMouseListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphMouseListener.java >new file mode 100644 >index 0000000..5d6cb75 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphMouseListener.java >@@ -0,0 +1,70 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.GraphViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.LatencyGraphModel; >+ >+/** >+ * <b><u>GraphMouseListener</u></b> >+ * <p> >+ */ >+public class GraphMouseListener extends AbstractMouseListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * A reference to the observed view. >+ */ >+ protected GraphViewer fView; >+ >+ /** >+ * A reference to the HistogramPaintListener. >+ */ >+ protected GraphPaintListener fGraph; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the observed view. >+ * @param histogramPaintListener >+ * A reference to the histogram's paintListener. >+ */ >+ public GraphMouseListener(GraphViewer view, GraphPaintListener graphPaintListener) { >+ fView = view; >+ fGraph = graphPaintListener; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractMouseListener#display() >+ */ >+ @Override >+ protected void display() { >+ long currentTime = fGraph.getCurrentTimeFromHorizontalValue(fMouseX); >+ ((LatencyGraphModel)fView.getModel()).setCurrentEventNotifyListeners(currentTime); >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphPaintListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphPaintListener.java >new file mode 100644 >index 0000000..a6732c2 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphPaintListener.java >@@ -0,0 +1,227 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design, display improvements >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import java.text.DecimalFormat; >+ >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.BaseDistributionData; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramUtils; >+import org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.GraphViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.Config; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.GraphScaledData; >+import org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphDataModel; >+ >+/** >+ * <b><u>GraphPaintListener</u></b> >+ * <p> >+ * Graph paint listener. >+ * >+ * @author Philippe Sawicki >+ */ >+public class GraphPaintListener extends AbstractPaintListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Scaled data from data model >+ */ >+ protected GraphScaledData fScaledData; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param viewer >+ * A reference to the listener's viewer. >+ */ >+ public GraphPaintListener(AbstractViewer view) { >+ super(view); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#scale() >+ */ >+ @Override >+ public void scale() { >+ >+ // width of the plot area >+ double width = getWidth(); >+ // height of the plot area >+ double height = getHeight(); >+ >+ IGraphDataModel model = ((GraphViewer)fViewer).getModel(); >+ fScaledData = model.scaleTo((int)width, (int)height, fBarWith); >+ >+ fXMin = fScaledData.getHorFirstBucketTime() > 0 ? fScaledData.getHorFirstBucketTime() : 0; >+ fXMax = 0; >+ if (fScaledData.getHorLastBucket() > 0) { >+ fXMax = fScaledData.getHorBucketEndTime(fScaledData.getHorNbBuckets() - 1); >+ } >+ >+ fYMin = fScaledData.getVerFirstBucketTime() > 0 ? fScaledData.getVerFirstBucketTime() : 0; >+ fYMax = 0; >+ if (fScaledData.getVerLastBucket() > 0) { >+ fYMax = fScaledData.getVerBucketEndTime(fScaledData.getVerNbBuckets() - 1); >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#paintContent() >+ */ >+ @Override >+ public void paintContent() { >+ if (fXMin >= 0 && fXMax >= 0 && fYMin >= 0 && fYMax >= 0 && fScaledData != null) { >+ >+ fAxisImage.setForeground(fDataColor); >+ fAxisImage.setBackground(fDataColor); >+ >+ double height = getHeight(); >+ >+ int xLen = fScaledData.getHorNbBuckets(); >+ int yLen = fScaledData.getVerNbBuckets(); >+ >+ int barWidth = fScaledData.getBarWidth(); >+ >+ for (int i = 0; i < xLen; i++) { >+ for (int j = 0; j < yLen; j++) { >+ if (fScaledData.getEventCount(i, j) > 0) { >+ >+ double x = fPadding + i * barWidth + fVerticalAxisOffset + 1; >+ double y = fPadding + fPaddingTop + height - j * barWidth; >+ >+ // Avoid over-drawing background area >+ int yBarWidth = fBarWith; >+ if (y - yBarWidth < fPadding + fPaddingTop) { >+ yBarWidth = (int) (y - fPadding - fPaddingTop); >+ } >+ int xBarWidth = fBarWith; >+ if(x + xBarWidth > fClientArea.width - fPadding - fPaddingRight) { >+ xBarWidth = (int)(fClientArea.width - fPadding - fPaddingRight - x); >+ } >+ fAxisImage.fillRectangle((int) x, (int) y - (int) yBarWidth, (int) xBarWidth, (int) yBarWidth); >+ } >+ } >+ } >+ >+ if (fScaledData.isCurrentEventTimeValid()) { >+ // Draw vertical line >+ int index = fScaledData.getHorBucketIndex(fScaledData.getCurrentEventTime()); >+ >+ int x = fPadding + index * barWidth + fVerticalAxisOffset + 1; >+ fAxisImage.setForeground(fCurrentEventColor); >+ fAxisImage.setBackground(fCurrentEventColor); >+ fAxisImage.drawLine(x, fPadding + fPaddingTop, x, fClientArea.height - fPadding - fHorizontalAxisYOffset); >+ } >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#formatStringForVerticalAxis(long) >+ */ >+ @Override >+ public String formatStringForVerticalAxis(long value) { >+ DecimalFormat formatter = new DecimalFormat("0.0E0"); //$NON-NLS-1$ >+ return formatter.format(value); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#formatStringForHorizontalAxis(long) >+ */ >+ @Override >+ public String formatStringForHorizontalAxis(long value) { >+ return HistogramUtils.nanosecondsToString(value); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#formatToolTipLabel(int, int) >+ */ >+ @Override >+ public String formatToolTipLabel(int x, int y) { >+ >+ int index = getIndexFromHorizontalValue(x); >+ int yIndex = getIndexFromVerticalValue(y); >+ >+ if (index != BaseDistributionData.OUT_OF_RANGE_BUCKET && yIndex != BaseDistributionData.OUT_OF_RANGE_BUCKET) { >+ if (fScaledData.getEventCount(index, yIndex) > 0) { >+ StringBuffer buffer = new StringBuffer(); >+ buffer.append("Time Range in s = ["); //$NON-NLS-1$ >+ // TODO change Utility >+ long startTime = fScaledData.getHorBucketStartTime(index) > 0 ? fScaledData.getHorBucketStartTime(index) : 0; >+ buffer.append(HistogramUtils.nanosecondsToString(startTime)); >+ buffer.append(","); //$NON-NLS-1$ >+ buffer.append(HistogramUtils.nanosecondsToString(fScaledData.getHorBucketEndTime(index))); >+ buffer.append("]\n"); //$NON-NLS-1$ >+ buffer.append("Latency Range in s = ["); //$NON-NLS-1$ >+ long yStartTime = fScaledData.getVerBucketStartTime(yIndex) > 0 ? fScaledData.getVerBucketStartTime(yIndex) : 0; >+ buffer.append(HistogramUtils.nanosecondsToString(yStartTime)); >+ buffer.append(","); //$NON-NLS-1$ >+ buffer.append(HistogramUtils.nanosecondsToString(fScaledData.getVerBucketEndTime(yIndex))); >+ buffer.append("]\n"); //$NON-NLS-1$ >+ buffer.append("Latency count = "); //$NON-NLS-1$ >+ buffer.append(fScaledData.getEventCount(index, yIndex)); >+ return buffer.toString(); >+ } >+ } >+ return ""; //$NON-NLS-1$ >+ } >+ >+ public int getIndexFromHorizontalValue(int x) { >+ if (fScaledData != null) { >+ double barWidth = fScaledData.getBarWidth(); >+ >+ int index = (int) ((x - fPadding - fVerticalAxisOffset - 1) / barWidth); >+ if ((index >= 0) && (fScaledData.getHorNbBuckets() > index)) { >+ return index; >+ } >+ } >+ return BaseDistributionData.OUT_OF_RANGE_BUCKET; >+ } >+ >+ public int getIndexFromVerticalValue(int y) { >+ if (fScaledData != null) { >+ double barWidth = fScaledData.getBarWidth(); >+ double height = getHeight(); // height of the plot area >+ >+ int index = (int) ((height - (y - fPadding - fPaddingTop)) / barWidth); >+ if (index >= 0 && fScaledData.getVerNbBuckets() > index) { >+ return index; >+ } >+ } >+ return BaseDistributionData.OUT_OF_RANGE_BUCKET; >+ } >+ >+ public long getCurrentTimeFromHorizontalValue(int x) { >+ if (fXMin >= 0 && fXMax >= 0) { >+ int index = getIndexFromHorizontalValue(x); >+ if (index != BaseDistributionData.OUT_OF_RANGE_BUCKET) { >+ return fScaledData.getHorBucketStartTime(index); >+ } >+ } >+ return Config.INVALID_EVENT_TIME; >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/HistogramPaintListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/HistogramPaintListener.java >new file mode 100644 >index 0000000..0241f64 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/HistogramPaintListener.java >@@ -0,0 +1,355 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Adapted to new model-view-controller design, display improvements >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import java.text.DecimalFormat; >+import java.util.Collections; >+import java.util.Vector; >+ >+import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramScaledData; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramUtils; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.IHistogramDataModel; >+import org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.HistogramViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.Messages; >+import org.eclipse.swt.graphics.Image; >+import org.eclipse.swt.graphics.Point; >+import org.eclipse.swt.widgets.Display; >+import org.eclipse.ui.plugin.AbstractUIPlugin; >+ >+/** >+ * <b><u>HistogramPaintListener</u></b> >+ * <p> >+ * Histogram paint listener. >+ * >+ * @author Philippe Sawicki >+ */ >+public class HistogramPaintListener extends AbstractPaintListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Is a histogram bar so high that it is clipped from the draw area ? >+ */ >+ private boolean fBarIsClipped = false; >+ >+ /** >+ * Scaled data from data model >+ */ >+ protected HistogramScaledData fScaledData; >+ >+ /** >+ * Warning Image >+ */ >+ protected Image fWarningImage; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the listener's viewer. >+ */ >+ public HistogramPaintListener(AbstractViewer viewer) { >+ super(viewer); >+ fWarningImage = AbstractUIPlugin.imageDescriptorFromPlugin(Messages.LatencyView_tmf_UI, "icons/elcl16/warning.gif").createImage(Display.getCurrent()); //$NON-NLS-1$ >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Returns the histogram's bar Width. >+ * @return The histogram's bar Width. >+ */ >+ public int getBarWidth() { >+ return fBarWith; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#dispose() >+ */ >+ @Override >+ public void dispose() { >+ fWarningImage.dispose(); >+ super.dispose(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#scale() >+ */ >+ @Override >+ public void scale() { >+ // width of the plot area >+ double width = getWidth(); >+ // height of the plot area >+ double height = getHeight(); >+ >+ int barWidth = getBarWidth(); >+ >+ IHistogramDataModel model = ((HistogramViewer)fViewer).getModel(); >+ fScaledData = model.scaleTo((int)width, (int)height, barWidth); >+ >+ fYMin = 0; >+ fYMax = fScaledData.fMaxValue; >+ >+ fXMin = fScaledData.getFirstBucketTime(); >+ fXMin = fXMin > 0 ? fXMin : 0; >+ fXMax = fScaledData.getBucketEndTime(fScaledData.fLastBucket - 1); >+ >+ // No data to display - set end time to 0 >+ if (fYMax == 0) { >+ fXMax = 0; >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#paintVerticalTicks(int) >+ */ >+ @Override >+ public void paintVerticalTicks(int x) { >+ // done in method paintVerticalAxisValues() >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#paintVerticalAxisValues(int) >+ */ >+ @Override >+ public void paintVerticalAxisValues(int x) { >+ int zoomFactor = 1; >+ >+ zoomFactor = fViewer.getZoomFactor(); >+ >+ if (fYMin >= 0L && fYMax != 0L) { >+ fAxisImage.setForeground(fTextColor); >+ fAxisImage.setBackground(fBackgroundColor); >+ >+ // Apply the zoom to the max value of the graph for the next calculations >+ long yMax = fYMax / zoomFactor; >+ >+ int nbTicks = ((int)getHeight()) / MAX_HEIGHT_BETWEEN_TICKS + 1; >+ >+ Vector<Integer> values = new Vector<Integer>(); >+ boolean multipleSameValues = true; >+ while (multipleSameValues) { >+ double valueStep = (double) (yMax - fYMin) / (double) (nbTicks); >+ >+ for (int i = 0; i < nbTicks; i++) { >+ double currentValue = (double) (fYMin + i * valueStep) / (Math.pow(10, fDelta)); >+ >+ values.add((int) currentValue); >+ } >+ >+ Collections.sort(values); >+ boolean hasRepetition = false; >+ for (int i = 1; i < values.size(); i++) { >+ if (values.get(i) == values.get(i - 1)) { >+ hasRepetition = true; >+ break; >+ } >+ } >+ >+ if (hasRepetition) { >+ nbTicks--; >+ values.clear(); >+ } else { >+ multipleSameValues = false; >+ >+ // Draw rectangle over the old values >+ int height = fViewer.getBounds().height - 2 * fPadding - fPaddingTop - fHorizontalAxisYOffset; >+ fAxisImage.fillRectangle(0, fPadding + fPaddingTop, fPadding + fVerticalAxisOffset, height); >+ >+ double pixelStep = (getHeight()) / values.size() + 1; >+ >+ for (int i = 0; i < values.size(); i++) { >+ double currentValue = values.get(i); >+ >+ int y = (int) (fClientArea.height - fPadding - fHorizontalAxisYOffset - i * pixelStep); >+ String currentLabel = formatStringForVerticalAxis((long) currentValue); >+ >+ fAxisImage.setFont(fValuesFont); >+ >+ Point textDimensions = fAxisImage.stringExtent(currentLabel); >+ fAxisImage.drawText(currentLabel, x - textDimensions.x - 5, y - textDimensions.y / 2); >+ fAxisImage.drawLine(x - 3, y, x, y); >+ } >+ } >+ } >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#paintContent() >+ */ >+ @Override >+ public void paintContent() { >+ double zoomFactor = fViewer.getZoomFactor(); >+ >+ // Calculate the vertical axis factor and see if it has changed >+ double tmpDelta = fDelta; >+ fDelta = 0; >+ if (Long.toString(fYMax / (long) zoomFactor).length() > MAX_CHAR_VERTICAL_DISPLAY) { >+ fDelta = Long.toString(fYMax / (long) zoomFactor).length() - MAX_CHAR_VERTICAL_DISPLAY; >+ } >+ if (tmpDelta != fDelta) { >+ fViewer.clearBackground(); >+ } >+ >+ paintBackground(); >+ paintVerticalAxis(); >+ paintHorizontalAxis(); >+ >+ fAxisImage.setForeground(fDataColor); >+ fAxisImage.setBackground(fDataColor); >+ >+ // height of the plot area >+ double height = getHeight(); >+ >+ int barWidth = getBarWidth(); >+ >+ // axisImage_.setBackground(backgroundColor_); >+ // 1.a Iterate over the points, from 0 to nbPoints >+ // 1.b Find the max counter value >+ // 2. Assign the max value to the "yMax_" class attribute >+ // 3. Draw the histogram bars using "axisImage_.fillRectangle(...)" >+ boolean oneBarIsClipped = false; >+ >+ for (int i = 0; i < fScaledData.fData.length; i++) { >+ double pointY = fScaledData.fData[i]; >+ >+ // in pixels >+ double x = fPadding + i * barWidth + fVerticalAxisOffset + 1; >+ >+ if (i == fScaledData.fData.length - 1) >+ x -= 1.0; >+ double barHeight = zoomFactor * ((double)(pointY - fYMin) / (double)(fYMax - fYMin)) * height; >+ >+ if (barHeight > height + 1) { >+ barHeight = height; >+ oneBarIsClipped = true; >+ >+ fAxisImage.drawImage(fWarningImage, 5, 3); >+ } >+ >+ // Only draw the bars that have a barHeight of more than 1 pixel >+ if (barHeight > 0) { >+ double y = fPadding + fPaddingTop + height - barHeight; >+ fAxisImage.setBackground(fDataColor); >+ >+ if (barHeight > height - 1) { >+ fAxisImage.fillRectangle((int) x, (int) y, (int) barWidth, (int) (barHeight + 1)); >+ } else { >+ fAxisImage.fillRectangle((int) x, (int) y, (int) barWidth, (int) (barHeight + 2)); >+ } >+ } >+ } >+ >+ if (oneBarIsClipped) >+ fBarIsClipped = true; >+ else >+ fBarIsClipped = false; >+ } >+ >+ /** >+ * Paints the histogram horizontal axis values in engineering notation in which the exponent is a multiple of three. >+ * @param value >+ * The numeric value to convert to engineering notation. >+ * @return The given value formatted according to the engineering notation. >+ */ >+ @Override >+ public String formatStringForHorizontalAxis(long value) { >+ DecimalFormat formatter = new DecimalFormat("##0.#E0"); //$NON-NLS-1$ >+ return formatter.format(value); >+ } >+ >+ /** >+ * Sets the bar width. >+ * @param barWidth >+ * bar width to set >+ */ >+ public void setBarWidth(int barWidth) { >+ fBarWith = barWidth; >+ } >+ >+ /** >+ * Returns "true" if a histogram bar is so high that it cannot be drawn in the draw area, "false" otherwise. >+ * @return "true" if a histogram bar is so high that it cannot be drawn in the draw area, "false" otherwise. >+ */ >+ public boolean barIsClipped() { >+ return fBarIsClipped; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractPaintListener#formatToolTipLabel(int, int) >+ */ >+ @Override >+ public String formatToolTipLabel(int x, int y) { >+ if (fScaledData != null) { >+ >+ double barWidth = getBarWidth(); >+ double height = getHeight(); // height of the plot area >+ >+ double zoomFactor = fViewer.getZoomFactor(); >+ >+ int index = (int) ((x - fPadding - fVerticalAxisOffset - 1) / barWidth); >+ >+ double barHeight = 0.0; >+ if (index >= 0 && index <= fScaledData.fLastBucket) { >+ barHeight = (zoomFactor * height * (fScaledData.fData[index] - fYMin) / (fYMax - fYMin)); >+ } >+ >+ long fMouseY = (long) (height - (y - fPadding - fPaddingTop)); >+ >+ // Verifying mouse pointer is over histogram bar >+ if (index >= 0 && fScaledData.fLastBucket >= index && fMouseY >= 0 && fMouseY < barHeight && fMouseY < height && x >= (fVerticalAxisOffset + fPadding)) { >+ >+ fScaledData.fCurrentBucket = index; >+ >+ long startTime = fScaledData.getBucketStartTime(index); >+ // negative values are possible if time values came into the model in decreasing order >+ if (startTime < 0) { >+ startTime = 0; >+ } >+ long endTime = fScaledData.getBucketEndTime(index); >+ int nbEvents = fScaledData.fData[index]; >+ >+ StringBuffer buffer = new StringBuffer(); >+ buffer.append("Latency Range in s = ["); //$NON-NLS-1$ >+ buffer.append(HistogramUtils.nanosecondsToString(startTime)); >+ buffer.append(","); //$NON-NLS-1$ >+ buffer.append(HistogramUtils.nanosecondsToString(endTime)); >+ buffer.append("]\n"); //$NON-NLS-1$ >+ buffer.append("Latency count = "); //$NON-NLS-1$ >+ buffer.append(nbEvents); >+ return buffer.toString(); >+ } >+ } >+ return ""; //$NON-NLS-1$ >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TimePointerListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TimePointerListener.java >new file mode 100644 >index 0000000..31027ca >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TimePointerListener.java >@@ -0,0 +1,69 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ * Bernd Hufmann - Changed display interface implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer; >+ >+/** >+ * <b><u>TimePointerListener</u></b> >+ * <p> >+ * Displays a tooltip showing the approximate values of the point under the mouse cursor. >+ * >+ * @author Philippe Sawicki >+ */ >+public class TimePointerListener extends AbstractMouseTrackListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * A reference to the observed view. >+ */ >+ protected AbstractViewer fView; >+ >+ /** >+ * A reference to the HistogramPaintListener. >+ */ >+ protected GraphPaintListener fGraph; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the observed view. >+ * @param histogramPaintListener >+ * A reference to the histogram's paintListener. >+ */ >+ public TimePointerListener(AbstractViewer view, GraphPaintListener graphPaintListener) { >+ fView = view; >+ fGraph = graphPaintListener; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractMouseTrackListener#display() >+ */ >+ @Override >+ protected void display() { >+ fView.setToolTipText(fGraph.formatToolTipLabel(fMouseX, fMouseY)); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TooltipListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TooltipListener.java >new file mode 100644 >index 0000000..ccb8bc2 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TooltipListener.java >@@ -0,0 +1,100 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Bernd Hufmann - Changed display interface implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer; >+import org.eclipse.linuxtools.lttng.ui.views.latency.Messages; >+ >+/** >+ * <b><u>TooltipListener</u></b> >+ * <p> >+ * Tooltip listener, displays the event count for each latency selected by the mouse click area on histogram. >+ * >+ * @author Ali Jawhar >+ */ >+public class TooltipListener extends AbstractMouseTrackListener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * A reference to the observed view. >+ */ >+ protected AbstractViewer fView; >+ >+ /** >+ * A reference to the HistogramPaintListener. >+ */ >+ protected HistogramPaintListener fHistogram; >+ >+ /** >+ * Is the mouse over the warning icon, indicating that a bar is higher than the draw area due to zooming ? >+ */ >+ protected boolean fDisplayWarning = false; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the observed view. >+ * @param histogramPaintListener >+ * A reference to the histogram's paintListener. >+ */ >+ public TooltipListener(AbstractViewer view, HistogramPaintListener histogramPaintListener) { >+ fView = view; >+ fHistogram = histogramPaintListener; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.listeners.AbstractMouseTrackListener#display() >+ */ >+ @Override >+ protected void display() { >+ displayWarningTooltip(); >+ displayTooltip(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Helper Functions >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Displays a tooltip if the mouse is over the warning icon indication that a bar cannot be draw entirely due to the >+ * zoom factor. >+ */ >+ protected void displayWarningTooltip() { >+ if (fHistogram.barIsClipped() && fMouseX > 5 && fMouseX < 21 && fMouseY > 3 && fMouseY < 18) { >+ fView.setToolTipText(Messages.LatencyView_ClippingWarning); >+ fDisplayWarning = true; >+ } else { >+ fDisplayWarning = false; >+ } >+ } >+ >+ /** >+ * Displays the tooltip showing the details of the histogram bar pointed by the mouse. >+ */ >+ protected void displayTooltip() { >+ if (!fDisplayWarning) >+ fView.setToolTipText(fHistogram.formatToolTipLabel(fMouseX, fMouseY)); >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/ZoomListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/ZoomListener.java >new file mode 100644 >index 0000000..266f926 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/ZoomListener.java >@@ -0,0 +1,134 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactored code >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.listeners; >+ >+import org.eclipse.linuxtools.lttng.ui.views.latency.AbstractViewer; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.widgets.Canvas; >+import org.eclipse.swt.widgets.Event; >+import org.eclipse.swt.widgets.Listener; >+ >+/** >+ * <b><u>ZoomListener</u></b> >+ * <p> >+ * >+ * Canvas zoom listener. >+ * >+ * @author Philippe Sawicki >+ */ >+public class ZoomListener implements Listener { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * A reference to the observed view. >+ */ >+ protected AbstractViewer fView; >+ /** >+ * Default zoom factor. >+ */ >+ protected int fZoomFactor; >+ /** >+ * Zoom increment. >+ */ >+ protected int fZoomIncrement = 30; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the observed view. >+ * @param defaultZoomFactor >+ * Default zoom factor. >+ */ >+ public ZoomListener(AbstractViewer view, int defaultZoomFactor) { >+ fView = view; >+ fZoomFactor = defaultZoomFactor; >+ } >+ >+ /** >+ * Constructor. >+ * @param view >+ * A reference to the observed view. >+ */ >+ public ZoomListener(AbstractViewer view) { >+ this(view, 1); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Returns the zoom factor. >+ * @return The zoom factor. >+ */ >+ public int getZoomFactor() { >+ if (fZoomFactor < 1) >+ return 1; >+ else >+ return fZoomFactor; >+ } >+ >+ /** >+ * Returns the zoom increment. >+ * @return The zoom increment. >+ */ >+ public int getZoomIncrement() { >+ return fZoomIncrement; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) >+ */ >+ @Override >+ public void handleEvent(Event event) { >+ switch (event.type) { >+ case SWT.MouseWheel: >+ boolean scrollDown = (event.count == 0 ? false : (event.count > 0 ? false : true)); >+ int zoomStep = fZoomIncrement; >+ if (scrollDown) >+ zoomStep = -fZoomIncrement; >+ fZoomFactor = Math.max(0, fZoomFactor + zoomStep); >+ >+ Canvas canvas = (Canvas) event.widget; >+ if (fView != null) { >+ // clear the background to allow redraw of values of the vertical axis. >+ fView.clearBackground(); >+ fView.redrawTitle(); >+ fView.askForRedraw(); >+ } >+ canvas.redraw(); >+ break; >+ } >+ } >+ >+ /** >+ * Sets the zoom increment. >+ * @param zoomIncrement >+ * The new zoom increment. >+ */ >+ public void setZoomIncrement(int zoomIncrement) { >+ fZoomIncrement = zoomIncrement; >+ } >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/messages.properties b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/messages.properties >new file mode 100644 >index 0000000..cf907c0 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/messages.properties >@@ -0,0 +1,59 @@ >+#******************************************************************************* >+# Copyright (c) 2011 Ericsson >+# >+# 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: >+# Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+# Bernd Hufmann - Updated and added properties >+# *******************************************************************************/ >+ >+LatencyView_ViewName=LatencyView >+LatencyView_Action_IncreaseBarWidth_Tooltip=Increase bar width/height >+LatencyView_Action_DecreaseBarWidth_Tooltip=Decrease bar width/height >+LatencyView_Action_AddEvents_Tooltip=Add matching events >+LatencyView_Action_DeleteEvents_Tooltip=Delete matching events >+LatencyView_Action_ListEvents_Tooltip=List matching events >+LatencyView_Dialogs_AddEvents_Title=Add event pairs >+LatencyView_Dialogs_AddEvents_Message=Select a pair of events to add it to the match list : >+LatencyView_Dialogs_AddEvents_Buttons_Add=Add >+LatencyView_Dialogs_AddEvents_Buttons_Close=Close >+LatencyView_Dialogs_AddEvents_Columns_Start=Start event types >+LatencyView_Dialogs_AddEvents_Columns_End=End event types >+LatencyView_Dialogs_AddEvents_Columns_List_Trigger=Trigger event type >+LatencyView_Dialogs_AddEvents_Columns_List_End=End event type >+LatencyView_Dialogs_AddEvents_Errors_NoSelection=You must select one item from both lists_ >+LatencyView_Dialogs_AddEvents_Errors_StartNotSelected=You must select one item from the start event list_ >+LatencyView_Dialogs_AddEvents_Errors_EndNotSelected=You must select one item from the end event list_ >+LatencyView_Dialogs_AddEvents_Errors_SameSelected=The same event cannot be selected in both list at the same time_ >+LatencyView_Dialogs_AddEvents_Errors_AlreadyMatched=The start and end events are already matched_ >+LatencyView_Dialogs_AddEvents_Errors_StartAlreadyMatched=The start event is already matched_ >+LatencyView_Dialogs_AddEvents_Errors_EndAlreadyMatched=The end event is already matched_ >+LatencyView_Dialogs_AddEvents_Errors_StartAsEnd=The start event is already matched as an end event_ >+LatencyView_Dialogs_AddEvents_Errors_EndAsStart=The end event is already matched as a start event_ >+LatencyView_Dialogs_DeleteEvents_Title=Delete event pairs >+LatencyView_Dialogs_DeleteEvents_Message=Select a pair of matched events to remove it from the list : >+LatencyView_Dialogs_DeleteEvents_Buttons_Close=Close >+LatencyView_Dialogs_DeleteEvents_Buttons_Delete=Delete >+LatencyView_Dialogs_DeleteEvents_Confirm_Title=Confirm event deletion >+LatencyView_Dialogs_DeleteEvents_Confirm_Message=Are you sure you want to delete these event pairs? >+LatencyView_Dialogs_ListEvents_Title=Matched events list >+LatencyView_Dialogs_ListEvents_Message=List of matched events for latency computation : >+LatencyView_Dialogs_ListEvents_Buttons_Close=Close >+LatencyView_Dialogs_ListEvents_Buttons_Reset=Reset to default pairs >+LatencyView_Dialogs_ListEvents_Columns_Trigger=Trigger event type >+LatencyView_Dialogs_ListEvents_Columns_End=End event type >+LatencyView_Dialogs_ListEvents_Confirm_Title=Confirm pairs reset >+LatencyView_Dialogs_ListEvents_Confirm_Message=Are you sure you want to reset the event pairs to their default values? >+LatencyView_Graphs_Graph_Title=Latency vs Time >+LatencyView_Graphs_Graph_XAxisLabel=time (s) >+LatencyView_Graphs_Graph_YAxisLabel=latency (ms) >+LatencyView_Graphs_Histogram_Title=Latency Distribution >+LatencyView_Graphs_Histogram_XAxisLabel=latency (ms) >+LatencyView_Graphs_Histogram_YAxisLabel=# events >+LatencyView_msgSlogan=Latency View >+LatencyView_tmf_UI=org.eclipse.linuxtools.lttng.ui >+LatencyView_ClippingWarning=One or more bars are higher than the drawing area due to zooming >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/Config.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/Config.java >new file mode 100644 >index 0000000..e2d77ea >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/Config.java >@@ -0,0 +1,76 @@ >+/******************************************************************************* >+ * Copyright (c) 2010, 2011 Ericsson >+ * >+ * 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: >+ * Philippe Sawicki (INF4990.A2010@gmail.com) - Initial API and implementation >+ * Mathieu Denis (mathieu.denis55@gmail.com) - Refactor code >+ * Bernd Hufmann - Added and updated constants >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+/** >+ * <b><u>Config</u></b> >+ * <p> >+ * Configuration class, holds some application constants. >+ * >+ * @author Philippe Sawicki >+ */ >+public class Config { >+ >+ /** >+ * Private constructor to defeat instantiation. >+ */ >+ private Config() { >+ } >+ >+ /** >+ * Time scale for TMF events; >+ */ >+ public static byte TIME_SCALE = -9; >+ >+ /** >+ * Size of the point buffer holding point values before sending them to the view. >+ */ >+ public static final int POINT_BUFFER_SIZE = 10000; >+ >+ /** >+ * Histogram bar width. >+ */ >+ public static final int DEFAULT_HISTOGRAM_BAR_WIDTH = 2; >+ >+ /** >+ * Histogram bar width increase step. >+ */ >+ public static final int MIN_HISTOGRAM_BAR_WIDTH = 1; >+ >+ /** >+ * Histogram bar width increase step. >+ */ >+ public static final int MAX_HISTOGRAM_BAR_WIDTH = 16; >+ >+ >+ /** >+ * Diameter of a point drawn on the chart (in pixels). >+ */ >+ public static final int GRAPH_POINT_DIAMETER = 1; >+ >+ /** >+ * Graph padding. >+ */ >+ public static final int GRAPH_PADDING = 10; >+ >+ /** >+ * Default number of buckets used in data models >+ */ >+ public static final int DEFAULT_NUMBER_OF_BUCKETS = 2 * 1000; >+ >+ /** >+ * Invalid event time >+ */ >+ public static final long INVALID_EVENT_TIME = -1; >+} >\ No newline at end of file >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/GraphScaledData.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/GraphScaledData.java >new file mode 100644 >index 0000000..d41e684 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/GraphScaledData.java >@@ -0,0 +1,246 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+/** >+ * <b><u>GraphScaledData</u></b> >+ * Convenience class for scaled distribution data. >+ * <p> >+ */ >+import java.util.Arrays; >+ >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.BaseDistributionData; >+ >+public class GraphScaledData { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ private int fWidth; >+ private int fHeight; >+ private int fBarWidth; >+ private int[][] fData; >+ private BaseDistributionData fHorDistributionData; >+ private BaseDistributionData fVerDistributionData; >+ private long fCurrentEventTime; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ public GraphScaledData(int width, int height, int barWidth) { >+ fWidth = width; >+ fHeight = height; >+ fBarWidth = barWidth; >+ int horNbBuckets = (int)width/barWidth; >+ int verNbBuckets = (int)height/barWidth; >+ fData = new int[horNbBuckets][verNbBuckets]; >+ for (int[] row : fData) { >+ Arrays.fill(row, 0); >+ } >+ fHorDistributionData = new BaseDistributionData(horNbBuckets); >+ fHorDistributionData.clear(); >+ >+ fVerDistributionData = new BaseDistributionData(verNbBuckets); >+ fVerDistributionData.clear(); >+ >+ fCurrentEventTime = Config.INVALID_EVENT_TIME; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ public int getWidth() { >+ return fWidth; >+ } >+ >+ public int getHeight() { >+ return fHeight; >+ } >+ >+ public int getBarWidth() { >+ return fBarWidth; >+ } >+ >+ public int[][] getData() { >+ return fData; >+ } >+ >+ public int getHorNbBuckets() { >+ return fHorDistributionData.getNbBuckets(); >+ } >+ >+ public int getVerNbBuckets() { >+ return fVerDistributionData.getNbBuckets(); >+ } >+ >+ public long getHorFirstBucketTime() { >+ return fHorDistributionData.getFirstBucketTime(); >+ } >+ >+ public long getVerFirstBucketTime() { >+ return fVerDistributionData.getFirstBucketTime(); >+ } >+ >+ public long getHorLastBucketTime() { >+ return fHorDistributionData.getLastBucketTime(); >+ } >+ >+ public long getVerLastBucketTime() { >+ return fVerDistributionData.getLastBucketTime(); >+ } >+ >+ public long getHorFirstEventTime() { >+ return fHorDistributionData.getFirstEventTime(); >+ } >+ >+ public long getVerFirstEventTime() { >+ return fVerDistributionData.getFirstEventTime(); >+ } >+ >+ public long getHorLastEventTime() { >+ return fHorDistributionData.getLastEventTime(); >+ } >+ >+ public long getVerLastEventTime() { >+ return fVerDistributionData.getLastEventTime(); >+ } >+ >+ public long getHorBucketDuration() { >+ return fHorDistributionData.getBucketDuration(); >+ } >+ >+ public long getVerBucketDuration() { >+ return fVerDistributionData.getBucketDuration(); >+ } >+ >+ public int getHorLastBucket() { >+ return fHorDistributionData.getLastBucket(); >+ } >+ >+ public int getVerLastBucket() { >+ return fVerDistributionData.getLastBucket(); >+ } >+ >+ public long getHorBucketStartTime(int index) { >+ return fHorDistributionData.getBucketStartTime(index); >+ } >+ >+ public long getHorBucketEndTime(int index) { >+ return fHorDistributionData.getBucketEndTime(index); >+ } >+ >+ public long getVerBucketStartTime(int index) { >+ return fVerDistributionData.getBucketStartTime(index); >+ } >+ >+ public long getVerBucketEndTime(int index) { >+ return fVerDistributionData.getBucketEndTime(index); >+ } >+ >+ public int getEventCount(int horIndex, int verIndex) { >+ return fData[horIndex][verIndex]; >+ } >+ >+ public long getCurrentEventTime() { >+ return fCurrentEventTime; >+ } >+ >+ public boolean isCurrentEventTimeValid() { >+ if (fCurrentEventTime == Config.INVALID_EVENT_TIME || fCurrentEventTime < getHorFirstEventTime() || fCurrentEventTime > getHorLastEventTime()) { >+ return false; >+ } >+ return true; >+ } >+ >+ public int getHorBucketIndex(long time) { >+ return fHorDistributionData.getIndex(time); >+ } >+ >+ public int getVerBucketIndex(long time) { >+ return fVerDistributionData.getIndex(time); >+ } >+ >+ public boolean isHorIndexValid(int index) { >+ return fHorDistributionData.isIndexValid(index); >+ } >+ >+ public boolean isVerIndexValid(int index) { >+ return fVerDistributionData.isIndexValid(index); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ public void setWidth(int width) { >+ fWidth = width; >+ } >+ >+ public void setHeight(int height) { >+ fHeight = height; >+ } >+ >+ public void setBarWidth(int barWidth) { >+ fBarWidth = barWidth; >+ } >+ >+ public void setData(int[][] data) { >+ fData = data; >+ } >+ >+ public void setHorFirstBucketTime(long firstBucketTime) { >+ fHorDistributionData.setFirstBucketTime(firstBucketTime); >+ } >+ >+ public void setVerFirstBucketTime(long firstBucketTime) { >+ fVerDistributionData.setFirstBucketTime(firstBucketTime); >+ } >+ >+ public void setHorFirstEventTime(long firstEventTime) { >+ fHorDistributionData.setFirstEventTime(firstEventTime); >+ } >+ >+ public void setVerFirstEventTime(long firstEventTime) { >+ fVerDistributionData.setFirstEventTime(firstEventTime); >+ } >+ >+ public void setHorLastEventTime(long lastEventTime) { >+ fHorDistributionData.setLastEventTime(lastEventTime); >+ } >+ >+ public void setVerLastEventTime(long lastEventTime) { >+ fVerDistributionData.setLastEventTime(lastEventTime); >+ } >+ >+ public void setHorBucketDuration(long bucketDuration) { >+ fHorDistributionData.setBucketDuration(bucketDuration); >+ } >+ >+ public void setVerBucketDuration(long bucketDuration) { >+ fVerDistributionData.setBucketDuration(bucketDuration); >+ } >+ >+ public void setHorLastBucket(int lastBucket) { >+ fHorDistributionData.setLastBucket(lastBucket); >+ } >+ >+ public void setVerLastBucket(int lastBucket) { >+ fVerDistributionData.setLastBucket(lastBucket); >+ } >+ >+ public void setCurrentEventTime(long currentEventTime) { >+ fCurrentEventTime = currentEventTime; >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphDataModel.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphDataModel.java >new file mode 100644 >index 0000000..182004b >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphDataModel.java >@@ -0,0 +1,41 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.IBaseDistributionModel; >+ >+/** >+ * <b><u>IGraphDataModel</u></b> >+ * <p> >+ */ >+public interface IGraphDataModel extends IBaseDistributionModel { >+ >+ /** >+ * Add event to the correct bucket, compacting the if needed. >+ * >+ * @param eventCount - the event count >+ * @param timestamp - the timestamp (x-coordinate) of the event to count >+ * @param time - the time (y-coordinate) of the event to count >+ */ >+ public void countEvent(int eventCount, long timestamp, long time); >+ >+ /** >+ * Scale the model data to the width and height requested. >+ * >+ * @param width - width of graph >+ * @param height - height of graph >+ * @param barWidth - width of bar >+ * @return the result array of size [width] and where the highest value >+ * doesn't exceed [height] >+ */ >+ public GraphScaledData scaleTo(int width, int height, int barWidth); >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphModelListener.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphModelListener.java >new file mode 100644 >index 0000000..b664399 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphModelListener.java >@@ -0,0 +1,31 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+/** >+ * <b><u>IGraphModelListener</u></b> >+ * <p> >+ */ >+public interface IGraphModelListener { >+ >+ /** >+ * Method to notify listeners about model updates >+ */ >+ public void graphModelUpdated(); >+ >+ /** >+ * Method to inform listeners about current time updates >+ */ >+ public void currentEventUpdated(long currentEventTime); >+ >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyController.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyController.java >new file mode 100644 >index 0000000..fa212d3 >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyController.java >@@ -0,0 +1,189 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+import org.eclipse.core.runtime.ListenerList; >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.IBaseDistributionModel; >+import org.eclipse.linuxtools.lttng.ui.views.histogram.IHistogramDataModel; >+import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider; >+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; >+import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest; >+import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest.ExecutionType; >+ >+/** >+ * <b><u>LatencyController</u></b> >+ * <p> >+ */ >+public class LatencyController { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ >+ private static LatencyController fInstance = null; >+ >+ private LatencyEventRequest fEventRequest; >+ >+ private TmfEventProvider<?> fProvider; >+ >+ private final ListenerList fModels; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ private LatencyController() { >+ fModels = new ListenerList(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ public static LatencyController getInstance() { >+ if (fInstance == null) { >+ fInstance = new LatencyController(); >+ } >+ return fInstance; >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /** >+ * Refresh all registered models >+ * >+ * @param provider - TmfEventProvider to request data from >+ * @param timeRange - time range of request >+ */ >+ @SuppressWarnings({ "unchecked", "rawtypes" }) >+ public void refreshModels(TmfEventProvider<?> provider, TmfTimeRange timeRange) { >+ // save provider >+ fProvider = provider; >+ if (fProvider != null) { >+ if (fEventRequest != null && !fEventRequest.isCompleted()) { >+ fEventRequest.cancel(); >+ } >+ clear(); >+ fEventRequest = new LatencyEventRequest(this, timeRange, ExecutionType.FOREGROUND); >+ fProvider.sendRequest((TmfDataRequest)fEventRequest); >+ } >+ } >+ >+ /** >+ * Refreshes registered models by re-sending previous request to saved provider >+ */ >+ public void refreshModels() { >+ if (fProvider != null && fEventRequest != null) { >+ refreshModels(fProvider, fEventRequest.getRange()); >+ } >+ } >+ >+ /** >+ * Clear all models >+ */ >+ public void clear() { >+ Object models[] = fModels.getListeners(); >+ >+ for (int i = 0; i < models.length; i++) { >+ ((IBaseDistributionModel)models[i]).clear(); >+ } >+ } >+ >+ /** >+ * Dispose of controller >+ */ >+ public void dispose() { >+ if (fEventRequest != null && !fEventRequest.isCompleted()) { >+ fEventRequest.cancel(); >+ } >+ fProvider = null; >+ } >+ >+ /** >+ * Register given model. >+ * @param model - model to register >+ */ >+ public void registerModel(IBaseDistributionModel model) { >+ fModels.add(model); >+ } >+ >+ /** >+ * Deregister given model. >+ * >+ * @param model - model to deregister >+ */ >+ public void deregisterModel(IBaseDistributionModel model) { >+ fModels.remove(model); >+ } >+ >+ /** >+ * Handle data of event request and pass it information to the registered models >+ * >+ * @param eventCount - event count >+ * @param timestamp - start timestamp of latency calculation >+ * @param latency - latency value (startTimestamp - endTimestamp) >+ */ >+ public void handleData(int eventCount, long timestamp, long latency) { >+ Object[] models = fModels.getListeners(); >+ for (int i = 0; i < models.length; i++) { >+ IBaseDistributionModel model = (IBaseDistributionModel)models[i]; >+ if (model instanceof IHistogramDataModel) { >+ ((IHistogramDataModel)model).countEvent(eventCount, latency); >+ } else if (model instanceof IGraphDataModel) { >+ ((IGraphDataModel)model).countEvent(eventCount, timestamp, latency); >+ } >+ } >+ } >+ >+ /** >+ * Handle complete indication from request. >+ */ >+ public void handleCompleted() { >+ Object[] models = fModels.getListeners(); >+ for (int i = 0; i < models.length; i++) { >+ ((IBaseDistributionModel)models[i]).complete(); >+ } >+ } >+ >+ /** >+ * Handle cancel indication from request. >+ */ >+ public void handleCancel() { >+ clear(); >+ } >+ >+ /** >+ * Set event provider for refresh. >+ * >+ * @param provider >+ */ >+ public void setEventProvider(TmfEventProvider<?> provider) { >+ fProvider = provider; >+ } >+ >+ /** >+ * Set current event time in model(s). >+ * >+ * @param timestamp >+ */ >+ public void setCurrentEventTime(long timestamp) { >+ Object[] models = fModels.getListeners(); >+ for (int i = 0; i < models.length; i++) { >+ IBaseDistributionModel model = (IBaseDistributionModel)models[i]; >+ if (model instanceof LatencyGraphModel) { >+ ((LatencyGraphModel)model).setCurrentEventNotifyListeners(timestamp); >+ } >+ } >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyEventRequest.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyEventRequest.java >new file mode 100644 >index 0000000..d871ecb >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyEventRequest.java >@@ -0,0 +1,91 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+import org.eclipse.linuxtools.lttng.core.LttngConstants; >+import org.eclipse.linuxtools.lttng.core.event.LttngEvent; >+import org.eclipse.linuxtools.lttng.core.latency.analyzer.EventMatcher; >+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; >+import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; >+import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest; >+ >+/** >+ * <b><u>LatencyEventRequest</u></b> >+ * <p> >+ */ >+public class LatencyEventRequest extends TmfEventRequest<LttngEvent> { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ final private LatencyController fController; >+ >+ // ------------------------------------------------------------------------ >+ // Constructor >+ // ------------------------------------------------------------------------ >+ >+ public LatencyEventRequest(LatencyController controller, TmfTimeRange range, int rank, int nbEvents, ITmfDataRequest.ExecutionType execType) { >+ super(LttngEvent.class, range, rank, nbEvents, LttngConstants.DEFAULT_BLOCK_SIZE, execType); >+ fController = controller; >+ EventMatcher.getInstance().clearStack(); >+ } >+ >+ public LatencyEventRequest(LatencyController controller, TmfTimeRange range, ITmfDataRequest.ExecutionType execType) { >+ this(controller, range, 0, ALL_DATA, execType); >+ } >+ >+ public LatencyEventRequest(LatencyController controller, TmfTimeRange range, int rank, ITmfDataRequest.ExecutionType execType) { >+ this(controller, range, rank, ALL_DATA, execType); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleData(org.eclipse.linuxtools.tmf.event.TmfData) >+ */ >+ @Override >+ public void handleData(LttngEvent event) { >+ super.handleData(event); >+ >+ LttngEvent startEvent = EventMatcher.getInstance().process(event); >+ >+ if (startEvent != null) { >+ long latency = event.getTimestamp().getValue() - startEvent.getTimestamp().getValue(); >+ fController.handleData(getNbRead(), startEvent.getTimestamp().getValue(), latency); >+ } >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCompleted() >+ */ >+ @Override >+ public void handleCompleted() { >+ fController.handleCompleted(); >+ super.handleCompleted(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.tmf.request.TmfDataRequest#handleCancel() >+ */ >+ @Override >+ public void handleCancel() { >+ EventMatcher.getInstance().clearStack(); >+ fController.handleCancel(); >+ super.handleCancel(); >+ } >+} >diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyGraphModel.java b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyGraphModel.java >new file mode 100644 >index 0000000..399379f >--- /dev/null >+++ b/lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyGraphModel.java >@@ -0,0 +1,380 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Ericsson >+ * >+ * 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: >+ * Bernd Hufmann - Initial API and implementation >+ *******************************************************************************/ >+ >+package org.eclipse.linuxtools.lttng.ui.views.latency.model; >+ >+import java.util.Arrays; >+import java.util.concurrent.locks.ReentrantLock; >+ >+import org.eclipse.core.runtime.ListenerList; >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.DistributionData; >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.HorDistributionData; >+import org.eclipse.linuxtools.lttng.ui.views.distribution.model.VerDistributionData; >+ >+/** >+ * <b><u>LatencyGraphModel</u></b> >+ * <p> >+ */ >+public class LatencyGraphModel implements IGraphDataModel { >+ >+ // ------------------------------------------------------------------------ >+ // Attributes >+ // ------------------------------------------------------------------------ >+ private final int fNbBuckets; >+ private final int [][] fBuckets; >+ private final DistributionData fHorDistributionData; >+ private final DistributionData fVerDistributionData; >+ private long fCurrentEventTime; >+ >+ // private listener lists >+ private final ListenerList fModelListeners; >+ >+ private final ReentrantLock fLock; >+ >+ // ------------------------------------------------------------------------ >+ // Constructors >+ // ------------------------------------------------------------------------ >+ public LatencyGraphModel() { >+ this(Config.DEFAULT_NUMBER_OF_BUCKETS); >+ } >+ >+ public LatencyGraphModel(int nbBuckets) { >+ fNbBuckets = nbBuckets; >+ fBuckets = new int[nbBuckets][nbBuckets]; >+ fHorDistributionData = new HorDistributionData(nbBuckets, fBuckets); >+ fVerDistributionData = new VerDistributionData(nbBuckets, fBuckets); >+ fCurrentEventTime = Config.INVALID_EVENT_TIME; >+ >+ fModelListeners = new ListenerList(); >+ fLock = new ReentrantLock(); >+ clear(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Accessors >+ // ------------------------------------------------------------------------ >+ >+ public int getNbBuckets() { >+ return fNbBuckets; >+ } >+ >+ public long getHorBucketDuration() { >+ fLock.lock(); >+ try { >+ return fHorDistributionData.getBucketDuration(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getVerBucketDuration() { >+ fLock.lock(); >+ try { >+ return fVerDistributionData.getBucketDuration(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getHorFirstBucketTime() { >+ fLock.lock(); >+ try { >+ return fHorDistributionData.getFirstBucketTime(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getVerFirstBucketTime() { >+ fLock.lock(); >+ try { >+ return fVerDistributionData.getFirstBucketTime(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getHorFirstEventTime() { >+ fLock.lock(); >+ try { >+ return fHorDistributionData.getFirstEventTime(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getVerFirstEventTime() { >+ fLock.lock(); >+ try { >+ return fVerDistributionData.getFirstEventTime(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getHorLastEventTime() { >+ fLock.lock(); >+ try { >+ return fHorDistributionData.getLastEventTime(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getVerLastEventTime() { >+ fLock.lock(); >+ try { >+ return fVerDistributionData.getLastEventTime(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getHorTimeLimit() { >+ fLock.lock(); >+ try { >+ return fHorDistributionData.getTimeLimit(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getVerTimeLimit() { >+ fLock.lock(); >+ try { >+ return fVerDistributionData.getTimeLimit(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public int getHorLastBucket() { >+ fLock.lock(); >+ try { >+ return fHorDistributionData.getLastBucket(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public int getVerLastBucket() { >+ fLock.lock(); >+ try { >+ return fVerDistributionData.getLastBucket(); >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ public long getCurrentEventTime() { >+ fLock.lock(); >+ try { >+ return fCurrentEventTime; >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Listener interface >+ // ------------------------------------------------------------------------ >+ public void addGraphModelListener(IGraphModelListener listener) { >+ fModelListeners.add(listener); >+ } >+ >+ public void removeGraphModelListener(IGraphModelListener listener) { >+ fModelListeners.remove(listener); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Operations >+ // ------------------------------------------------------------------------ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.IBaseDataModel#clear() >+ */ >+ @Override >+ public void clear() { >+ fLock.lock(); >+ try { >+ for (int[] row : fBuckets) { >+ Arrays.fill(row, 0, fNbBuckets, 0); >+ } >+ fHorDistributionData.clear(); >+ fVerDistributionData.clear(); >+ } finally { >+ fLock.unlock(); >+ } >+ fireModelUpdateNotification(); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphDataModel#countEvent(int, long, long) >+ */ >+ @Override >+ public void countEvent(int eventCount, long timestamp, long time) { >+ fLock.lock(); >+ try { >+ int horIndex = fHorDistributionData.countEvent(timestamp); >+ int verIndex = fVerDistributionData.countEvent(time); >+ >+ fBuckets[horIndex][verIndex]++; >+ } finally { >+ fLock.unlock(); >+ } >+ >+ fireModelUpdateNotification(eventCount); >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.latency.model.IGraphDataModel#scaleTo(int, int, int) >+ */ >+ @Override >+ public GraphScaledData scaleTo(int width, int height, int barWidth) { >+ GraphScaledData scaledData = new GraphScaledData(width, height, barWidth); >+ fLock.lock(); >+ try { >+ if (!fHorDistributionData.isFirst() && !fVerDistributionData.isFirst() ) { >+ >+ // Basic validation >+ if (width <= 0 || height <= 0 || barWidth <= 0) >+ throw new AssertionError("Invalid histogram dimensions (" + width + "x" + height + ", barWidth=" + barWidth + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$ >+ >+ // Scale horizontally >+ int nbBars = width / barWidth; >+ int bucketsPerBar = fHorDistributionData.getLastBucket() / nbBars + 1; >+ >+ int horData[][] = new int[nbBars][fNbBuckets]; >+ for (int y = 0; y < fNbBuckets; y++) { >+ for (int i = 0; i < nbBars; i++) { >+ int count = 0; >+ for (int j = i * bucketsPerBar; j < (i + 1) * bucketsPerBar; j++) { >+ if (fNbBuckets <= j) >+ break; >+ count += fBuckets[j][y]; >+ } >+ horData[i][y] = count; >+ } >+ } >+ >+ // Scale vertically >+ int nbVerBars = height / barWidth; >+ int bucketsPerVerBar = fVerDistributionData.getLastBucket() / nbVerBars + 1; >+ >+ int verData[][] = new int[nbBars][nbVerBars]; >+ for (int x = 0; x < nbBars; x++) { >+ for (int i = 0; i < nbVerBars; i++) { >+ int count = 0; >+ for (int j = i * bucketsPerVerBar; j < (i + 1) * bucketsPerVerBar; j++) { >+ if (fNbBuckets <= j) >+ break; >+ count += horData[x][j]; >+ } >+ verData[x][i] = count; >+ } >+ } >+ >+ scaledData.setData(verData); >+ scaledData.setHorFirstBucketTime(fHorDistributionData.getFirstBucketTime()); >+ scaledData.setVerFirstBucketTime(fVerDistributionData.getFirstBucketTime()); >+ scaledData.setHorFirstEventTime(fHorDistributionData.getFirstEventTime()); >+ scaledData.setVerFirstEventTime(fVerDistributionData.getFirstEventTime()); >+ scaledData.setHorLastEventTime(fHorDistributionData.getLastEventTime()); >+ scaledData.setVerLastEventTime(fVerDistributionData.getLastEventTime()); >+ scaledData.setHorBucketDuration(bucketsPerBar * fHorDistributionData.getBucketDuration()); >+ scaledData.setVerBucketDuration(bucketsPerVerBar * fVerDistributionData.getBucketDuration()); >+ scaledData.setHorLastBucket(fHorDistributionData.getLastBucket() / bucketsPerBar); >+ scaledData.setVerLastBucket(fVerDistributionData.getLastBucket() / bucketsPerVerBar); >+ scaledData.setCurrentEventTime(fCurrentEventTime); >+ } >+ } finally { >+ fLock.unlock(); >+ } >+ >+ return scaledData; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * @see org.eclipse.linuxtools.lttng.ui.views.distribution.model.IBaseDataModel#complete() >+ */ >+ @Override >+ public void complete() { >+ fireModelUpdateNotification(); >+ } >+ >+ /** >+ * Sets the current event time but don't notify listeners. >+ * >+ * @param timestamp >+ */ >+ public void setCurrentEvent(long timestamp) { >+ fLock.lock(); >+ try { >+ fCurrentEventTime = timestamp; >+ } finally { >+ fLock.unlock(); >+ } >+ } >+ >+ /** >+ * Sets the current event time and notify listeners. >+ * >+ * @param timestamp >+ */ >+ public void setCurrentEventNotifyListeners(long timestamp) { >+ fLock.lock(); >+ try { >+ fCurrentEventTime = timestamp; >+ } finally { >+ fLock.unlock(); >+ } >+ fireCurrentEventUpdateNotification(); >+ } >+ >+ // ------------------------------------------------------------------------ >+ // Helper functions >+ // ------------------------------------------------------------------------ >+ >+ /* >+ * Notify listeners immediately >+ */ >+ private void fireModelUpdateNotification() { >+ fireModelUpdateNotification(0); >+ } >+ >+ /* >+ * Notify listeners with certain refresh rate. >+ */ >+ private void fireModelUpdateNotification(int count) { >+ if (count % Config.POINT_BUFFER_SIZE == 0) { >+ Object[] listeners = fModelListeners.getListeners(); >+ for (int i = 0; i < listeners.length; i++) { >+ IGraphModelListener listener = (IGraphModelListener) listeners[i]; >+ listener.graphModelUpdated(); >+ } >+ } >+ } >+ >+ /* >+ * Notify listeners immediately >+ */ >+ private void fireCurrentEventUpdateNotification() { >+ Object[] listeners = fModelListeners.getListeners(); >+ for (int i = 0; i < listeners.length; i++) { >+ IGraphModelListener listener = (IGraphModelListener) listeners[i]; >+ listener.currentEventUpdated(fCurrentEventTime); >+ } >+ } >+} >-- >1.7.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
jjohnstn
:
iplog+
Actions:
View
|
Diff
Attachments on
bug 331467
:
184440
|
185278
|
185279
|
201090
|
201276
|
201280
| 209983