Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernd Hufmann2012-01-24 16:27:45 +0000
committerBernd Hufmann2012-02-13 14:05:41 +0000
commitff3352b8038e3e989229be91c4ee0f76e49849d9 (patch)
tree8ed6183d70ff63bf4ec69a54be121ef98fc7f1a9
parenta875cdfe468551a0460115407fdbd1f03c1f0691 (diff)
downloadorg.eclipse.linuxtools-ff3352b8038e3e989229be91c4ee0f76e49849d9.tar.gz
org.eclipse.linuxtools-ff3352b8038e3e989229be91c4ee0f76e49849d9.tar.xz
org.eclipse.linuxtools-ff3352b8038e3e989229be91c4ee0f76e49849d9.zip
Added latency analysis feature (bug 331467)
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.core/META-INF/MANIFEST.MF5
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/EventMatcher.java505
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/latency/analyzer/StackWrapper.java152
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/EventsPair.java29
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.core/src/org/eclipse/linuxtools/lttng/core/util/Pair.java121
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/AllLTTngUITests.java1
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/AllTests.java27
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/distribution/LatencyGraphModelTest.java582
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui.tests/src/org/eclipse/linuxtools/lttng/ui/tests/histogram/HistogramDataModelTest.java256
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF5
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/add_button.gifbin0 -> 308 bytes
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/decreasebar_button.gifbin0 -> 211 bytes
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/delete_button.gifbin0 -> 337 bytes
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/increasebar_button.gifbin0 -> 208 bytes
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/warning.gifbin0 -> 999 bytes
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/icons/eview16/graph.gifbin0 -> 197 bytes
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties1
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/plugin.xml9
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/BaseDistributionData.java142
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/DistributionData.java179
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/HorDistributionData.java70
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/IBaseDistributionModel.java25
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/distribution/model/VerDistributionData.java69
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/FullTraceHistogram.java7
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/Histogram.java54
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramDataModel.java184
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java14
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramScaledData.java34
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java9
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramDataModel.java38
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/IHistogramModelListener.java23
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeRangeHistogram.java3
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/AbstractViewer.java255
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/GraphViewer.java158
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/HistogramViewer.java157
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/LatencyView.java477
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/Messages.java85
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AbstractDialog.java240
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/AddDialog.java488
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/DeleteDialog.java155
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/dialogs/ListDialog.java252
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseListener.java80
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractMouseTrackListener.java77
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/AbstractPaintListener.java735
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphMouseListener.java70
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/GraphPaintListener.java227
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/HistogramPaintListener.java355
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TimePointerListener.java69
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/TooltipListener.java100
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/listeners/ZoomListener.java134
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/messages.properties59
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/Config.java76
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/GraphScaledData.java246
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphDataModel.java41
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/IGraphModelListener.java31
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyController.java189
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyEventRequest.java91
-rw-r--r--lttng/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/latency/model/LatencyGraphModel.java380
58 files changed, 7668 insertions, 103 deletions
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 a8275a04e2..1ac8175feb 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 0000000000..721efadfe7
--- /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 0000000000..e64ccb2c04
--- /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 0000000000..3a13edd3b4
--- /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 0000000000..cebcf03da6
--- /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 dcc3c10f25..ab6fe78934 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 0000000000..b44a4debe7
--- /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 0000000000..36c382d76b
--- /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 e0e0f3f9bd..249d34d2ef 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 e3fe166072..8cf889675b 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 0000000000..ae9543c6e7
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/add_button.gif
Binary files differ
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 0000000000..3d9202508c
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/decreasebar_button.gif
Binary files differ
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 0000000000..6bc0689f13
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/delete_button.gif
Binary files differ
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 0000000000..aa58227d1a
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/increasebar_button.gif
Binary files differ
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 0000000000..7285660618
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/icons/elcl16/warning.gif
Binary files differ
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 0000000000..fc187dc2d0
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng.ui/icons/eview16/graph.gif
Binary files differ
diff --git a/lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties b/lttng/org.eclipse.linuxtools.lttng.ui/plugin.properties
index 5d6ea9dc3e..2211985c6d 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 15bd8f1294..988f3e8455 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 0000000000..ef3ee33f92
--- /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 0000000000..75e3286bd0
--- /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 0000000000..766384f69c
--- /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 0000000000..5c61a9eee2
--- /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 0000000000..e44398c417
--- /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 d7e0345d4d..176cf8db6b 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 b7632607e3..dc665aba11 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 36c6fb748c..28b944ecca 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 2b88329570..120d243298 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 8260b4fb59..b1e6a1fe5e 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 32f9dc11bf..62bc9573ef 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 0000000000..35606f3351
--- /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 0000000000..d980a17ccb
--- /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 1ed5f7ef5b..85a00612e4 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 0000000000..75597d693b
--- /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 0000000000..2598543198
--- /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 0000000000..96860d3a7f
--- /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 0000000000..dcb227eb0d
--- /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 0000000000..85cffa9179
--- /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 0000000000..2551eae068
--- /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 0000000000..aee1ef9e44
--- /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 0000000000..c975688aa8
--- /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 0000000000..fd993525a0
--- /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 0000000000..3d3b1a09bd
--- /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 0000000000..b4e53feaa9
--- /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 0000000000..ae7be22b4a
--- /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 0000000000..5d6cb75372
--- /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 0000000000..a6732c2fee
--- /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 0000000000..0241f647cc
--- /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 0000000000..31027ca4aa
--- /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 0000000000..ccb8bc2d74
--- /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 0000000000..266f926a1f
--- /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 0000000000..cf907c03d5
--- /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 0000000000..e2d77ead64
--- /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 0000000000..d41e684eaf
--- /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 0000000000..182004bbb5
--- /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 0000000000..b6643991a3
--- /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 0000000000..fa212d3fc1
--- /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 0000000000..d871ecb4fa
--- /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 0000000000..399379f2da
--- /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);
+ }
+ }
+}

Back to the top