# HG changeset patch # User Mario Torre # Date 1418294682 -3600 # Node ID b1306c7c742200ed3d1f95c77f7945224637d7d7 # Parent 504adea43d70bdef5f23cf4073cc63755e90a26f Thread monitor improvements part I review-thread: http://icedtea.classpath.org/pipermail/thermostat/2014-December/012136.html reviewed-by: omajid, jkang diff -r 504adea43d70 -r b1306c7c7422 client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatScrollBar.java --- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatScrollBar.java Thu Dec 11 01:35:29 2014 -0700 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatScrollBar.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,13 +36,11 @@ package com.redhat.thermostat.client.swing.components; -import com.redhat.thermostat.client.swing.components.ThermostatThinScrollBar; - /** * This widget implements standard sized scrollbars. */ @SuppressWarnings("serial") -class ThermostatScrollBar extends ThermostatThinScrollBar { +public class ThermostatScrollBar extends ThermostatThinScrollBar { public ThermostatScrollBar() { this(ThermostatScrollBar.VERTICAL); } diff -r 504adea43d70 -r b1306c7c7422 storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Query.java --- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Query.java Thu Dec 11 01:35:29 2014 -0700 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Query.java Thu Dec 11 11:44:42 2014 +0100 @@ -63,7 +63,9 @@ throw new IllegalArgumentException("Already contains criteria" + " with this id." + " New: " + criterion + - " Old: " + map.get(id)); + " (id = " + id + ")" + + " Old: " + map.get(id) + + " query id: " + getId()); } map.put(id, criterion); criteria.add(criterion); diff -r 504adea43d70 -r b1306c7c7422 storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/WhereCriterion.java --- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/WhereCriterion.java Thu Dec 11 01:35:29 2014 -0700 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/WhereCriterion.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,6 +36,8 @@ package com.redhat.thermostat.storage.core.experimental.statement; +import java.util.Objects; + /** * */ @@ -50,6 +52,10 @@ FieldDescriptor descriptor, TypeMapper.Criteria criteria) { + Objects.requireNonNull(id, "id must be not null"); + Objects.requireNonNull(criteria, "criteria must be not null"); + Objects.requireNonNull(descriptor, "descriptor must be not null"); + this.descriptor = descriptor; this.criteria = criteria; this.id = id; diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/ThreadCollector.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/ThreadCollector.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/ThreadCollector.java Thu Dec 11 11:44:42 2014 +0100 @@ -37,11 +37,10 @@ package com.redhat.thermostat.thread.client.common.collector; import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler; import com.redhat.thermostat.storage.dao.AgentInfoDAO; import com.redhat.thermostat.thread.dao.ThreadDao; import com.redhat.thermostat.thread.model.SessionID; -import com.redhat.thermostat.thread.model.ThreadContentionSample; -import com.redhat.thermostat.thread.model.ThreadHeader; import com.redhat.thermostat.thread.model.ThreadSession; import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; @@ -58,6 +57,11 @@ boolean isHarvesterCollecting(); /** + * Returns the range of all known threads probes. + */ + Range getThreadRange(SessionID session); + + /** * Returns a list of sessions recorded during sampling. */ List getThreadSessions(Range range); @@ -71,25 +75,6 @@ List getThreadSummary(SessionID session, Range range); /** - * Return the range of all {@link ThreadState} data (timestamp of first and - * last ThreadState entry in storage) for this virtual machine. - */ - Range getThreadStateTotalTimeRange(); - - /** - * Return the range of {@link ThreadState} for the given - * {@link ThreadHeader} (timestamp of first and - * last ThreadState entry in storage). - */ - Range getThreadStateRange(ThreadHeader thread); - - /** - * Returns a list with all the {@link ThreadState} information for the - * given {@link ThreadHeader}, in the given range, in ascending order. - */ - List getThreadStates(ThreadHeader thread, Range range); - - /** * Check for deadlocks. {@link #getLatestDeadLockData} needs to be called to * obtain the data. */ @@ -97,16 +82,9 @@ /** Return the latest deadlock data */ VmDeadLockData getLatestDeadLockData(); - - /** - * Returns a list with all {@link ThreadHeader}s listed in the storage. - */ - List getThreads(); - /** - * Returns the latest {@link ThreadContentionSample} available for this - * {@link ThreadHeader}. - */ - ThreadContentionSample getLatestContentionSample(ThreadHeader thread); + void getThreadStates(SessionID session, + ResultHandler handler, + Range range); } diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadMXBeanCollector.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadMXBeanCollector.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadMXBeanCollector.java Thu Dec 11 11:44:42 2014 +0100 @@ -45,29 +45,31 @@ import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.core.HostRef; import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler; import com.redhat.thermostat.storage.dao.AgentInfoDAO; import com.redhat.thermostat.thread.client.common.collector.ThreadCollector; import com.redhat.thermostat.thread.collector.HarvesterCommand; import com.redhat.thermostat.thread.dao.ThreadDao; import com.redhat.thermostat.thread.model.SessionID; -import com.redhat.thermostat.thread.model.ThreadContentionSample; import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; -import com.redhat.thermostat.thread.model.ThreadHeader; import com.redhat.thermostat.thread.model.ThreadSession; import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; import com.redhat.thermostat.thread.model.VmDeadLockData; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; - import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; import java.util.logging.Logger; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; public class ThreadMXBeanCollector implements ThreadCollector { - + + private static final Range FULL_RANGE = new Range<>(0l, Long.MAX_VALUE); + private static final int ALL = -1; + private static final int FIRST = 1; + private static final String CMD_CHANNEL_ACTION_NAME = "thread-harvester"; private static final Logger logger = LoggingUtils.getLogger(ThreadMXBeanCollector.class); @@ -99,7 +101,7 @@ return harvester; } - + @Override public boolean startHarvester() { @@ -136,13 +138,14 @@ @Override public List getThreadSessions(Range range) { - return threadDao.getSessions(ref, range, Integer.MAX_VALUE); + return threadDao.getSessions(ref, range, ALL, ThreadDao.Sort.ASCENDING); } @Override public SessionID getLastThreadSession() { List sessions = - threadDao.getSessions(ref, new Range<>(0l, Long.MAX_VALUE), 1); + threadDao.getSessions(ref, FULL_RANGE, FIRST, + ThreadDao.Sort.DESCENDING); return sessions.isEmpty() ? null : new SessionID(sessions.get(0).getSession()); } @@ -162,18 +165,41 @@ } @Override - public Range getThreadStateRange(ThreadHeader thread) { + public Range getThreadRange(SessionID session) { + + final long[] timestamps = new long[2]; + timestamps[0] = 0l; + timestamps[1] = Long.MAX_VALUE; - Range result = null; + threadDao.getThreadStates(ref, session, + new ResultHandler() { + @Override + public void onResult(ThreadState result) { + timestamps[1] = result.getTimeStamp(); + } + }, + FULL_RANGE, FIRST, ThreadDao.Sort.DESCENDING); - ThreadState last = threadDao.getLastThreadState(thread); - ThreadState first = threadDao.getFirstThreadState(thread); + threadDao.getThreadStates(ref, session, + new ResultHandler() { + @Override + public void onResult(ThreadState result) { + timestamps[0] = result.getTimeStamp(); + } + }, + FULL_RANGE, FIRST, ThreadDao.Sort.ASCENDING); - if (last != null && first != null) { - result = new Range<>(first.getProbeStartTime(), last.getProbeEndTime()); - } + return new Range<>(timestamps[0], timestamps[1]); + } - return result; + @Override + public void getThreadStates(SessionID session, + ResultHandler handler, + Range range) + { + threadDao.getThreadStates(ref, session, handler, range, + ALL, + ThreadDao.Sort.ASCENDING); } @Override @@ -183,15 +209,6 @@ } @Override - public Range getThreadStateTotalTimeRange() { - return threadDao.getThreadStateTotalTimeRange(ref); - } - - public List getThreadStates(ThreadHeader thread, Range range) { - return threadDao.getThreadStates(thread, range); - } - - @Override public VmDeadLockData getLatestDeadLockData() { return threadDao.loadLatestDeadLockStatus(ref); } @@ -207,10 +224,10 @@ postAndWait(harvester); } - @Override - public ThreadContentionSample getLatestContentionSample(ThreadHeader thread) { - return threadDao.getLatestContentionSample(thread); - } +// @Override +// public ThreadContentionSample getLatestContentionSample(ThreadHeader thread) { +// return threadDao.getLatestContentionSample(thread); +// } private boolean postAndWait(Request harvester) { final CountDownLatch latch = new CountDownLatch(1); @@ -239,11 +256,6 @@ return result[0]; } - @Override - public List getThreads() { - return threadDao.getThreads(ref); - } - private void enqueueRequest(Request req) throws CommandChannelException { ServiceReference ref = context.getServiceReference(RequestQueue.class.getName()); if (ref == null) { diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/ThreadInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/ThreadInfo.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,92 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.common.model.timeline; + +import java.util.Objects; + +public class ThreadInfo { + + private long id; + private String name; + + public ThreadInfo() { + name = ""; + id = -1; + } + + public ThreadInfo(ThreadInfo source) { + name = source.getName(); + id = source.getId(); + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public void setName(String name) { + Objects.requireNonNull(name); + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ThreadInfo that = (ThreadInfo) o; + + if (id != that.id) return false; + if (!name.equals(that.name)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + name.hashCode(); + return result; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/Timeline.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/Timeline.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.common.model.timeline; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Iterator; - -public class Timeline implements Iterable { - - private Deque infos; - - private String name; - private long id; - - public Timeline(String name, long id) { - this.name = name; - this.id = id; - infos = new ArrayDeque<>(); - } - - public String getName() { - return name; - } - - public long getId() { - return id; - } - - public TimelineInfo last() { - return infos.peekLast(); - } - - @Override - public Iterator iterator() { - return infos.iterator(); - } - - public TimelineInfo[] toArray() { - return (TimelineInfo[]) infos.toArray(); - } - - public void add(TimelineInfo info) { - infos.add(info); - } - - public int size() { - return infos.size(); - } -} - diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineDimensionModel.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineDimensionModel.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.common.model.timeline; - -import java.beans.PropertyChangeListener; - -import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; - -/** - * Model to define the size of the timeline with respect to the physical - * dimension of the {@link ThreadTimelineView}. - */ -public interface TimelineDimensionModel { - - /** - * This property defines the total length in milliseconds of the - * {@link ThreadTimelineView}. - */ - public static final String LENGTH_PROPERTY = "LENGTH_PROPERTY"; - - long getLengthInMillis(); - - public void addPropertyChangeListener(String property, PropertyChangeListener listener); -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineFactory.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,79 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.common.model.timeline; + +import com.redhat.thermostat.client.ui.Palette; +import com.redhat.thermostat.thread.model.ThreadState; + +/** + * + */ +public class TimelineFactory { + + public static TimelineProbe createTimelineProbe(ThreadState state) + { + Palette color = null; + + Thread.State threadState = Thread.State.valueOf(state.getState()); + switch (threadState) { + case NEW: + color = Palette.GREEN; + break; + + case RUNNABLE: + color = Palette.ADWAITA_BLU; + break; + + case BLOCKED: + color = Palette.VIOLET; + break; + + case WAITING: + color = Palette.GRANITA_ORANGE; + break; + + case TIMED_WAITING: + color = Palette.ADWAITA_BLU; + break; + + case TERMINATED: + color = Palette.LIGHT_GRAY; + break; + } + return new TimelineProbe(color, state.getState(), state.getTimeStamp()); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineGroupDataModel.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineGroupDataModel.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.common.model.timeline; - -import com.redhat.thermostat.common.model.Range; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - * - */ -public class TimelineGroupDataModel { - - public enum RangeChangeProperty { - TOTAL_RANGE, - PAGE_RANGE - } - - private Range totalRange; - private Range pageRange; - - private PropertyChangeSupport propertyChangeSupport; - - public TimelineGroupDataModel() { - this(new Range<>(0L, Long.MAX_VALUE), new Range(0L, Long.MAX_VALUE)); - } - - public TimelineGroupDataModel(Range totalRange, Range pageRange) { - this.totalRange = totalRange; - this.pageRange = pageRange; - propertyChangeSupport = new PropertyChangeSupport(this); - } - - public Range getTotalRange() { - return totalRange; - } - - public void setTotalRange(Range totalRange) { - Range old = this.totalRange; - this.totalRange = totalRange; - fireRangeChangeEvent(RangeChangeProperty.TOTAL_RANGE, old, this.totalRange); - } - - public Range getPageRange() { - return pageRange; - } - - public void setPageRange(Range pageRange) { - Range old = this.pageRange; - this.pageRange = pageRange; - fireRangeChangeEvent(RangeChangeProperty.PAGE_RANGE, old, this.pageRange); - } - - public void addPropertyChangeListener(RangeChangeProperty property, PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(property.name(), listener); - } - - private void fireRangeChangeEvent(RangeChangeProperty property, Range oldRange, Range newRange) { - propertyChangeSupport.firePropertyChange(property.name(), oldRange, newRange); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineInfo.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineInfo.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.common.model.timeline; - -import com.redhat.thermostat.client.ui.Palette; -import com.redhat.thermostat.common.model.Range; - -public class TimelineInfo { - - private Palette colour; - private Range timeStamp; - - public TimelineInfo() { - timeStamp = new Range<>(0l, Long.MAX_VALUE); - colour = Palette.BLACK; - } - - public TimelineInfo(Palette colour, Range timeStamp) { - this.timeStamp = timeStamp; - this.colour = colour; - } - - public Palette getColor() { - return colour; - } - - public void setColor(Palette colour) { - this.colour = colour; - } - - public void setRange(Range timestamp) { - this.timeStamp = timestamp; - } - - public Range getRange() { - return timeStamp; - } - - @Override - public String toString() { - return "TimelineInfo [colour=" + colour + ", timeStamp=" + timeStamp + "]"; - } -} - diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/model/timeline/TimelineProbe.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.common.model.timeline; + +import com.redhat.thermostat.client.ui.Palette; + +public class TimelineProbe { + + private String state; + private final long timeStamp; + private Palette colour; + + public TimelineProbe(Palette color, String state, long timeStamp) { + this.colour = color; + this.state = state; + this.timeStamp = timeStamp; + } + + public long getTimeStamp() { + return timeStamp; + } + + public Palette getColor() { + return colour; + } + + public String getState() { + return state; + } + + @Override + public String toString() { + return "TimelineInfo [colour = " + colour + ", " + timeStamp + "]"; + } +} + diff -r 504adea43d70 -r b1306c7c7422 thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/view/ThreadTimelineView.java --- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/view/ThreadTimelineView.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/view/ThreadTimelineView.java Thu Dec 11 11:44:42 2014 +0100 @@ -37,74 +37,21 @@ package com.redhat.thermostat.thread.client.common.view; import com.redhat.thermostat.client.core.views.BasicView; -import com.redhat.thermostat.common.ActionListener; -import com.redhat.thermostat.common.ActionNotifier; import com.redhat.thermostat.common.model.Range; -import com.redhat.thermostat.thread.client.common.model.timeline.Timeline; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineGroupDataModel; -import com.redhat.thermostat.thread.model.ThreadHeader; -import java.util.List; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; public abstract class ThreadTimelineView extends BasicView { - public static enum ThreadTimelineViewAction { - THREAD_TIMELINE_SELECTED, - SWITCH_TO_FOLLOW_MODE, - SWITCH_TO_STATIC_MODE, - } - - public static enum TimelineSelectorState { - FOLLOWING, - STATIC, - } - - protected final ActionNotifier threadTimelineNotifier; - - public ThreadTimelineView() { - threadTimelineNotifier = new ActionNotifier<>(this); - } - - public void addThreadSelectionActionListener(ActionListener listener) { - threadTimelineNotifier.addActionListener(listener); - } - - public void removeThreadSelectionActionListener(ActionListener listener) { - threadTimelineNotifier.removeActionListener(listener); - } - - protected void requestFollowMode() { - threadTimelineNotifier.fireAction(ThreadTimelineViewAction.SWITCH_TO_FOLLOW_MODE); - } + /** + * Add this thread to the list of threads visible on screen + */ + public abstract void addThread(ThreadInfo thread); - protected void requestStaticMode(Range pageRange) { - threadTimelineNotifier.fireAction(ThreadTimelineViewAction.SWITCH_TO_STATIC_MODE, pageRange); - } - - /** - * Returns the {@link TimelineGroupDataModel} for this view. - */ - public abstract TimelineGroupDataModel getGroupDataModel(); - - /** - * Ensures that the Timeline selector is in one of the possible states. - */ - public abstract void ensureTimelineState(TimelineSelectorState following); + public abstract void setTotalRange(Range totalRange); - /** - * Update the list of all {@link ThreadHeader} currently displayed by - * this view. - */ - public abstract void updateThreadList(List threads); + public abstract void addProbe(ThreadInfo info, TimelineProbe state); - /** - * Display the given {@link Timeline} associated to this {@link ThreadHeader}. - */ - public abstract void displayTimeline(ThreadHeader thread, Timeline threadTimeline); - - /** - * Notify the View that all the changes may be delivered to the rendering - * thread. - */ - public abstract void submitChanges(); + public abstract void clear(); } diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/CommonController.java --- a/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/CommonController.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/CommonController.java Thu Dec 11 11:44:42 2014 +0100 @@ -66,11 +66,13 @@ public void actionPerformed(ActionEvent actionEvent) { switch (actionEvent.getActionId()) { case VISIBLE: + onViewVisible(); timer.start(); break; case HIDDEN: timer.stop(); + onViewHidden(); break; default: @@ -79,5 +81,8 @@ } }); } + + protected void onViewVisible() {} + protected void onViewHidden() {} } diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationController.java --- a/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationController.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationController.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,9 +36,6 @@ package com.redhat.thermostat.thread.client.controller.impl; -import java.util.logging.Level; -import java.util.logging.Logger; - import com.redhat.thermostat.client.core.controllers.InformationServiceController; import com.redhat.thermostat.client.core.views.UIComponent; import com.redhat.thermostat.common.ActionEvent; @@ -54,11 +51,12 @@ import com.redhat.thermostat.thread.client.common.ThreadViewProvider; import com.redhat.thermostat.thread.client.common.collector.ThreadCollector; import com.redhat.thermostat.thread.client.common.collector.ThreadCollectorFactory; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; import com.redhat.thermostat.thread.client.common.view.ThreadTableView; +import com.redhat.thermostat.thread.client.common.view.ThreadTableView.ThreadSelectionAction; import com.redhat.thermostat.thread.client.common.view.ThreadView; -import com.redhat.thermostat.thread.client.common.view.ThreadTableView.ThreadSelectionAction; import com.redhat.thermostat.thread.client.common.view.ThreadView.ThreadAction; +import java.util.logging.Level; +import java.util.logging.Logger; public class ThreadInformationController implements InformationServiceController { @@ -70,18 +68,13 @@ private ApplicationService appService; - private TimelineDimensionModel timelineDimensionModel; - public ThreadInformationController(VmRef ref, ApplicationService appService, VmInfoDAO vmInfoDao, ThreadCollectorFactory collectorFactory, - ThreadViewProvider viewFactory, - TimelineDimensionModel timelineDimensionModel) + ThreadViewProvider viewFactory) { this.appService = appService; - this.timelineDimensionModel = timelineDimensionModel; - view = viewFactory.createView(); view.setApplicationService(appService, ref.getVmId() + "-" + ref.getHostRef().getAgentId()); @@ -169,8 +162,9 @@ threadTableController.initialize(); CommonController threadTimeline = - new ThreadTimelineController(view.createThreadTimelineView(), collector, - tf.createTimer(), timelineDimensionModel); + new ThreadTimelineController(view.createThreadTimelineView(), + collector, + tf.createTimer()); threadTimeline.initialize(); } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationServiceImpl.java --- a/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationServiceImpl.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationServiceImpl.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,15 +36,14 @@ package com.redhat.thermostat.thread.client.controller.impl; -import com.redhat.thermostat.common.Filter; import com.redhat.thermostat.client.core.NameMatchingRefFilter; import com.redhat.thermostat.client.core.controllers.InformationServiceController; import com.redhat.thermostat.common.ApplicationService; +import com.redhat.thermostat.common.Filter; import com.redhat.thermostat.storage.core.VmRef; import com.redhat.thermostat.storage.dao.VmInfoDAO; import com.redhat.thermostat.thread.client.common.ThreadViewProvider; import com.redhat.thermostat.thread.client.common.collector.ThreadCollectorFactory; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; import com.redhat.thermostat.thread.client.controller.ThreadInformationService; public class ThreadInformationServiceImpl implements ThreadInformationService { @@ -56,18 +55,16 @@ private VmInfoDAO vmInfoDao; private ThreadCollectorFactory collectorFactory; private ThreadViewProvider viewFactory; - private TimelineDimensionModel timelineDimensionModel; - public ThreadInformationServiceImpl(ApplicationService appService, VmInfoDAO vmInfoDao, - ThreadCollectorFactory collectorFactory, - ThreadViewProvider viewFactory, - TimelineDimensionModel timelineDimensionModel) + public ThreadInformationServiceImpl(ApplicationService appService, + VmInfoDAO vmInfoDao, + ThreadCollectorFactory collectorFactory, + ThreadViewProvider viewFactory) { this.service = appService; this.vmInfoDao = vmInfoDao; this.collectorFactory = collectorFactory; this.viewFactory = viewFactory; - this.timelineDimensionModel = timelineDimensionModel; } @Override @@ -77,7 +74,8 @@ @Override public InformationServiceController getInformationServiceController(VmRef ref) { - return new ThreadInformationController(ref, service, vmInfoDao, collectorFactory, viewFactory, timelineDimensionModel); + return new ThreadInformationController(ref, service, vmInfoDao, + collectorFactory, viewFactory); } @Override diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTableController.java --- a/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTableController.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTableController.java Thu Dec 11 11:44:42 2014 +0100 @@ -41,13 +41,6 @@ import com.redhat.thermostat.thread.client.common.ThreadTableBean; import com.redhat.thermostat.thread.client.common.collector.ThreadCollector; import com.redhat.thermostat.thread.client.common.view.ThreadTableView; -import com.redhat.thermostat.thread.model.ThreadContentionSample; -import com.redhat.thermostat.thread.model.ThreadHeader; -import com.redhat.thermostat.thread.model.ThreadState; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; public class ThreadTableController extends CommonController { @@ -55,7 +48,7 @@ private ThreadCollector collector; private Range lastRangeChecked; - private Map threadStates; +// private Map threadStates; public ThreadTableController(ThreadTableView threadTableView, ThreadCollector collector, @@ -64,7 +57,7 @@ super(timer, threadTableView); timer.setAction(new ThreadTableControllerAction()); - threadStates = new HashMap<>(); +// threadStates = new HashMap<>(); this.collector = collector; this.threadTableView = threadTableView; } @@ -74,78 +67,78 @@ @Override public void run() { - if (lastRangeChecked == null) { - lastRangeChecked = collector.getThreadStateTotalTimeRange(); - } else { - lastRangeChecked = new Range<>(lastRangeChecked.getMax(), - System.currentTimeMillis()); - } - - List tableBeans = new ArrayList<>(); - - List threads = collector.getThreads(); - - for (ThreadHeader thread : threads) { - - ThreadTableBean bean = threadStates.get(thread); - if (bean == null) { - bean = new ThreadTableBean(); - bean.setName(thread.getThreadName()); - bean.setId(thread.getThreadId()); - - threadStates.put(thread, bean); - } - - List states = collector.getThreadStates(thread, lastRangeChecked); - for (ThreadState state : states) { - - Thread.State threadState = Thread.State.valueOf(state.getState()); - - Range range = state.getRange(); - long currentRangeInCollection = range.getMax() - range.getMin(); - long currentStateInBean = getCurrentStateInBean(bean, threadState); - - currentStateInBean += currentRangeInCollection; - setCurrentStateInBean(bean, threadState, currentStateInBean); - - double totalRunningTime = bean.getRunningTime() + - bean.getMonitorTime() + - bean.getSleepingTime() + - bean.getWaitingTime(); - - if (totalRunningTime > 0) { - double percent = (bean.getRunningTime() / totalRunningTime) * 100; - bean.setRunningPercent(percent); - - percent = (bean.getWaitingTime() / totalRunningTime) * 100; - bean.setWaitingPercent(percent); - - percent = (bean.getMonitorTime() / totalRunningTime) * 100; - bean.setMonitorPercent(percent); - - percent = (bean.getSleepingTime() / totalRunningTime) * 100; - bean.setSleepingPercent(percent); - } - } - - // check the latest stat regarding wait and block count - ThreadContentionSample sample = collector.getLatestContentionSample(thread); - if (sample != null) { - bean.setBlockedCount(sample.getBlockedCount()); - bean.setWaitedCount(sample.getWaitedCount()); - } - - // finally, the time range for this thread - Range dataRange = collector.getThreadStateRange(thread); - if (dataRange != null) { - bean.setStartTimeStamp(dataRange.getMin()); - bean.setStopTimeStamp(dataRange.getMax()); - } - - tableBeans.add(bean); - } - - threadTableView.display(tableBeans); +// if (lastRangeChecked == null) { +// lastRangeChecked = collector.getThreadStateTotalTimeRange(); +// } else { +// lastRangeChecked = new Range<>(lastRangeChecked.getMax(), +// System.currentTimeMillis()); +// } +// +// List tableBeans = new ArrayList<>(); +// +// List threads = collector.getThreads(); +// +// for (ThreadHeader thread : threads) { +// +// ThreadTableBean bean = threadStates.get(thread); +// if (bean == null) { +// bean = new ThreadTableBean(); +// bean.setName(thread.getThreadName()); +// bean.setId(thread.getThreadId()); +// +// threadStates.put(thread, bean); +// } +// +// List states = collector.getThreadStates(thread, lastRangeChecked); +// for (ThreadState state : states) { +// +// Thread.State threadState = Thread.State.valueOf(state.getState()); +// +// Range range = state.getRange(); +// long currentRangeInCollection = range.getMax() - range.getMin(); +// long currentStateInBean = getCurrentStateInBean(bean, threadState); +// +// currentStateInBean += currentRangeInCollection; +// setCurrentStateInBean(bean, threadState, currentStateInBean); +// +// double totalRunningTime = bean.getRunningTime() + +// bean.getMonitorTime() + +// bean.getSleepingTime() + +// bean.getWaitingTime(); +// +// if (totalRunningTime > 0) { +// double percent = (bean.getRunningTime() / totalRunningTime) * 100; +// bean.setRunningPercent(percent); +// +// percent = (bean.getWaitingTime() / totalRunningTime) * 100; +// bean.setWaitingPercent(percent); +// +// percent = (bean.getMonitorTime() / totalRunningTime) * 100; +// bean.setMonitorPercent(percent); +// +// percent = (bean.getSleepingTime() / totalRunningTime) * 100; +// bean.setSleepingPercent(percent); +// } +// } +// +// // check the latest stat regarding wait and block count +// ThreadContentionSample sample = collector.getLatestContentionSample(thread); +// if (sample != null) { +// bean.setBlockedCount(sample.getBlockedCount()); +// bean.setWaitedCount(sample.getWaitedCount()); +// } +// +// // finally, the time range for this thread +// Range dataRange = collector.getThreadStateRange(thread); +// if (dataRange != null) { +// bean.setStartTimeStamp(dataRange.getMin()); +// bean.setStopTimeStamp(dataRange.getMax()); +// } +// +// tableBeans.add(bean); +// } +// +// threadTableView.display(tableBeans); } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTimelineController.java --- a/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTimelineController.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTimelineController.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,20 +36,19 @@ package com.redhat.thermostat.thread.client.controller.impl; -import com.redhat.thermostat.common.ActionEvent; -import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.model.Range; -import com.redhat.thermostat.thread.client.common.chart.ChartColors; +import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler; import com.redhat.thermostat.thread.client.common.collector.ThreadCollector; -import com.redhat.thermostat.thread.client.common.model.timeline.Timeline; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineFactory; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; -import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView.ThreadTimelineViewAction; -import com.redhat.thermostat.thread.model.ThreadHeader; +import com.redhat.thermostat.thread.model.SessionID; import com.redhat.thermostat.thread.model.ThreadState; -import java.util.List; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; public class ThreadTimelineController extends CommonController { @@ -57,126 +56,115 @@ private ThreadTimelineView view; private ThreadCollector collector; - - private static final long EXTRA_TIMELINE_BUFFER = 2000; - - private final String lock = new String("ThreadTimelineController"); + + private static final String lock = new String("ThreadTimelineController"); + + private boolean requestClear; - private boolean followMode; - - private TimelineDimensionModel timelineDimensionModel; - private Range pageRangeInStaticMode; - - public ThreadTimelineController(ThreadTimelineView view, ThreadCollector collector, Timer timer, - TimelineDimensionModel timelineDimensionModel) { + public ThreadTimelineController(ThreadTimelineView view, + ThreadCollector collector, + Timer timer) + { super(timer, view); timer.setAction(new ThreadTimelineControllerAction()); this.view = view; - this.view.addThreadSelectionActionListener(new ThreadTimelineSelectedAction()); this.collector = collector; - followMode = false; - - this.timelineDimensionModel = timelineDimensionModel; } - private class ThreadTimelineSelectedAction implements ActionListener { - - @Override - public void actionPerformed(ActionEvent actionEvent) { - switch (actionEvent.getActionId()) { - case THREAD_TIMELINE_SELECTED: - break; - - case SWITCH_TO_FOLLOW_MODE: - synchronized (lock) { - followMode = true; - } - view.ensureTimelineState(ThreadTimelineView.TimelineSelectorState.FOLLOWING); - break; - - case SWITCH_TO_STATIC_MODE: - synchronized (lock) { - followMode = false; - pageRangeInStaticMode = (Range) actionEvent.getPayload(); - } - view.ensureTimelineState(ThreadTimelineView.TimelineSelectorState.STATIC); - break; - - default: - break; - } + private class ThreadTimelineControllerAction implements Runnable { + + private Range range; + private Range lastRange; + private ThreadStateResultHandler threadStateResultHandler; + private long lastUpdate; + + private SessionID lastSession; + + public ThreadTimelineControllerAction() { + lastUpdate = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1); + threadStateResultHandler = new ThreadStateResultHandler(); } - } - - private class ThreadTimelineControllerAction implements Runnable { + + private void resetState() { + view.clear(); + lastRange = null; + lastUpdate = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1); + threadStateResultHandler.knownStates.clear(); + threadStateResultHandler.key = new ThreadInfo(); + } @Override public void run() { - + synchronized (lock) { - long timelineLength = timelineDimensionModel.getLengthInMillis(); + // FIXME: show only the last sessions for now, support for + // filtering over sessions will come later + SessionID session = collector.getLastThreadSession(); + if (session == null) { + // ok, no data, let's skip this round + return; + } - Range totalRange = collector.getThreadStateTotalTimeRange(); + if (lastSession == null || + !session.get().equals(lastSession.get())) + { + // since we only visualise one sessions at a time and this + // is a new session needs, let's clear the view + resetState(); + } + lastSession = session; + + // get the full range of known timelines per vm + Range totalRange = collector.getThreadRange(session); if (totalRange == null) { - // that simply means we don't have data yet, let's just skip - // this loop + // this just means we don't have any data yet return; } - view.getGroupDataModel().setTotalRange(totalRange); - List threads = collector.getThreads(); + if (!totalRange.equals(lastRange)) { + view.setTotalRange(totalRange); + } + lastRange = totalRange; - view.updateThreadList(threads); + range = new Range<>(lastUpdate, totalRange.getMax()); + lastUpdate = totalRange.getMax(); - Range pageRange = null; - Range visibleRange = null; - List states = null; - if (followMode || pageRangeInStaticMode == null) { - // get the latest info available, ensure a little of extra - // buffer so that we are sure to have continuity around the - // timeline edges - long max = totalRange.getMax(); - long pageMin = max - timelineLength; - pageRange = new Range<>(pageMin, totalRange.getMax()); + collector.getThreadStates(session, + threadStateResultHandler, + range); + threadStateResultHandler.results = 0; + } + } + } - long min = pageMin - EXTRA_TIMELINE_BUFFER; - visibleRange = new Range<>(min, max); - - view.getGroupDataModel().setPageRange(pageRange); + private class ThreadStateResultHandler implements ResultHandler { + private ThreadInfo key; + private Set knownStates; - } else { - long max = pageRangeInStaticMode.getMax() + EXTRA_TIMELINE_BUFFER; - long pageMin = max - timelineLength; - long min = pageMin - EXTRA_TIMELINE_BUFFER; - visibleRange = new Range<>(min, max); - view.getGroupDataModel().setPageRange(pageRangeInStaticMode); - } + int results; - long sampleStart = 0l; - if (_DEBUG_BLOCK_TIMING_) { - sampleStart = System.currentTimeMillis(); - } + public ThreadStateResultHandler() { + this.key = new ThreadInfo(); + knownStates = new HashSet<>(); + } + + @Override + public void onResult(ThreadState state) { + + results++; - for (ThreadHeader thread : threads) { - states = collector.getThreadStates(thread, visibleRange); - Timeline threadTimeline = new Timeline(thread.getThreadName(), thread.getThreadId()); - for (ThreadState state : states) { - TimelineInfo info = new TimelineInfo(); - info.setColor(ChartColors.getPaletteColor(state.getState())); - info.setRange(state.getRange()); - threadTimeline.add(info); - } - view.displayTimeline(thread, threadTimeline); - } + key.setName(state.getName()); + key.setId(state.getId()); - if (_DEBUG_BLOCK_TIMING_) { - long sampleStop = System.currentTimeMillis(); - System.err.println("getThreadStates time: " + (sampleStop - sampleStart)); - } + ThreadInfo info = new ThreadInfo(key); + if (!knownStates.contains(key)) { + view.addThread(info); + knownStates.add(info); + } - view.submitChanges(); - } + TimelineProbe probe = TimelineFactory.createTimelineProbe(state); + view.addProbe(info, probe); } } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/osgi/Activator.java --- a/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/osgi/Activator.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/main/java/com/redhat/thermostat/thread/client/controller/osgi/Activator.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,16 +36,6 @@ package com.redhat.thermostat.thread.client.controller.osgi; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.Map; -import java.util.Objects; - -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - import com.redhat.thermostat.client.core.InformationService; import com.redhat.thermostat.common.ApplicationService; import com.redhat.thermostat.common.Constants; @@ -57,6 +47,13 @@ import com.redhat.thermostat.thread.client.common.collector.ThreadCollectorFactory; import com.redhat.thermostat.thread.client.controller.ThreadInformationService; import com.redhat.thermostat.thread.client.controller.impl.ThreadInformationServiceImpl; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Map; +import java.util.Objects; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; public class Activator implements BundleActivator { @@ -69,7 +66,6 @@ ApplicationService.class, VmInfoDAO.class, ThreadViewProvider.class, - TimelineDimensionModel.class, }; Action action = new Action() { @@ -82,11 +78,13 @@ ApplicationService applicationService = (ApplicationService) services.get(ApplicationService.class.getName()); VmInfoDAO vmInfoDao = Objects.requireNonNull((VmInfoDAO) services.get(VmInfoDAO.class.getName())); ThreadViewProvider viewFactory = (ThreadViewProvider) services.get(ThreadViewProvider.class.getName()); - TimelineDimensionModel timelineDimensionModel = (TimelineDimensionModel) services.get(TimelineDimensionModel.class.getName()); - ThreadInformationService vmInfoService = new ThreadInformationServiceImpl(applicationService, vmInfoDao, - collectorFactory, viewFactory, - timelineDimensionModel); + ThreadInformationService vmInfoService = + new ThreadInformationServiceImpl(applicationService, + vmInfoDao, + collectorFactory, + viewFactory); + Dictionary properties = new Hashtable<>(); properties.put(Constants.GENERIC_SERVICE_CLASSNAME, VmRef.class.getName()); properties.put(InformationService.KEY_SERVICE_ID, ThreadInformationService.SERVICE_ID); diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationControllerTest.java --- a/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationControllerTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadInformationControllerTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -50,7 +50,6 @@ import com.redhat.thermostat.thread.client.common.ThreadViewProvider; import com.redhat.thermostat.thread.client.common.collector.ThreadCollector; import com.redhat.thermostat.thread.client.common.collector.ThreadCollectorFactory; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; import com.redhat.thermostat.thread.client.common.view.ThreadCountView; import com.redhat.thermostat.thread.client.common.view.ThreadTableView; import com.redhat.thermostat.thread.client.common.view.ThreadTableView.ThreadSelectionAction; @@ -87,13 +86,9 @@ private ThreadTimelineView threadTimelineView; private ThreadCountView threadCountView; - private TimelineDimensionModel timelineDimensionModel; - @Before public void setUp() { - timelineDimensionModel = mock(TimelineDimensionModel.class); - appService = mock(ApplicationService.class); vmInfo = mock(VmInfo.class); when(vmInfo.isAlive()).thenReturn(true); @@ -154,8 +149,7 @@ controller = new ThreadInformationController(ref, appService, vmInfoDao, collectorFactory, - viewFactory, - timelineDimensionModel); + viewFactory); } @Test @@ -195,8 +189,7 @@ controller = new ThreadInformationController(ref, appService, vmInfoDao, collectorFactory, - viewFactory, - timelineDimensionModel); + viewFactory); verify(collector).isHarvesterCollecting(); verify(view, times(1)).setRecording(false, false); diff -r 504adea43d70 -r b1306c7c7422 thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTimelineControllerTest.java --- a/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTimelineControllerTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-controllers/src/test/java/com/redhat/thermostat/thread/client/controller/impl/ThreadTimelineControllerTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -38,21 +38,17 @@ import com.redhat.thermostat.common.Timer; import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler; import com.redhat.thermostat.thread.client.common.collector.ThreadCollector; -import com.redhat.thermostat.thread.client.common.model.timeline.Timeline; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineGroupDataModel; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; -import com.redhat.thermostat.thread.model.ThreadHeader; -import java.util.ArrayList; -import java.util.List; +import com.redhat.thermostat.thread.model.SessionID; +import com.redhat.thermostat.thread.model.ThreadState; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; -import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -60,72 +56,109 @@ public class ThreadTimelineControllerTest { - private ArgumentCaptor timerActionCaptor; - private Timer timer; - private ThreadTimelineView view; private ThreadCollector collector; - private TimelineDimensionModel timelineDimensionModel; - private TimelineGroupDataModel groupDataModel; - - private Range totalRange = new Range<>(0l, 30_000l); + private Timer timer; + private SessionID session; @Before - public void setUp() throws Exception { - timer = mock(Timer.class); - timerActionCaptor = ArgumentCaptor.forClass(Runnable.class); - doNothing().when(timer).setAction(timerActionCaptor.capture()); - + public void setup() { view = mock(ThreadTimelineView.class); collector = mock(ThreadCollector.class); - timelineDimensionModel = mock(TimelineDimensionModel.class); - when(timelineDimensionModel.getLengthInMillis()).thenReturn(25_000l); - when(collector.getThreadStateTotalTimeRange()).thenReturn(totalRange); + timer = mock(Timer.class); + session = mock(SessionID.class); + + when(collector.getLastThreadSession()).thenReturn(session); + } + + @Test + public void verifySession() { + ArgumentCaptor captor = + ArgumentCaptor.forClass(Runnable.class); + doNothing().when(timer).setAction(captor.capture()); + + ThreadTimelineController controller = + new ThreadTimelineController(view, collector, timer); + Runnable timerAction = captor.getValue(); + + timerAction.run(); - groupDataModel = mock(TimelineGroupDataModel.class); - when(view.getGroupDataModel()).thenReturn(groupDataModel); + verify(collector).getLastThreadSession(); + } + + @Test + public void verifyRange() { + ArgumentCaptor captor = + ArgumentCaptor.forClass(Runnable.class); + doNothing().when(timer).setAction(captor.capture()); + + Range range = new Range<>(0l, 10l); + when(collector.getThreadRange(session)).thenReturn(range); + + ThreadTimelineController controller = + new ThreadTimelineController(view, collector, timer); + Runnable timerAction = captor.getValue(); + + timerAction.run(); + + verify(collector).getThreadRange(session); + verify(view).setTotalRange(range); } @Test - public void testTimelineController() { - - Range pageRange = new Range<>(5_000l, 30_000l); - ArgumentCaptor pageRangeCaptor = ArgumentCaptor.forClass(Range.class); - doNothing().when(groupDataModel).setPageRange(pageRangeCaptor.capture()); + public void testAllBeansAreLoaded() { + ArgumentCaptor captor = + ArgumentCaptor.forClass(Runnable.class); + doNothing().when(timer).setAction(captor.capture()); - ThreadHeader thread1 = mock(ThreadHeader.class); - ThreadHeader thread2 = mock(ThreadHeader.class); - - List threads = new ArrayList<>(); + ArgumentCaptor captor2 = + ArgumentCaptor.forClass(ResultHandler.class); + doNothing().when(collector).getThreadStates(any(SessionID.class), + captor2.capture(), + any(Range.class)); - threads.add(thread1); - threads.add(thread2); - - when(collector.getThreads()).thenReturn(threads); + Range range = new Range<>(0l, 10l); + when(collector.getThreadRange(session)).thenReturn(range); ThreadTimelineController controller = - new ThreadTimelineController(view, collector, timer, - timelineDimensionModel); + new ThreadTimelineController(view, collector, timer); + Runnable timerAction = captor.getValue(); - Runnable controllerRunnable = timerActionCaptor.getValue(); + timerAction.run(); + + ResultHandler handler = captor2.getValue(); - controllerRunnable.run(); + ThreadState state0 = mock(ThreadState.class); + when(state0.getName()).thenReturn("state0"); + when(state0.getId()).thenReturn(0l); + when(state0.getState()).thenReturn("NEW"); - // check that the thread list is correctly passed to the view - verify(view).updateThreadList(threads); + ThreadState state1 = mock(ThreadState.class); + when(state1.getName()).thenReturn("state1"); + when(state1.getId()).thenReturn(1l); + when(state1.getState()).thenReturn("NEW"); - // verify group model gets updated with the page and total data - verify(groupDataModel).setTotalRange(totalRange); - Range pageRangeResult = pageRangeCaptor.getValue(); - assertEquals(pageRangeResult, pageRange); + ThreadState state2 = mock(ThreadState.class); + when(state2.getName()).thenReturn("state2"); + when(state2.getId()).thenReturn(2l); + when(state2.getState()).thenReturn("NEW"); + + handler.onResult(state0); + handler.onResult(state1); + handler.onResult(state2); - // check that the thread state is queried for each of the thread headers - verify(collector).getThreadStates(eq(thread1), any(Range.class)); - verify(collector).getThreadStates(eq(thread2), any(Range.class)); + ThreadInfo info = new ThreadInfo(); + info.setName("state0"); + info.setId(0l); + + verify(view).addThread(info); - verify(view).displayTimeline(eq(thread1), any(Timeline.class)); - verify(view).displayTimeline(eq(thread2), any(Timeline.class)); + info.setName("state1"); + info.setId(1l); + verify(view).addThread(info); - verify(view).submitChanges(); + info.setName("state2"); + info.setId(2l); + verify(view).addThread(info); } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/pom.xml --- a/thread/client-swing/pom.xml Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/pom.xml Thu Dec 11 11:44:42 2014 +0100 @@ -115,8 +115,10 @@ com.redhat.thermostat.thread.client.swing.osgi, com.redhat.thermostat.thread.client.swing.impl, - com.redhat.thermostat.thread.client.swing.impl.timeline, - com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar, + com.redhat.thermostat.thread.client.swing.impl.timeline, + com.redhat.thermostat.thread.client.swing.impl.timeline.model, + com.redhat.thermostat.thread.client.swing.experimental.components, + com.redhat.thermostat.thread.client.swing.experimental.utils, <_nouses>true diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/SwingThreadViewService.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/SwingThreadViewService.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/SwingThreadViewService.java Thu Dec 11 11:44:42 2014 +0100 @@ -40,21 +40,18 @@ import com.redhat.thermostat.thread.client.common.ThreadViewProvider; import com.redhat.thermostat.thread.client.common.view.ThreadView; import com.redhat.thermostat.thread.client.swing.impl.SwingThreadView; -import com.redhat.thermostat.thread.client.swing.impl.timeline.SwingTimelineDimensionModel; public class SwingThreadViewService implements ThreadViewProvider { private UIDefaults uiDefaults; - private SwingTimelineDimensionModel dimensionModel; - - public SwingThreadViewService(UIDefaults uiDefaults, SwingTimelineDimensionModel dimensionModel) { + + public SwingThreadViewService(UIDefaults uiDefaults) { this.uiDefaults = uiDefaults; - this.dimensionModel = dimensionModel; } @Override public ThreadView createView() { - return new SwingThreadView(uiDefaults, dimensionModel); + return new SwingThreadView(uiDefaults); } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/components/ContentPane.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/components/ContentPane.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.experimental.components; + +import com.redhat.thermostat.client.ui.Palette; +import java.awt.BorderLayout; +import javax.swing.JPanel; + +/** + * Basic panel that should be used for all custom panels in Thermostat. + */ +public class ContentPane extends JPanel { + public ContentPane() { + setBackground(Palette.WHITE.getColor()); + setLayout(new BorderLayout()); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/components/DataPane.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/components/DataPane.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,82 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.experimental.components; + +import com.redhat.thermostat.client.swing.GraphicsUtils; +import com.redhat.thermostat.client.ui.Palette; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; + +public class DataPane extends ContentPane { + + private final Palette top; + private final Palette bottom; + + public DataPane() { + this(Palette.WHITE, Palette.LIGHT_GRAY); + } + + public DataPane(Palette top, Palette bottom) { + this.top = top; + this.bottom = bottom; + setLayout(new BorderLayout()); + } + + @Override + protected void paintComponent(Graphics g) { + + Color top = this.top.getColor(); + Color bottom = this.bottom.getColor(); + Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); + final float[] fractions = {.0f, .2f, .4f, 1.f}; + final Color[] colors = { + top, + top, + top, + bottom, + }; + LinearGradientPaint paint = new LinearGradientPaint(0, 0, 0, + getHeight(), + fractions, colors); + graphics.setPaint(paint); + graphics.fillRect(0, 0, getWidth(), getHeight()); + graphics.dispose(); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/components/Separator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/components/Separator.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,197 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.experimental.components; + +import com.redhat.thermostat.client.swing.GraphicsUtils; +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.ui.Palette; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.LinearGradientPaint; +import java.awt.Rectangle; +import javax.swing.border.AbstractBorder; + +/** + * A configurable border that separates two components. + */ +public class Separator extends AbstractBorder { + + public enum Type { + SOLID, + SMOOTH, + } + + public enum Side { + TOP, + BOTTOM, + LEFT, + RIGHT, + } + + private Side side; + + private UIDefaults defaults; + private Type type; + + public Separator(UIDefaults defaults) { + this(defaults, Side.TOP, Type.SOLID); + } + + public Separator(UIDefaults defaults, Side side, Type type) { + this.side = side; + this.defaults = defaults; + this.type = type; + } + + private void paintSolidBorder(Graphics2D graphics, int x, int y, int width, int height) { + + Rectangle fillRect = new Rectangle(x, y, width, height); + + switch (side) { + + default: + case TOP: + graphics.setColor(Palette.DARK_GRAY.getColor()); + graphics.drawLine(x, y + 1, x + width - 1, y + 1); + graphics.setPaint(Palette.WHITE.getColor()); + graphics.drawLine(x, y, x + width - 1, y); + break; + + case BOTTOM: + graphics.setColor(Palette.WHITE.getColor()); + graphics.drawLine(x, y + height - 1, x + width - 1, y + height - 1); + graphics.setPaint(Palette.DARK_GRAY.getColor());//defaults.getComponentBGColor()); + graphics.drawLine(x, y + height - 2, x + width - 1, y + height - 2); + break; + + case LEFT: + graphics.setColor(Palette.WHITE.getColor()); + graphics.drawLine(x, y, x, y + height - 1); + graphics.setPaint(Palette.DARK_GRAY.getColor()); + graphics.drawLine(x + 1, y, x + 1, y + height - 1); + break; + + case RIGHT: + graphics.setColor(Palette.WHITE.getColor()); + graphics.drawLine(x + width - 1, y, x + width - 1, y + height - 1); + graphics.setPaint(Palette.DARK_GRAY.getColor()); + graphics.drawLine(x + width - 2, y, x + width - 2, y + height - 1); + break; + } + } + + private void paintSmoothBorder(Graphics2D graphics, int x, int y, int width, int height) { + + final float[] fractions = {.0f, .4f, .6f, 1.f}; + final Color[] colors = { + (Color) defaults.getComponentBGColor(), + (Color) defaults.getReferenceFieldIconColor(), + (Color) defaults.getReferenceFieldIconColor(), + (Color) defaults.getComponentBGColor(), + }; + + Rectangle gradientRect = new Rectangle(x, y, width, height); + Rectangle fillRect = new Rectangle(x, y, width, height); + + switch (side) { + default: + case TOP: + gradientRect.y = 0; + gradientRect.height = 0; + fillRect.height = 1; + break; + + case BOTTOM: + gradientRect.y = 0; + gradientRect.height = 0; + fillRect.y = y + height - 1; + fillRect.height = 1; + break; + + case LEFT: + gradientRect.x = 0; + gradientRect.width = 0; + fillRect.width = 1; + break; + + case RIGHT: + gradientRect.x = 0; + gradientRect.width = 0; + fillRect.x = x + width - 1; + fillRect.width = 1; + break; + } + + LinearGradientPaint paint = + new LinearGradientPaint(gradientRect.x, + gradientRect.y, gradientRect.width, + gradientRect.height, fractions, colors); + graphics.setPaint(paint); + graphics.fill(fillRect); + + graphics.dispose(); + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + + Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); + switch (type) { + case SOLID: + paintSolidBorder(graphics, x, y, width, height); + break; + + case SMOOTH: + paintSmoothBorder(graphics, x, y, width, height); + break; + } + } + + @Override + public Insets getBorderInsets(Component c, Insets insets) { + + insets.top = 2; + insets.left = 0; + insets.right = 0; + insets.bottom = 0; + + return insets; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/utils/EDTHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/experimental/utils/EDTHelper.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.experimental.utils; + +import com.redhat.thermostat.client.swing.EdtHelper; +import com.redhat.thermostat.common.utils.LoggingUtils; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.SwingUtilities; + +/** + * + */ +public class EDTHelper { + private static final Logger logger = LoggingUtils.getLogger(EDTHelper.class); + private EdtHelper delegate; + public EDTHelper() { + delegate = new EdtHelper(); + } + + public T callAndWait(Callable c) { + T result = null; + try { + result = delegate.callAndWait(c); + + } catch (InvocationTargetException | InterruptedException e) { + logger.log(Level.WARNING, "Exception while waiting for task", e); + } + return result; + } + + public void callLater(Runnable run) { + SwingUtilities.invokeLater(run); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadTimelineView.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadTimelineView.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadTimelineView.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,130 +36,64 @@ package com.redhat.thermostat.thread.client.swing.impl; -import com.redhat.thermostat.client.swing.ComponentVisibleListener; import com.redhat.thermostat.client.swing.SwingComponent; import com.redhat.thermostat.client.swing.UIDefaults; -import com.redhat.thermostat.client.swing.components.ThermostatScrollPane; import com.redhat.thermostat.client.swing.experimental.ComponentVisibilityNotifier; import com.redhat.thermostat.common.model.Range; -import com.redhat.thermostat.thread.client.common.model.timeline.Timeline; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineGroupDataModel; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; -import com.redhat.thermostat.thread.client.swing.impl.timeline.HeaderController; -import com.redhat.thermostat.thread.client.swing.impl.timeline.SwingTimelineDimensionModel; -import com.redhat.thermostat.thread.client.swing.impl.timeline.ThreadTimelineHeader; -import com.redhat.thermostat.thread.client.swing.impl.timeline.TimelineCellRenderer; +import com.redhat.thermostat.thread.client.swing.experimental.utils.EDTHelper; +import com.redhat.thermostat.thread.client.swing.impl.timeline.RangeComponent; import com.redhat.thermostat.thread.client.swing.impl.timeline.TimelineComponent; -import com.redhat.thermostat.thread.client.swing.impl.timeline.TimelineGroupThreadConverter; -import com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar.SwingTimelineScrollBarController; -import com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar.TimelineScrollBar; -import com.redhat.thermostat.thread.model.ThreadHeader; - -import java.awt.BorderLayout; +import com.redhat.thermostat.thread.client.swing.impl.timeline.TimelineContainer; +import com.redhat.thermostat.thread.client.swing.impl.timeline.TimelineViewComponent; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangedTimelineProbe; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineDateFormatter; import java.awt.Component; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; import java.util.HashMap; -import java.util.List; import java.util.Map; -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; - public class SwingThreadTimelineView extends ThreadTimelineView implements SwingComponent { - private SwingTimelineScrollBarController scrollBarController; - private Map timelineMap; + private final UIDefaults uiDefaults; + private TimelineViewComponent contentPane; - private TimelineGroupThreadConverter groupDataModel; - private SwingTimelineDimensionModel dimensionModel; + private ComponentVisibilityNotifier visibilityNotifier; - private DefaultListModel timelineModel; - private JList timelines; + private Map timelines; + + private EDTHelper edt; - private ThreadTimelineHeader header; - private JPanel contentPane; - private JScrollPane scrollPane; + public SwingThreadTimelineView(UIDefaults uiDefaults) { + this.uiDefaults = uiDefaults; - public SwingThreadTimelineView(UIDefaults uiDefaults, - final SwingTimelineDimensionModel dimensionModel) - { - timelineMap = new HashMap<>(); + edt = new EDTHelper(); + timelines = new HashMap<>(); + + this.contentPane = new TimelineViewComponent(uiDefaults); + clear(); - this.dimensionModel = dimensionModel; + visibilityNotifier = new ComponentVisibilityNotifier(); + visibilityNotifier.initialize(contentPane, notifier); + } - TimelineGroupDataModel realGDM = new TimelineGroupDataModel(); - groupDataModel = new TimelineGroupThreadConverter(realGDM); - - contentPane = new JPanel(); - new ComponentVisibilityNotifier().initialize(contentPane, notifier); - contentPane.addHierarchyListener(new ComponentVisibleListener() { + @Override + public void addThread(final ThreadInfo thread) { + edt.callLater(new Runnable() { @Override - public void componentShown(Component component) { - // TODO: this should be retrieved from state properties - requestFollowMode(); - } - - @Override - public void componentHidden(Component component) { - // TODO should requestFollowMode be disabled? + public void run() { + if (!timelines.containsKey(thread)) { + TimelineComponent timeline = + new TimelineComponent(uiDefaults, thread, + contentPane.getModel()); + timeline.initComponents(); + + timelines.put(thread, timeline); + contentPane.addTimeline(timeline); + } } }); - - contentPane.setLayout(new BorderLayout(0, 0)); - - JPanel timelineBottomControls = new JPanel(); - timelineBottomControls.setLayout(new BorderLayout(0, 0)); - - TimelineScrollBar scrollbar = setupTimelineScrollBar(uiDefaults); - timelineBottomControls.add(scrollbar, BorderLayout.NORTH); - - createScrollPane(); - contentPane.add(scrollPane, BorderLayout.CENTER); - - ThreadTimelineLegendPanel timelineLegend = new ThreadTimelineLegendPanel(); - timelineBottomControls.add(timelineLegend, BorderLayout.SOUTH); - - contentPane.add(timelineBottomControls, BorderLayout.SOUTH); - contentPane.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(ComponentEvent e) { - dimensionModel.setWidth(contentPane.getWidth()); - } - }); - } - - TimelineScrollBar setupTimelineScrollBar(UIDefaults uiDefaults) { - - TimelineScrollBar scrollbar = new TimelineScrollBar(uiDefaults); - scrollBarController = new SwingTimelineScrollBarController(this, scrollbar, - groupDataModel, - dimensionModel); - scrollBarController.initScrollbar(this); - return scrollbar; - } - - private void createScrollPane() { - - timelineModel = new DefaultListModel<>(); - timelines = new JList<>(timelineModel); - timelines.setCellRenderer(new TimelineCellRenderer()); - timelines.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - - scrollPane = new ThermostatScrollPane(timelines); - scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - - header = new ThreadTimelineHeader(groupDataModel, dimensionModel); - header.setName("TimelineRulerHeader_thread"); - - scrollPane.setColumnHeaderView(header); - groupDataModel.addPropertyChangeListener(TimelineGroupDataModel.RangeChangeProperty.PAGE_RANGE, - new HeaderController(header, timelines)); } @Override @@ -168,70 +102,64 @@ } @Override - public void ensureTimelineState(final TimelineSelectorState following) { - SwingUtilities.invokeLater(new Runnable() { + public void setTotalRange(final Range totalRange) { + edt.callLater(new Runnable() { @Override public void run() { - scrollBarController.ensureTimelineState(following); + contentPane.getModel().setRange(totalRange); } }); } - + @Override - public void updateThreadList(final List threads) { - SwingUtilities.invokeLater(new Runnable() { + public void clear() { + edt.callLater(new Runnable() { @Override public void run() { - // TODO: remove timelines that are not in the list, but - // still present onscreen - for (ThreadHeader thread : threads) { - if (!timelineMap.containsKey(thread)) { - TimelineComponent timeline = - new TimelineComponent(groupDataModel, - dimensionModel, - thread.getThreadName()); - timelineMap.put(thread, timeline); - timelineModel.addElement(timeline); - } - } + timelines.clear(); + contentPane.removeAll(); + contentPane.initComponents(); + contentPane.revalidate(); } }); } @Override - public TimelineGroupDataModel getGroupDataModel() { - return groupDataModel.getDataModel(); - } - - @Override - public void displayTimeline(final ThreadHeader thread, - final Timeline threadTimeline) - { - SwingUtilities.invokeLater(new Runnable() { + public void addProbe(final ThreadInfo info, final TimelineProbe state) { + edt.callLater(new Runnable() { @Override public void run() { - TimelineComponent timeline = timelineMap.get(thread); - if (timeline != null) { - timeline.setTimeline(threadTimeline); + TimelineComponent component = timelines.get(info); + TimelineContainer timelineContainer = + component.getTimelineContainer(); + RangeComponent rangeComponent = + timelineContainer.getLastRangeComponent(); + + if (rangeComponent == null) { + setRangedComponent(state, timelineContainer); + + } else { + RangedTimelineProbe probe = rangeComponent.getInfo(); + probe.setProbeEnd(state.getTimeStamp()); + if (!probe.getColor().equals(state.getColor())) { + setRangedComponent(state, timelineContainer); + } } + timelineContainer.revalidate(); } }); } - @Override - public void submitChanges() { - contentPane.revalidate(); - } - - // rise visibility so other classes here can use those methods through us - @Override - public void requestFollowMode() { - super.requestFollowMode(); - } - - @Override - public void requestStaticMode(Range pageRange) { - super.requestStaticMode(pageRange); + private void setRangedComponent(TimelineProbe state, + TimelineContainer timelineContainer) + { + RangedTimelineProbe probe = + new RangedTimelineProbe(state, state.getTimeStamp()); + RangeComponent rangeComponent = new RangeComponent(probe); + rangeComponent.setToolTipText(state.getState() + " - " + + TimelineDateFormatter.format(state. + getTimeStamp())); + timelineContainer.add(rangeComponent); } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadView.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadView.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadView.java Thu Dec 11 11:44:42 2014 +0100 @@ -50,7 +50,6 @@ import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; import com.redhat.thermostat.thread.client.common.view.ThreadView; import com.redhat.thermostat.thread.client.common.view.VmDeadLockView; -import com.redhat.thermostat.thread.client.swing.impl.timeline.SwingTimelineDimensionModel; import java.awt.Component; import java.awt.event.ItemEvent; @@ -86,13 +85,11 @@ private int threadDetailsPaneID = 0; private UIDefaults uiDefaults; - private SwingTimelineDimensionModel dimensionModel; - - public SwingThreadView(UIDefaults uiDefaults, SwingTimelineDimensionModel dimensionModel) { + + public SwingThreadView(UIDefaults uiDefaults) { this.uiDefaults = uiDefaults; - this.dimensionModel = dimensionModel; - + panel = new ThreadMainPanel(); // TODO use ComponentVisiblityNotifier instead // sadly, the BasicView.notifier field can not be accessed here @@ -158,7 +155,7 @@ topPane = new ThermostatTabbedPane(); topPane.setName("topTabbedPane"); - threadTimelineView = new SwingThreadTimelineView(uiDefaults, dimensionModel); + threadTimelineView = new SwingThreadTimelineView(uiDefaults); topPane.addTab(t.localize(LocaleResources.TIMELINE).getContents(), threadTimelineView.getUiComponent()); threadCountView = new SwingThreadCountView(); diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/HeaderController.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/HeaderController.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import javax.swing.JComponent; - -/** - */ -public class HeaderController implements PropertyChangeListener { - - private JComponent[] toRepaint; - public HeaderController(JComponent ... toRepaint) { - this.toRepaint = toRepaint; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - for (JComponent component : toRepaint) { - component.repaint(); - } - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RangeComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RangeComponent.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangedTimelineProbe; +import java.awt.Graphics; +import java.awt.Rectangle; + +/** + * + */ +public class RangeComponent extends ContentPane { + private RangedTimelineProbe info; + + public RangeComponent(RangedTimelineProbe info) { + this.info = info; + } + + public RangedTimelineProbe getInfo() { + return info; + } + + @Override + protected void paintComponent(Graphics g) { + g.setColor(info.getColor().getColor()); + Rectangle bounds = g.getClipBounds(); + g.fillRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RangeComponentHeader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RangeComponentHeader.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,101 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.swing.components.FontAwesomeIcon; +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JLabel; + +/** + * + */ +public class RangeComponentHeader extends ContentPane { + + private final TimelineModel model; + private final UIDefaults defaults; + private ContentPane controls; + + public RangeComponentHeader(TimelineModel model, UIDefaults defaults) { + this.model = model; + this.defaults = defaults; + } + + public void initComponents() { + controls = new ContentPane(); + controls.setLayout(new GridLayout(1, 0, 5, 5)); + + JLabel zoomOut = new JLabel(new FontAwesomeIcon('\uf066', 15, + defaults.getIconColor())); + zoomOut.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + double ratio = model.getMagnificationRatio(); + model.setMagnificationRatio(ratio/2); + } + }); + controls.add(zoomOut); + + JLabel restoreZoom = new JLabel(new FontAwesomeIcon('\uf03b', 15, + defaults.getIconColor())); + restoreZoom.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + model.setMagnificationRatio(TimelineModel.DEFAULT_RATIO); + } + }); + controls.add(restoreZoom); + + JLabel zoomIn = new JLabel(new FontAwesomeIcon('\uf065', 15, + defaults.getIconColor())); + zoomIn.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + double ratio = model.getMagnificationRatio(); + model.setMagnificationRatio(ratio*2); + } + }); + controls.add(zoomIn); + + add(controls, BorderLayout.EAST); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RangeComponentLayoutManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RangeComponentLayoutManager.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.client.swing.components.AbstractLayout; +import com.redhat.thermostat.common.model.LongRangeNormalizer; +import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangedTimelineProbe; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; +import java.awt.Container; +import java.awt.Dimension; + +/** + * + */ +class RangeComponentLayoutManager extends AbstractLayout { + + private static final int STATE_COMPONENT_HEIGHT = 5; + + private static final boolean DEBUG_TIMELINES = false; + + @Override + protected void doLayout(Container parent) { + TimelineContainer container = (TimelineContainer) parent; + + Dimension size = getRealLayoutSize(container); + TimelineModel model = container.getModel(); + + LongRangeNormalizer normalizer = new LongRangeNormalizer(model.getRange()); + + normalizer.setMinNormalized(0); + normalizer.setMaxNormalized(size.width); + + if (DEBUG_TIMELINES) System.err.print(container.getName()); + + for (RangeComponent rangeComponent : container) { + + RangedTimelineProbe info = rangeComponent.getInfo(); + Range range = info.getRange(); + int x = (int) normalizer.getValueNormalized(range.getMin()); + int width = (int) normalizer.getValueNormalized(range.getMax()) - x + 1; + + rangeComponent.setBounds(x, 0, width, 5); + + if (DEBUG_TIMELINES) System.err.print(" [" + range.getMin() + + " - " + range.getMax() + "]"); + } + + if (DEBUG_TIMELINES) System.err.println(""); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return getRealLayoutSize(parent); + } + + public Dimension getRealLayoutSize(Container parent) { + TimelineContainer container = (TimelineContainer) parent; + + TimelineModel model = container.getModel(); + + Range range = model.getRange(); + + double length = range.getMax() - range.getMin(); + double multiplier = model.getMagnificationRatio(); + + return new Dimension((int) Math.round(length * multiplier), + STATE_COMPONENT_HEIGHT); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RulerComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/RulerComponent.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,164 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.client.swing.GraphicsUtils; +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.ui.Palette; +import com.redhat.thermostat.thread.client.swing.experimental.components.DataPane; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; + +/** + * + */ +public class RulerComponent extends DataPane { + + protected class RenderingInfo { + long startRendering; + long stopRendering; + + long startMark; + long increment; + } + + protected final UIDefaults uiDefaults; + protected TimelineModel model; + private boolean selected; + + public RulerComponent(UIDefaults defaults, TimelineModel model) { + + super(Palette.LIGHT_GRAY, Palette.WHITE); + + this.uiDefaults = defaults; + this.model = model; + setFont(defaults.getDefaultFont().deriveFont(Font.PLAIN, 10.f)); + setName("ruler"); + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + @Override + public Dimension getPreferredSize() { + Dimension pref = super.getPreferredSize(); + pref.height = getHeight(); + return pref; + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getSize() { + return getPreferredSize(); + } + + private RenderingInfo getRenderingInfo(Rectangle bounds) { + + RenderingInfo info = new RenderingInfo(); + info.stopRendering = bounds.x + bounds.width; + info.increment = 10; + + long start = model.getRange().getMin(); + long visibleStartTime = start + model.getScrollBarModel().getValue(); + + // small mark, 1 second boundary + long mark = visibleStartTime - (1_000 * (visibleStartTime/1_000)); + info.startRendering = -mark; + + return info; + } + + @Override + protected void paintComponent(Graphics g) { + Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); + + Rectangle bounds = graphics.getClipBounds(); + if (!isSelected()) { + super.paintComponent(g); + } else { + graphics.setPaint(uiDefaults.getSelectedComponentBGColor()); + graphics.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + } + + Color lines = Palette.PALE_GRAY.getColor(); + Color tickLines = Palette.DARK_GRAY.getColor(); + + RenderingInfo info = getRenderingInfo(bounds); + int height = bounds.y + bounds.height; + + boolean resetColor = false; + long mark = 10l; + + graphics.setColor(lines); + for (int i = (int) info.startRendering, j = (int) info.startMark; + i < info.stopRendering; i += info.increment, j++) + { + if (j % mark == 0) { + graphics.setColor(tickLines); + resetColor = true; + } + + graphics.drawLine(i, bounds.y, i, height); + + if (resetColor) { + graphics.setColor(lines); + resetColor = false; + } + } + + // TODO +// if (drawLabels) { +// drawLabels(graphics, info); +// } + + graphics.dispose(); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/SwingTimelineDimensionModel.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/SwingTimelineDimensionModel.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - */ -public class SwingTimelineDimensionModel implements TimelineDimensionModel { - - /** - * Default increment is 20 pixels per units. - * Subclasses may use different values. - * - * @see #DEFAULT_INCREMENT_IN_MILLIS - */ - public static final int DEFAULT_INCREMENT_IN_PIXELS = 20; - - /** - * Default increments is 1 second (1000 ms) per pixel unit. - * Subclasses may use different values. - * - * @see #DEFAULT_INCREMENT_IN_PIXELS - */ - public static final long DEFAULT_INCREMENT_IN_MILLIS = 1_000; - - private PropertyChangeSupport propertyChangeSupport; - - private int width; - private int incrementInPixels = DEFAULT_INCREMENT_IN_PIXELS; - private long incrementInMillis = DEFAULT_INCREMENT_IN_MILLIS; - - private volatile long length; - - public SwingTimelineDimensionModel() { - propertyChangeSupport = new PropertyChangeSupport(this); - } - - public void setWidth(int width) { - this.width = width; - - computeLength(); - } - - public int getWidth() { - return width; - } - - public void setIncrement(int pixels, long millis) { - this.incrementInMillis = millis; - this.incrementInPixels = pixels; - - computeLength(); - } - - public int getIncrementInPixels() { - return incrementInPixels; - } - - public long getIncrementInMillis() { - return incrementInMillis; - } - - public int getLengthInPixels() { - return width / incrementInPixels; - } - - private void computeLength() { - - long oldLength = length; - - int lengthInPixels = getLengthInPixels(); - length = incrementInMillis * lengthInPixels; - - propertyChangeSupport.firePropertyChange(LENGTH_PROPERTY, oldLength, length); - } - - @Override - public long getLengthInMillis() { - return length; - } - - @Override - public void addPropertyChangeListener(String property, PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(property, listener); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/ThreadTimelineHeader.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/ThreadTimelineHeader.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import com.redhat.thermostat.client.swing.GraphicsUtils; -import com.redhat.thermostat.client.ui.Palette; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Rectangle; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * - */ -@SuppressWarnings("serial") -public class ThreadTimelineHeader extends TimelineBaseComponent { - - public ThreadTimelineHeader(TimelineGroupThreadConverter timelinePageModel, - SwingTimelineDimensionModel dimensionModel) - { - super(timelinePageModel, dimensionModel); - setBorder(new TimelineBorder(false)); - } - - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - - Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); - - Rectangle bounds = graphics.getClipBounds(); - int x = getRoundedStartingX(bounds); - int pixelIncrement = dimensionModel.getIncrementInPixels(); - long increment = dimensionModel.getIncrementInMillis(); - - int upperBound = bounds.x + bounds.width; - - Paint gradient = new GradientPaint(0, 0, Palette.WHITE.getColor(), 0, getHeight(), Palette.GRAY.getColor()); - int height = getHeight(); - - DateFormat df = new SimpleDateFormat("HH:mm:ss"); - - long currentTime = timelinePageModel.getDataModel().getPageRange().getMin() - getRound(); - - for (int i = x, j = 0; i < upperBound; i += pixelIncrement, j++) { - if (j % 10 == 0) { - graphics.setColor(Palette.THERMOSTAT_BLU.getColor()); - graphics.drawLine(i, 0, i, height); - - graphics.setPaint(gradient); - - String value = df.format(new Date(currentTime)); - - int stringWidth = (int) getFont().getStringBounds(value, graphics.getFontRenderContext()).getWidth() - 1; - int stringHeight = (int) getFont().getStringBounds(value, graphics.getFontRenderContext()).getHeight(); - graphics.fillRect(i + 1, bounds.y + 5, stringWidth + 4, stringHeight + 4); - - graphics.setColor(Palette.THERMOSTAT_BLU.getColor()); - graphics.drawString(value, i + 1, bounds.y + stringHeight + 5); - } - currentTime += increment; - } - - graphics.dispose(); - } -} - diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineAdjustmentListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineAdjustmentListener.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import javax.swing.BoundedRangeModel; + +/** + * + */ +public class TimelineAdjustmentListener implements AdjustmentListener { + + private TimelineModel model; + private boolean followMode; + + public TimelineAdjustmentListener(TimelineModel model) { + this.model = model; + } + + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + BoundedRangeModel scrollBarModel = model.getScrollBarModel(); + if (scrollBarModel.getValueIsAdjusting()) { + followMode = false; + return; + } + + int max = scrollBarModel.getMaximum(); + int currentExtent = scrollBarModel.getValue() + + scrollBarModel.getExtent(); + + if (currentExtent == max) { + followMode = true; + } + + if (followMode) { + int value = max - scrollBarModel.getExtent(); + scrollBarModel.setValue(value); + } + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineBaseComponent.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineBaseComponent.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import com.redhat.thermostat.client.swing.GraphicsUtils; -import com.redhat.thermostat.client.swing.components.GradientPanel; -import com.redhat.thermostat.client.ui.Palette; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; - -/** - */ -public class TimelineBaseComponent extends GradientPanel { - - public static final Font FONT = new Font("SansSerif", Font.PLAIN, 10); - - private boolean selected; - - /** - * This value defines the gap between two labels, in terms of units - * (i.e. every TIME_GAP_BETWEEN_LABELS there will be a label displayed). - */ - static final long TIME_GAP_BETWEEN_LABELS = 10; - - static final int FIXED_HEIGHT = 20; - - protected TimelineGroupThreadConverter timelinePageModel; - protected SwingTimelineDimensionModel dimensionModel; - - public TimelineBaseComponent(TimelineGroupThreadConverter timelinePageModel, - SwingTimelineDimensionModel dimensionModel) - { - super(Palette.LIGHT_GRAY.getColor(), Palette.WHITE.getColor()); - setFont(FONT); - - this.timelinePageModel = timelinePageModel; - this.dimensionModel = dimensionModel; - - this.selected = false; - } - - protected long getRound() { - long min = timelinePageModel.getDataModel().getPageRange().getMin(); - long timeIncrement = dimensionModel.getIncrementInMillis(); - return min % (TIME_GAP_BETWEEN_LABELS * timeIncrement); - } - - protected int getRoundedStartingX(Rectangle bounds) { - - long timeIncrement = dimensionModel.getIncrementInMillis(); - long round = getRound(); - long roundDelta = round / timeIncrement; - - int pixelIncrement = dimensionModel.getIncrementInPixels(); - long pixelDelta = roundDelta * pixelIncrement; - - return (int) (bounds.x - pixelDelta); - } - - @Override - protected void paintComponent(Graphics g) { - - Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); - Rectangle bounds = graphics.getClipBounds(); - - Color lines = Palette.GRAY.getColor(); - Color tickLines = Palette.THERMOSTAT_BLU.getColor(); - - if (!isSelected()) { - super.paintComponent(g); - } else { - graphics.setColor(Palette.ADWAITA_BLU.getColor()); - graphics.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); - - lines = Palette.DARK_GRAY.getColor(); - tickLines = Palette.ROYAL_BLUE.getColor(); - } - - int pixelIncrement = dimensionModel.getIncrementInPixels(); - int x = getRoundedStartingX(bounds); - int upperBound = bounds.x + bounds.width; - - graphics.setColor(Palette.GRAY.getColor()); - - boolean resetColor = false; - for (int i = x, j = 0; i < upperBound; i += pixelIncrement, j++) { - if (j % 10 == 0) { - graphics.setColor(tickLines); - resetColor = true; - } - - graphics.drawLine(i, 0, i, bounds.height); - - if (resetColor) { - graphics.setColor(lines); - resetColor = false; - } - } - - graphics.dispose(); - } - - @Override - public int getHeight() { - return FIXED_HEIGHT; - } - - @Override - public Dimension getPreferredSize() { - Dimension pref = super.getPreferredSize(); - pref.height = getHeight(); - return pref; - } - - public boolean isSelected() { - return selected; - } - - public void setSelected(boolean selected) { - this.selected = selected; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineBorder.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineBorder.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import com.redhat.thermostat.client.swing.components.DebugBorder; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Insets; - -/** - */ -class TimelineBorder extends DebugBorder { - private boolean isOpaque; - - public TimelineBorder() { - this(false); - } - - public TimelineBorder(boolean opaque) { - this.isOpaque = opaque; - } - - @Override - public boolean isBorderOpaque() { - return isOpaque; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, - int height) - { - g.setColor(c.getForeground()); - g.drawLine(0, c.getHeight() - 1, c.getWidth() - 1, c.getHeight() - 1); - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - - insets.top = 0; - insets.left = 0; - insets.right = 0; - insets.bottom = 1; - - return insets; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineCellRenderer.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineCellRenderer.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.ListCellRenderer; - -@SuppressWarnings("serial") -public class TimelineCellRenderer extends JPanel implements ListCellRenderer { - - @Override - public TimelineComponent getListCellRendererComponent(JList list, - TimelineComponent value, - int index, boolean isSelected, - boolean cellHasFocus) - { - value.setSelected(isSelected); - return value; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineComponent.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineComponent.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineComponent.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,59 +36,98 @@ package com.redhat.thermostat.thread.client.swing.impl.timeline; -import com.redhat.thermostat.client.swing.GraphicsUtils; -import com.redhat.thermostat.common.model.LongRangeNormalizer; -import com.redhat.thermostat.common.model.Range; -import com.redhat.thermostat.thread.client.common.model.timeline.Timeline; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineInfo; +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.swing.components.ThermostatScrollPane; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import com.redhat.thermostat.thread.client.swing.experimental.components.Separator; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; -@SuppressWarnings("serial") -public class TimelineComponent extends TimelineBaseComponent { +/** + * + */ +public class TimelineComponent extends RulerComponent { - private static final int MIN_HEIGHT = 42; + private static final int MIN_HEIGHT = 50; + private final ThreadInfo threadInfo; + + private ContentPane labelPane; private TimelineLabel label; - private Timeline timeline; - public TimelineComponent(TimelineGroupThreadConverter timelinePageModel, - SwingTimelineDimensionModel dimensionModel, - String name) + private ThermostatScrollPane scrollPane; + private TimelineContainer timelineContainer; + + public TimelineComponent(UIDefaults uiDefaults, ThreadInfo threadInfo, + TimelineModel model) { - // TODO: get those from color properties - super(timelinePageModel, dimensionModel); + super(uiDefaults, model); + this.threadInfo = threadInfo; + } + + public void initComponents() { + setName(threadInfo.getName()); + + initModel(); - setLayout(new BorderLayout()); - label = new TimelineLabel(name); - add(label, BorderLayout.LINE_START); + initLabelPane(); + initThreadPane(); + + setBorder(new Separator(uiDefaults, Separator.Side.BOTTOM, + Separator.Type.SOLID)); + + Hover hover = new Hover(); + addMouseListener(hover); } - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); + private void initModel() { + model.getScrollBarModel().addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + repaint(); + } + }); + } - Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); + private void initThreadPane() { + + timelineContainer = new TimelineContainer(model); + timelineContainer.setName(threadInfo.getName()); - Range pageRange = timelinePageModel.getDataModel().getPageRange(); + scrollPane = new ThermostatScrollPane(timelineContainer); + scrollPane.setHorizontalScrollBarPolicy(ThermostatScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ThermostatScrollPane.VERTICAL_SCROLLBAR_NEVER); - int y = MIN_HEIGHT / 2; + add(scrollPane, BorderLayout.CENTER); - LongRangeNormalizer normalizer = new LongRangeNormalizer(pageRange, 0, getWidth()); - if (timeline != null) { - for (TimelineInfo sample : timeline) { - graphics.setColor(sample.getColor().getColor()); - Range sampleRange = sample.getRange(); + scrollPane.getHorizontalScrollBar().setModel(model.getScrollBarModel()); + } + + public TimelineContainer getTimelineContainer() { + return timelineContainer; + } + + private void initLabelPane() { + label = new TimelineLabel(uiDefaults, getName()); + labelPane = new ContentPane(); - int x0 = (int) normalizer.getValueNormalized(sampleRange.getMin()); - int x1 = (int) normalizer.getValueNormalized(sampleRange.getMax()); + labelPane.setOpaque(false); + labelPane.setLayout(new GridBagLayout()); - graphics.fillRect(x0, y, x1 - x0 + 1, 5); - } - } - graphics.dispose(); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 1.f; + + labelPane.add(label, gbc); + add(labelPane, BorderLayout.NORTH); } @Override @@ -96,32 +135,20 @@ return MIN_HEIGHT; } - @Override - public Dimension getPreferredSize() { - Dimension pref = super.getPreferredSize(); - pref.height = getHeight(); - return pref; - } + private class Hover extends MouseAdapter { + @Override + public void mouseEntered(MouseEvent e) { + onMouseHover(true); + } - @Override - public Dimension getMinimumSize() { - return getPreferredSize(); - } + @Override + public void mouseExited(MouseEvent e) { + onMouseHover(false); + } - @Override - public Dimension getSize() { - return getPreferredSize(); - } - - public void setTimeline(Timeline timeline) { - this.timeline = timeline; - if (timeline != null && timeline.size() > 0) { - label.setForeground(timeline.last().getColor().getColor()); + public void onMouseHover(boolean hover) { + label.onMouseHover(hover); + repaint(); } } - - public Timeline getTimeline() { - return timeline; - } } - diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineContainer.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,103 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangeChangeEvent; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangeChangeListener; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RatioChangeEvent; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RatioChangeListener; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; +import java.awt.Component; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * + */ +public class TimelineContainer extends ContentPane implements Iterable { + + private List rangeComponents; + private TimelineModel model; + + public TimelineContainer(TimelineModel model) { + rangeComponents = new ArrayList<>(); + + setOpaque(false); + setLayout(new RangeComponentLayoutManager()); + + setModel(model); + } + + public Component add(RangeComponent comp) { + rangeComponents.add(comp); + return super.add(comp); + } + + @Override + public Iterator iterator() { + return rangeComponents.iterator(); + } + + public TimelineModel getModel() { + return model; + } + + public void setModel(TimelineModel model) { + this.model = model; + model.addRangeChangeListener(new RangeChangeListener() { + @Override + public void rangeChanged(RangeChangeEvent event) { + revalidate(); + repaint(); + } + }); + model.addRatioChangeListener(new RatioChangeListener() { + @Override + public void ratioChanged(RatioChangeEvent event) { + revalidate(); + repaint(); + } + }); + } + + public RangeComponent getLastRangeComponent() { + return rangeComponents.isEmpty() ? null : + rangeComponents.get(rangeComponents.size() - 1); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineGroupThreadConverter.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineGroupThreadConverter.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineGroupDataModel; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import javax.swing.SwingUtilities; - -/* - */ -public class TimelineGroupThreadConverter implements PropertyChangeListener { - - private TimelineGroupDataModel source; - private PropertyChangeSupport propertyChangeSupport; - - public TimelineGroupThreadConverter(TimelineGroupDataModel source) { - - this.source = source; - propertyChangeSupport = new PropertyChangeSupport(this); - - source.addPropertyChangeListener(TimelineGroupDataModel.RangeChangeProperty.PAGE_RANGE, this); - source.addPropertyChangeListener(TimelineGroupDataModel.RangeChangeProperty.TOTAL_RANGE, this); - } - - @Override - public void propertyChange(final PropertyChangeEvent evt) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - propertyChangeSupport.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); - } - }); - } - - public void addPropertyChangeListener(TimelineGroupDataModel.RangeChangeProperty property, PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(property.name(), listener); - } - - public TimelineGroupDataModel getDataModel() { - return source; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineLabel.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineLabel.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineLabel.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,73 +36,52 @@ package com.redhat.thermostat.thread.client.swing.impl.timeline; -import com.redhat.thermostat.client.swing.GraphicsUtils; -import com.redhat.thermostat.client.swing.components.experimental.TimelineUtils; +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.swing.components.FontAwesomeIcon; +import com.redhat.thermostat.client.swing.components.Icon; +import com.redhat.thermostat.client.swing.components.LabelField; import com.redhat.thermostat.client.ui.Palette; +import com.redhat.thermostat.shared.locale.LocalizedString; +import com.redhat.thermostat.thread.client.swing.experimental.components.DataPane; +import com.redhat.thermostat.thread.client.swing.experimental.components.Separator; import java.awt.Color; -import java.awt.Dimension; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Paint; -import javax.swing.JLabel; -import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; /** + * */ -public class TimelineLabel extends JPanel { +class TimelineLabel extends DataPane { + private LabelField nameLabel; + private Icon infoOn; + private Icon infoOff; - private String text; + TimelineLabel(UIDefaults defaults, String text) { + super(Palette.WHITE, Palette.LIGHT_GRAY); + + setBorder(new Separator(defaults, Separator.Side.BOTTOM, Separator.Type.SOLID)); - public TimelineLabel(String text) { - setOpaque(false); - setBorder(new TimelineBorder(true)); + nameLabel = new LabelField(LocalizedString.EMPTY_STRING); + nameLabel.setFont(defaults.getDefaultFont().deriveFont(10.f)); - this.text = text; + nameLabel.setText(text); + nameLabel.setHorizontalAlignment(SwingConstants.CENTER); + nameLabel.setVerticalAlignment(SwingConstants.CENTER); + nameLabel.setForeground((Color) defaults.getSelectedComponentBGColor()); + nameLabel.setBorder(new EmptyBorder(2, 2, 2, 2)); - JLabel nameLabel = new JLabel(text); - nameLabel.setFont(TimelineUtils.FONT); - nameLabel.setForeground(Palette.THERMOSTAT_BLU.getColor()); + nameLabel.setHorizontalTextPosition(SwingConstants.LEFT); + + infoOn = new FontAwesomeIcon('\uf05a', 12, Palette.DARK_GRAY.getColor()); + infoOff = new FontAwesomeIcon('\uf05a', 12, Palette.PALE_GRAY.getColor()); + + nameLabel.setIcon(infoOff); add(nameLabel); } - @Override - public int getHeight() { - return 20; - } - - @Override - public Dimension getPreferredSize() { - Dimension dim = super.getPreferredSize(); - dim.height = getHeight(); - return dim; - } - - @Override - public Dimension getSize() { - return getPreferredSize(); - } - - @Override - protected void paintComponent(Graphics g) { - - GraphicsUtils utils = GraphicsUtils.getInstance(); - - Graphics2D graphics = utils.createAAGraphics(g); - - Color up = utils.deriveWithAlpha(Palette.WHITE.getColor(), 200); - Color bottom = utils.deriveWithAlpha(Palette.GRAY.getColor(), 200); - - Paint gradient = new GradientPaint(0, 0, up, 0, getHeight(), bottom); - graphics.setPaint(gradient); - - graphics.fillRect(0, 0, getWidth(), getHeight()); - - graphics.dispose(); - } - - public String getText() { - return text; + public void onMouseHover(boolean hover) { + nameLabel.setIcon(hover ? infoOn : infoOff); + repaint(); } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineRangeModelFormatter.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineRangeModelFormatter.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * Formatter class for {@link TimelineRange} - */ -public class TimelineRangeModelFormatter { - - private static DateFormat df = new SimpleDateFormat("yyyy.MM.dd, HH:mm:ss"); - - public static String getFormattedString(long range) { - if (range < 0) { - return " - "; - } - return df.format(new Date(range)); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineViewComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineViewComponent.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,136 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.swing.components.ThermostatScrollBar; +import com.redhat.thermostat.client.swing.components.ThermostatScrollPane; +import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangeChangeEvent; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RangeChangeListener; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RatioChangeEvent; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.RatioChangeListener; +import com.redhat.thermostat.thread.client.swing.impl.timeline.model.TimelineModel; +import java.awt.BorderLayout; +import java.awt.Rectangle; + +/** + * + */ +public class TimelineViewComponent extends ContentPane { + + private TimelineModel model; + private ThermostatScrollPane scrollPane; + private TimelineViewport viewport; + + private ThermostatScrollBar scrollBar; + private UIDefaults uiDefaults; + + public TimelineViewComponent(UIDefaults uiDefaults) { + this.uiDefaults = uiDefaults; + } + + public void initComponents() { + + this.model = new TimelineModel(); + + viewport = new TimelineViewport(); + + scrollPane = new ThermostatScrollPane(viewport); + scrollPane.setVerticalScrollBarPolicy(ThermostatScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.setHorizontalScrollBarPolicy(ThermostatScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + RangeComponentHeader header = new RangeComponentHeader(model, uiDefaults); + header.initComponents(); + scrollPane.setColumnHeaderView(header); + + add(scrollPane, BorderLayout.CENTER); + + scrollBar = new ThermostatScrollBar(ThermostatScrollBar.HORIZONTAL); + model.setScrollBarModel(scrollBar.getModel()); + + scrollBar.addAdjustmentListener(new TimelineAdjustmentListener(model)); + + add(scrollBar, BorderLayout.SOUTH); + scrollBar.setEnabled(false); + scrollBar.setVisible(false); + + model.addRatioChangeListener(new RatioChangeListener() { + @Override + public void ratioChanged(RatioChangeEvent event) { + checkEnableScrollbar(); + } + }); + model.addRangeChangeListener(new RangeChangeListener() { + @Override + public void rangeChanged(RangeChangeEvent event) { + checkEnableScrollbar(); + } + }); + } + + private void checkEnableScrollbar() { + Range range = model.getRange(); + Rectangle bounds = getBounds(); + long length = bounds.x + bounds.width; + length = Math.round(length / model.getMagnificationRatio()); + + long lengthInMs = range.getMax() - range.getMin(); + lengthInMs = Math.round(lengthInMs / model.getMagnificationRatio()); + + boolean shouldEnable = (length < lengthInMs); + + scrollBar.setVisible(shouldEnable); + scrollBar.setEnabled(shouldEnable); + } + + public void addTimeline(TimelineComponent timeline) { + viewport.add(timeline); + checkEnableScrollbar(); + + timeline. + + revalidate(); + repaint(); + } + + public TimelineModel getModel() { + return model; + } +} + diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineViewport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineViewport.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline; + +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import java.awt.Dimension; +import java.awt.Rectangle; +import javax.swing.BoxLayout; +import javax.swing.Scrollable; + +/** + * + */ +public class TimelineViewport extends ContentPane implements Scrollable { + + public TimelineViewport() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + } + + @Override + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + @Override + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + return 1; + } + + @Override + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return 1; + } + + @Override + public boolean getScrollableTracksViewportWidth() { + return true; + } + + @Override + public boolean getScrollableTracksViewportHeight() { + return false; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RangeChangeEvent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RangeChangeEvent.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import com.redhat.thermostat.common.model.Range; +import java.util.EventObject; + +/** + * + */ +public class RangeChangeEvent extends EventObject { + + private final TimelineModel source; + private final Range range; + + public RangeChangeEvent(TimelineModel source, Range range) { + super(source); + this.source = source; + this.range = range; + } + + @Override + public TimelineModel getSource() { + return (TimelineModel) super.getSource(); + } + + public Range getRange() { + return range; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RangeChangeListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RangeChangeListener.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import java.util.EventListener; + +/** + * + */ +public interface RangeChangeListener extends EventListener { + + public void rangeChanged(RangeChangeEvent event); +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RangedTimelineProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RangedTimelineProbe.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; + +/** + * + */ +public class RangedTimelineProbe extends TimelineProbe { + + private long probeEnd; + + public RangedTimelineProbe(TimelineProbe probe, long probeStop) + { + super(probe.getColor(), probe.getState(), probe.getTimeStamp()); + this.probeEnd = probeStop; + } + + public void setProbeEnd(long probeEnd) { + this.probeEnd = probeEnd; + } + + public Range getRange() { + return new Range<>(getTimeStamp(), probeEnd); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RatioChangeEvent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RatioChangeEvent.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import java.util.EventObject; + +/** + * + */ +public class RatioChangeEvent extends EventObject { + private final TimelineModel source; + private final double ratio; + + public RatioChangeEvent(TimelineModel source, double ratio) { + super(source); + this.source = source; + this.ratio = ratio; + } + + @Override + public TimelineModel getSource() { + return (TimelineModel) super.getSource(); + } + + public double getRatio() { + return ratio; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RatioChangeListener.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/RatioChangeListener.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import java.util.EventListener; + +/** + * + */ +public interface RatioChangeListener extends EventListener { + public void ratioChanged(RatioChangeEvent event); +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/TimelineDateFormatter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/TimelineDateFormatter.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * + */ +public class TimelineDateFormatter { + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS"); + + public static String format(long timeStamp) { + return DATE_FORMAT.format(new Date(timeStamp)); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/TimelineModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/model/TimelineModel.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,129 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl.timeline.model; + +import com.redhat.thermostat.common.model.Range; +import javax.swing.BoundedRangeModel; +import javax.swing.event.EventListenerList; + +/** + * + */ +public class TimelineModel { + + public static final double DEFAULT_RATIO = 1./100.; + + private EventListenerList listenerList; + + private double magnificationRatio; + + private Range range; + private BoundedRangeModel scrollBarModel; + + private TimelineModel model; + + public TimelineModel() { + this.listenerList = new EventListenerList(); + magnificationRatio = DEFAULT_RATIO; + } + + public Range getRange() { + return range; + } + + public void setRange(Range range) { + this.range = range; + fireRangeChangeEvent(); + } + + public void setScrollBarModel(BoundedRangeModel scrollBarModel) { + this.scrollBarModel = scrollBarModel; + } + + public BoundedRangeModel getScrollBarModel() { + return scrollBarModel; + } + + public void addRangeChangeListener(RangeChangeListener listener) { + listenerList.add(RangeChangeListener.class, listener); + } + + public void addRatioChangeListener(RatioChangeListener listener) { + listenerList.add(RatioChangeListener.class, listener); + } + + public void removeRatioChangeListener(RatioChangeListener listener) { + listenerList.remove(RatioChangeListener.class, listener); + } + + public void removeRangeChangeListener(RangeChangeListener listener) { + listenerList.remove(RangeChangeListener.class, listener); + } + + public double getMagnificationRatio() { + return magnificationRatio; + } + + public void setMagnificationRatio(double magnificationRatio) { + this.magnificationRatio = magnificationRatio; + fireRatioChangeEvent(); + } + + private void fireRatioChangeEvent() { + Object[] listeners = listenerList.getListenerList(); + RatioChangeEvent event = + new RatioChangeEvent(this, magnificationRatio); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == RatioChangeListener.class) { + ((RatioChangeListener) listeners[i + 1]).ratioChanged(event); + } + } + } + + private void fireRangeChangeEvent() { + Object[] listeners = listenerList.getListenerList(); + RangeChangeEvent event = + new RangeChangeEvent(this, + new Range<>(range.getMin(), + range.getMax())); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == RangeChangeListener.class) { + ((RangeChangeListener) listeners[i + 1]).rangeChanged(event); + } + } + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/SwingTimelineScrollBarController.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/SwingTimelineScrollBarController.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar; - -import com.redhat.thermostat.common.model.Range; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineGroupDataModel; -import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; -import com.redhat.thermostat.thread.client.swing.impl.SwingThreadTimelineView; -import com.redhat.thermostat.thread.client.swing.impl.timeline.SwingTimelineDimensionModel; -import com.redhat.thermostat.thread.client.swing.impl.timeline.TimelineGroupThreadConverter; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -public class SwingTimelineScrollBarController implements PropertyChangeListener, AdjustmentListener { - - private static final int MIN_THUMB_PERCENTAGE = 2; - - private boolean followMode; - - private TimelineScrollBar scrollbar; - private TimelineGroupThreadConverter groupDataModel; - private SwingTimelineDimensionModel dimensionModel; - private SwingThreadTimelineView view; - - public SwingTimelineScrollBarController(SwingThreadTimelineView view, - TimelineScrollBar scrollbar, - TimelineGroupThreadConverter groupDataModel, - SwingTimelineDimensionModel dimensionModel) - { - this.scrollbar = scrollbar; - this.groupDataModel = groupDataModel; - this.dimensionModel = dimensionModel; - this.view = view; - } - - public void initScrollbar(SwingThreadTimelineView threadTimelineView) { - scrollbar.setEnabled(false); - scrollbar.addAdjustmentListener(this); - groupDataModel.addPropertyChangeListener(TimelineGroupDataModel.RangeChangeProperty.TOTAL_RANGE, this); - groupDataModel.addPropertyChangeListener(TimelineGroupDataModel.RangeChangeProperty.PAGE_RANGE, this); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (scrollbar.getValueIsAdjusting()) { - // we won't do anything at this point - return; - } - - Range pageRange = groupDataModel.getDataModel().getPageRange(); - Range totalRange = groupDataModel.getDataModel().getTotalRange(); - - double pageSize = (double) (pageRange.getMax() - pageRange.getMin()); - double totalSize = (double) (totalRange.getMax() - totalRange.getMin()); - int width = dimensionModel.getWidth(); - - // no data, or not everything has been instantiated correctly yet - if (totalSize <= 0 || width <= 0) { - return; - } - - // this happens when the whole data is less than the page size - if (totalSize <= pageSize) { - // set the whole thing 100% extent, the slider should - // not be enabled - scrollbar.setEnabled(false); - scrollbar.setValues(0, 100, 0, 100); - - } else { - // ensure the scrollbar is enabled - scrollbar.setEnabled(true); - - int amount = (int) Math.round((pageSize/totalSize) * 100); - if (amount < MIN_THUMB_PERCENTAGE) { - amount = MIN_THUMB_PERCENTAGE; - } - - int value = scrollbar.getValue(); - int max = scrollbar.getMaximum(); - if (followMode || (value + amount) >= max) { - value = max - amount; - } - // scrollbar.setValues(max - amount, amount, 0, 100); - scrollbar.setValues(value, amount, 0, 100); - } - } - - public void ensureTimelineState(ThreadTimelineView.TimelineSelectorState following) { - switch (following) { - default: - case FOLLOWING: { - - followMode = true; - - int amount = scrollbar.getVisibleAmount(); - int max = scrollbar.getMaximum(); - int total = max + amount; - int currentValue = scrollbar.getValue() + amount; - if (currentValue <= total) { - scrollbar.setValue(total); - } - - } break; - - case STATIC: - - followMode = false; - - // there is really nothing else to do here, the scrollbar stays - // where it is, this is taken care by the range handlers - break; - - } - } - - @Override - public void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - if (source instanceof TimelineScrollBar) { - TimelineScrollBar scrollBar = (TimelineScrollBar) source; - int value = scrollBar.getValue(); - int visible = scrollBar.getVisibleAmount(); - int max = scrollBar.getMaximum(); - - int currentExtent = value + visible; - if (!scrollBar.getValueIsAdjusting() && currentExtent == max) { - view.requestFollowMode(); - } else { - - Range totalRange = groupDataModel.getDataModel().getTotalRange(); - - long totalSize = totalRange.getMax() - totalRange.getMin(); - long length = dimensionModel.getLengthInMillis(); - - long currentStep = Math.round((value * totalSize) / 100); - - // what's the actual range based on current percentage on - // display? - long start = totalRange.getMin() + currentStep; - Range pageRange = new Range<>(start, start + length); - view.requestStaticMode(pageRange); - } - } - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/TimelineButtonUI.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/TimelineButtonUI.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar; - -import java.awt.Color; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Rectangle; - -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.plaf.basic.BasicButtonUI; - -import com.redhat.thermostat.client.swing.GraphicsUtils; -import com.redhat.thermostat.client.ui.Palette; - -class TimelineButtonUI extends BasicButtonUI { - - @Override - protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, - Rectangle textRect, Rectangle iconRect) - { - // no focus :) - } - - @Override - protected void paintButtonPressed(Graphics g, AbstractButton b) { - super.paintButtonPressed(g, b); - } - - @Override - public void paint(Graphics g, JComponent c) { - - JButton button = (JButton) c; - - GraphicsUtils utils = GraphicsUtils.getInstance(); - Graphics2D graphics = utils.createAAGraphics(g); - Rectangle clip = graphics.getClipBounds(); - - Color top = Palette.WHITE.getColor(); - Color bottom = Palette.GRAY.getColor(); - - ButtonModel model = button.getModel(); - if (model.isPressed()) { - Color tmp = top; - top = bottom; - bottom = tmp; - } - - Paint gradient = new GradientPaint(0, 0, top, 0, button.getHeight(), bottom); - - graphics.setPaint(gradient); - graphics.fillRect(clip.x, clip.y, clip.width, clip.height); - - Icon icon = button.getIcon(); - if (icon != null) { - int x = button.getWidth() / 2 - icon.getIconWidth() / 2; - int y = button.getHeight() / 2 - icon.getIconHeight() / 2; - icon.paintIcon(button, graphics, x, y); - } - - super.paint(g, c); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/TimelineScrollBar.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/TimelineScrollBar.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar; - -import com.redhat.thermostat.client.swing.UIDefaults; -import com.redhat.thermostat.client.swing.components.ThermostatThinScrollBar; - -@SuppressWarnings("serial") -public class TimelineScrollBar extends ThermostatThinScrollBar { - - public TimelineScrollBar(UIDefaults uiDefaults) { - super(TimelineScrollBar.HORIZONTAL); - setUI(new TimelineScrollBarUI(uiDefaults)); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/TimelineScrollBarUI.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/timeline/scrollbar/TimelineScrollBarUI.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline.scrollbar; - -import com.redhat.thermostat.client.swing.GraphicsUtils; -import com.redhat.thermostat.client.swing.UIDefaults; -import com.redhat.thermostat.client.swing.components.FontAwesomeIcon; -import com.redhat.thermostat.client.ui.Palette; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Rectangle; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.basic.BasicScrollBarUI; - -class TimelineScrollBarUI extends BasicScrollBarUI { - - static enum ButtonDirection { - INCREASE, - DECREASE, - } - - private UIDefaults uiDefaults; - - public TimelineScrollBarUI(UIDefaults uiDefaults) { - this.uiDefaults = uiDefaults; - } - - @SuppressWarnings("serial") - private class TimelineButton extends JButton { - - public TimelineButton(ButtonDirection direction) { - - switch (direction) { - case DECREASE: - setIcon(new FontAwesomeIcon('\uf104', 16, new Color(0, 0, 0, 100))); - break; - - case INCREASE: - default: - setIcon(new FontAwesomeIcon('\uf105', 16, new Color(0, 0, 0, 100))); - break; - } - - setOpaque(false); - setBorder(new EmptyBorder(5, 5, 5, 5)); - - // those should really go somewhere in TimelineUtils or common UI - // properties, including the date format below - setForeground(Palette.EARL_GRAY.getColor()); - setUI(new TimelineButtonUI()); - } - } - - @Override - protected void installDefaults() { - super.installDefaults(); - - scrollBarWidth = 16; - incrGap = 0; - decrGap = 0; - - minimumThumbSize = new Dimension(50, 5); - } - - @Override - protected JButton createDecreaseButton(int orientation) { - return new TimelineButton(ButtonDirection.DECREASE); - } - - @Override - protected JButton createIncreaseButton(int orientation) { - return new TimelineButton(ButtonDirection.INCREASE); - } - - @Override - protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { - GraphicsUtils utils = GraphicsUtils.getInstance(); - Graphics2D graphics = utils.createAAGraphics(g); - graphics.setColor(Palette.GRAY.getColor()); - - graphics.translate(trackBounds.x, trackBounds.y); - - int w = trackBounds.width - 1; - int h = trackBounds.height - 1; - - graphics.drawLine(0, h, w, h); - - for (int i = 0; i < trackBounds.width; i += 10) { - graphics.drawLine(i, h - 5, i, h); - if (i % 100 == 0) { - graphics.drawLine(i, 0, i, h); - } - } - - graphics.setColor(Palette.EARL_GRAY.getColor()); - graphics.drawLine(0, 0, 0, h); - graphics.drawLine(w, 0, w, h); - - graphics.dispose(); - } - - @Override - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if(thumbBounds.isEmpty() || !scrollbar.isEnabled()) { - return; - } - - GraphicsUtils utils = GraphicsUtils.getInstance(); - Graphics2D graphics = utils.createAAGraphics(g); - - int w = thumbBounds.width - 1; - int h = thumbBounds.height - 1; - - graphics.translate(thumbBounds.x, thumbBounds.y); - - Color top = utils.deriveWithAlpha(Palette.WHITE.getColor(), 50); - Color bottom = utils.deriveWithAlpha(Palette.DROID_GRAY.getColor(), 50); - Paint gradient = new GradientPaint(0, 0, top, 0, h, bottom); - - graphics.setPaint(gradient); - graphics.fillRect(0, 0, w, h); - - graphics.setPaint(uiDefaults.getReferenceFieldIconColor()); - - int y = h/2 + 1; - - graphics.drawLine(0, y, w, y); - graphics.drawLine(0, 0, 0, h); - graphics.drawLine(w, 0, w, h); - - graphics.dispose(); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/osgi/Activator.java --- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/osgi/Activator.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/osgi/Activator.java Thu Dec 11 11:44:42 2014 +0100 @@ -40,9 +40,7 @@ import com.redhat.thermostat.common.MultipleServiceTracker; import com.redhat.thermostat.common.MultipleServiceTracker.Action; import com.redhat.thermostat.thread.client.common.ThreadViewProvider; -import com.redhat.thermostat.thread.client.common.model.timeline.TimelineDimensionModel; import com.redhat.thermostat.thread.client.swing.SwingThreadViewService; -import com.redhat.thermostat.thread.client.swing.impl.timeline.SwingTimelineDimensionModel; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -72,18 +70,12 @@ @Override public void dependenciesAvailable(Map services) { - - SwingTimelineDimensionModel dimensionModel = new SwingTimelineDimensionModel(); - + UIDefaults uiDefaults = (UIDefaults) services.get(UIDefaults.class.getName()); ServiceRegistration reg = context.registerService(ThreadViewProvider.class.getName(), - new SwingThreadViewService(uiDefaults, dimensionModel), + new SwingThreadViewService(uiDefaults), null); regs.add(reg); - - reg = context.registerService(TimelineDimensionModel.class.getName(), - dimensionModel, null); - regs.add(reg); } }); diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewDemo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewDemo.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,173 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl; + +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.ui.Palette; +import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; +import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.mockito.Mockito; + +/** + * + */ +public class SwingThreadViewDemo { + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + + UIDefaults defaults = createUIDefaults(); + + ContentPane contentPane = new ContentPane(); + + SwingThreadTimelineView view = new SwingThreadTimelineView(defaults); + JFrame frame = new JFrame(); + frame.add(contentPane); + + contentPane.add(view.getUiComponent()); + + JButton addDate = new JButton("Add Timeline Data"); + + addDate.addActionListener(new DataFiller(view)); + contentPane.add(addDate, BorderLayout.SOUTH); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(new Dimension(800, 800)); + frame.setVisible(true); + } + }); + } + + private static class DataFiller implements ActionListener { + + private ThreadTimelineView view; + private long startTime; + private long lastUpdate; + + private boolean threadAdded; + private int swap; + private boolean swapped; + + DataFiller(ThreadTimelineView view) { + this.view = view; + startTime = System.currentTimeMillis(); + lastUpdate = startTime; + swap = 0; + } + + @Override + public void actionPerformed(ActionEvent e) { + lastUpdate = System.currentTimeMillis(); + final Range range = new Range<>(startTime, lastUpdate); + + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + + //System.err.println("range: " + (range.getMax() - range.getMin())); + + view.setTotalRange(range); + + if (!threadAdded) { + ThreadInfo info = new ThreadInfo(); + info.setName("test1"); + info.setId(0l); + view.addThread(info); + + info = new ThreadInfo(); + info.setName("test2"); + info.setId(1l); + view.addThread(info); + + threadAdded = true; + + } else { + + Palette color1 = Palette.THERMOSTAT_BLU; + Palette color2 = Palette.THERMOSTAT_RED; + + if (swapped) { + color1 = Palette.THERMOSTAT_RED; + color2 = Palette.THERMOSTAT_BLU; + } + + swap++; + if (swap % 10 == 0) { + swapped = !swapped; + swap = 0; + } + + ThreadInfo info = new ThreadInfo(); + info.setName("test1"); + info.setId(0l); + TimelineProbe probe = new TimelineProbe(color1, "test1", lastUpdate); + view.addProbe(info, probe); + + info = new ThreadInfo(); + info.setName("test2"); + info.setId(1l); + probe = new TimelineProbe(color2, "test2", lastUpdate); + view.addProbe(info, probe); + } + + return null; + } + }; + worker.execute(); + } + } + + private static UIDefaults createUIDefaults() { + UIDefaults defaults = Mockito.mock(UIDefaults.class); + Mockito.when(defaults.getDefaultFont()).thenReturn(new JLabel().getFont()); + return defaults; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewDemo2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewDemo2.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,185 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl; + +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.ui.Palette; +import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; +import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Same as demo 1, except that timelines are always exactly one fixed interval + * apart and probes are added right away. + */ +public class SwingThreadViewDemo2 { + + private static final int INTERVAL = 100; // ms + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + + UIDefaults defaults = createUIDefaults(); + + ContentPane contentPane = new ContentPane(); + + SwingThreadTimelineView view = new SwingThreadTimelineView(defaults); + JFrame frame = new JFrame(); + frame.add(contentPane); + + contentPane.add(view.getUiComponent()); + + JButton addDate = new JButton("Add Timeline Data"); + + addDate.addActionListener(new DataFiller(view)); + contentPane.add(addDate, BorderLayout.SOUTH); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(new Dimension(800, 800)); + frame.setVisible(true); + } + }); + } + + private static class DataFiller implements ActionListener { + + private ThreadTimelineView view; + private long startTime; + private long lastUpdate; + + private boolean threadAdded; + private int swap; + private boolean swapped; + + private int added; + + DataFiller(ThreadTimelineView view) { + this.view = view; + startTime = 0l; + lastUpdate = 0l; + swap = 0; + } + + @Override + public void actionPerformed(ActionEvent e) { + lastUpdate += INTERVAL; + final Range range = new Range<>(startTime, lastUpdate); + + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + +// System.err.println("range: " + (range.getMax() - range.getMin())); + + view.setTotalRange(range); + + if (!threadAdded) { + ThreadInfo info = new ThreadInfo(); + info.setName("test1"); + info.setId(0l); + view.addThread(info); + + info = new ThreadInfo(); + info.setName("test2"); + info.setId(1l); + view.addThread(info); + + threadAdded = true; + + } + + Palette color1 = Palette.THERMOSTAT_BLU; + Palette color2 = Palette.THERMOSTAT_RED; + + if (swapped) { + color1 = Palette.THERMOSTAT_RED; + color2 = Palette.THERMOSTAT_BLU; + } + + swap++; + if (swap % 10 == 0) { + swapped = !swapped; + swap = 0; + } + + ThreadInfo info = new ThreadInfo(); + info.setName("test1"); + info.setId(0l); + TimelineProbe probe = new TimelineProbe(color1, "test1", lastUpdate); + view.addProbe(info, probe); + + info = new ThreadInfo(); + info.setName("test2"); + info.setId(1l); + probe = new TimelineProbe(color2, "test2", lastUpdate); + view.addProbe(info, probe); + + added++; + + // System.err.println("probes added: " + added); + + return null; + } + }; + worker.execute(); + } + } + + private static UIDefaults createUIDefaults() { + UIDefaults defaults = mock(UIDefaults.class); + when(defaults.getDefaultFont()).thenReturn(new JLabel().getFont()); + when(defaults.getIconColor()).thenReturn(Palette.EARL_GRAY.getColor()); + + return defaults; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewDemo3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewDemo3.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,181 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.client.swing.impl; + +import com.redhat.thermostat.client.swing.UIDefaults; +import com.redhat.thermostat.client.ui.Palette; +import com.redhat.thermostat.common.model.Range; +import com.redhat.thermostat.thread.client.common.model.timeline.ThreadInfo; +import com.redhat.thermostat.thread.client.common.model.timeline.TimelineProbe; +import com.redhat.thermostat.thread.client.common.view.ThreadTimelineView; +import com.redhat.thermostat.thread.client.swing.experimental.components.ContentPane; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Same as demo 2, except that it insert 10 minutes worth of timelines. + * Startup time is also configurable. + */ +public class SwingThreadViewDemo3 { + + private static final int INTERVAL = 100; // ms + private static final long STARTUP = 999l; // ms + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + + UIDefaults defaults = createUIDefaults(); + + ContentPane contentPane = new ContentPane(); + + SwingThreadTimelineView view = new SwingThreadTimelineView(defaults); + JFrame frame = new JFrame(); + frame.add(contentPane); + + contentPane.add(view.getUiComponent()); + + JButton addDate = new JButton("Add Timeline Data"); + + addDate.addActionListener(new DataFiller(view)); + contentPane.add(addDate, BorderLayout.SOUTH); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(new Dimension(800, 800)); + frame.setVisible(true); + } + }); + } + + private static class DataFiller implements ActionListener { + + private ThreadTimelineView view; + private long startTime; + private long lastUpdate; + + private boolean threadAdded; + private int swap; + private boolean swapped; + + private int added; + + DataFiller(ThreadTimelineView view) { + this.view = view; + startTime = STARTUP; + lastUpdate = STARTUP; + swap = 0; + } + + @Override + public void actionPerformed(ActionEvent e) { + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + for (long l = 0; l < 10_000; l+=INTERVAL) { + lastUpdate += INTERVAL; + final Range range = new Range<>(startTime, lastUpdate); + view.setTotalRange(range); + + if (!threadAdded) { + ThreadInfo info = new ThreadInfo(); + info.setName("test1"); + info.setId(0l); + view.addThread(info); + + info = new ThreadInfo(); + info.setName("test2"); + info.setId(1l); + view.addThread(info); + + threadAdded = true; + + } + + Palette color1 = Palette.THERMOSTAT_BLU; + Palette color2 = Palette.THERMOSTAT_RED; + + if (swapped) { + color1 = Palette.THERMOSTAT_RED; + color2 = Palette.THERMOSTAT_BLU; + } + + swap++; + if (swap % 10 == 0) { + swapped = !swapped; + swap = 0; + } + + ThreadInfo info = new ThreadInfo(); + info.setName("test1"); + info.setId(0l); + TimelineProbe probe = new TimelineProbe(color1, "test1", lastUpdate); + view.addProbe(info, probe); + + info = new ThreadInfo(); + info.setName("test2"); + info.setId(1l); + probe = new TimelineProbe(color2, "test2", lastUpdate); + view.addProbe(info, probe); + + added++; + } + return null; + } + }; + worker.execute(); + } + } + + private static UIDefaults createUIDefaults() { + UIDefaults defaults = mock(UIDefaults.class); + when(defaults.getDefaultFont()).thenReturn(new JLabel().getFont()); + when(defaults.getIconColor()).thenReturn(Palette.EARL_GRAY.getColor()); + + return defaults; + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java --- a/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -37,24 +37,14 @@ package com.redhat.thermostat.thread.client.swing.impl; import com.redhat.thermostat.client.swing.UIDefaults; -import com.redhat.thermostat.common.ActionEvent; -import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.shared.locale.Translate; -import com.redhat.thermostat.thread.client.common.ThreadTableBean; import com.redhat.thermostat.thread.client.common.locale.LocaleResources; -import com.redhat.thermostat.thread.client.common.view.ThreadTableView; -import com.redhat.thermostat.thread.client.common.view.ThreadTableView.ThreadSelectionAction; -import com.redhat.thermostat.thread.client.swing.impl.timeline.SwingTimelineDimensionModel; import java.awt.Color; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; -import java.util.concurrent.Semaphore; import javax.swing.JFrame; import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner; import org.fest.swing.annotation.GUITest; -import org.fest.swing.data.TableCell; import org.fest.swing.edt.FailOnThreadViolationRepaintManager; import org.fest.swing.edt.GuiActionRunner; import org.fest.swing.edt.GuiTask; @@ -68,8 +58,6 @@ import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -113,7 +101,7 @@ GuiActionRunner.execute(new GuiTask() { @Override protected void executeInEDT() throws Throwable { - view = new SwingThreadView(defaults, new SwingTimelineDimensionModel()); + view = new SwingThreadView(defaults); frame = new JFrame(); frame.add(view.getUiComponent()); } @@ -157,45 +145,45 @@ togglefixture.requireDisabled(); } - @GUITest - @Test - public void verifTableViewLinksToDetailsView() throws InvocationTargetException, InterruptedException { - - final boolean listenerCalled[] = new boolean[1]; - - ThreadTableBean bean1 = mock(ThreadTableBean.class); - when(bean1.getName()).thenReturn("mocked bean 1"); - - ThreadTableBean bean2 = mock(ThreadTableBean.class); - when(bean2.getName()).thenReturn("mocked bean 2"); - - List threadList = new ArrayList<>(); - threadList.add(bean1); - threadList.add(bean2); - - frameFixture.show(); - - frameFixture.splitPane("threadMainPanelSplitPane").moveDividerTo(0); - frameFixture.tabbedPane("bottomTabbedPane").selectTab(0); - - final Semaphore sem = new Semaphore(1); - ThreadTableView tableView = view.createThreadTableView(); - tableView.addThreadSelectionActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - listenerCalled[0] = true; - view.displayThreadDetails((ThreadTableBean) actionEvent.getPayload()); - sem.release(); - } - }); - - tableView.display(threadList); - - frameFixture.table("threadBeansTable").cell(TableCell.row(1).column(0)).doubleClick(); - sem.acquire(); - - assertTrue(listenerCalled[0]); - assertEquals(1, frameFixture.tabbedPane("bottomTabbedPane").target.getSelectedIndex()); - } +// @GUITest +// @Test +// public void verifTableViewLinksToDetailsView() throws InvocationTargetException, InterruptedException { +// +// final boolean listenerCalled[] = new boolean[1]; +// +// ThreadTableBean bean1 = mock(ThreadTableBean.class); +// when(bean1.getName()).thenReturn("mocked bean 1"); +// +// ThreadTableBean bean2 = mock(ThreadTableBean.class); +// when(bean2.getName()).thenReturn("mocked bean 2"); +// +// List threadList = new ArrayList<>(); +// threadList.add(bean1); +// threadList.add(bean2); +// +// frameFixture.show(); +// +// frameFixture.splitPane("threadMainPanelSplitPane").moveDividerTo(0); +// frameFixture.tabbedPane("bottomTabbedPane").selectTab(0); +// +// final Semaphore sem = new Semaphore(1); +// ThreadTableView tableView = view.createThreadTableView(); +// tableView.addThreadSelectionActionListener(new ActionListener() { +// @Override +// public void actionPerformed(ActionEvent actionEvent) { +// listenerCalled[0] = true; +// view.displayThreadDetails((ThreadTableBean) actionEvent.getPayload()); +// sem.release(); +// } +// }); +// +// tableView.display(threadList); +// +// frameFixture.table("threadBeansTable").cell(TableCell.row(1).column(0)).doubleClick(); +// sem.acquire(); +// +// assertTrue(listenerCalled[0]); +// assertEquals(1, frameFixture.tabbedPane("bottomTabbedPane").target.getSelectedIndex()); +// } } diff -r 504adea43d70 -r b1306c7c7422 thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineRangeModelFormatterTest.java --- a/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/timeline/TimelineRangeModelFormatterTest.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.client.swing.impl.timeline; - -import java.util.Locale; -import java.util.TimeZone; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class TimelineRangeModelFormatterTest { - - private static Locale defaultLocale; - private static TimeZone defaultTimeZone; - - @BeforeClass - public static void setUp() { - defaultLocale = Locale.getDefault(); - Locale.setDefault(Locale.US); - - defaultTimeZone = TimeZone.getDefault(); - TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC")); - } - - @AfterClass - public static void tearDown() { - TimeZone.setDefault(defaultTimeZone); - Locale.setDefault(defaultLocale); - } - - @Test - public void testGetFormattedString() throws Exception { - String range = TimelineRangeModelFormatter.getFormattedString(5_000l); - assertEquals("1970.01.01, 00:00:05", range); - } - - @Test - public void testGetFormattedStringNegative() throws Exception { - String range = TimelineRangeModelFormatter.getFormattedString(-1l); - assertEquals(" - ", range); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/ThreadDao.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/ThreadDao.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/ThreadDao.java Thu Dec 11 11:44:42 2014 +0100 @@ -40,10 +40,11 @@ import com.redhat.thermostat.storage.core.Category; import com.redhat.thermostat.storage.core.Key; import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler; +import com.redhat.thermostat.thread.dao.impl.ThreadDaoKeys; import com.redhat.thermostat.thread.model.SessionID; import com.redhat.thermostat.thread.model.ThreadContentionSample; import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; -import com.redhat.thermostat.thread.model.ThreadHeader; import com.redhat.thermostat.thread.model.ThreadSession; import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; @@ -53,12 +54,10 @@ public interface ThreadDao { - /* - * User-facing string-constants used to represent VM thread capabilities. - */ - static final String CPU_TIME = "thread-cpu-time"; - static final String CONTENTION_MONITOR = "thread-contention-monitor"; - static final String THREAD_ALLOCATED_MEMORY = "thread-allocated-memory"; + public static enum Sort { + ASCENDING, + DESCENDING, + } /* * vm-thread-harvesting schema @@ -74,34 +73,6 @@ Arrays.>asList(Key.TIMESTAMP)); /* - * vm-thread-header schema - */ - static final Key THREAD_ID_KEY = new Key("threadId"); - static final Key THREAD_NAME_KEY = new Key("threadName"); - static final Key THREAD_HEADER_UUID = new Key("referenceID"); - static final Category THREAD_HEADER = - new Category<>("vm-thread-header", ThreadHeader.class, - Arrays.>asList(Key.AGENT_ID, Key.VM_ID, - THREAD_NAME_KEY, THREAD_HEADER_UUID, - THREAD_ID_KEY, Key.TIMESTAMP), - Arrays.>asList(Key.TIMESTAMP, THREAD_NAME_KEY, - THREAD_ID_KEY, THREAD_HEADER_UUID)); - - /* - * vm-thread-state schema - */ - static final Key THREAD_STATE_KEY = new Key("state"); - static final Key THREAD_PROBE_START = new Key("probeStartTime"); - static final Key THREAD_PROBE_END = new Key("probeEndTime"); - static final Category THREAD_STATE = - new Category<>("vm-thread-state", ThreadState.class, - Arrays.>asList(Key.AGENT_ID, Key.VM_ID, THREAD_STATE_KEY, - THREAD_PROBE_START, THREAD_PROBE_END, - THREAD_HEADER_UUID), - Arrays.>asList(THREAD_PROBE_START, THREAD_PROBE_END, - THREAD_HEADER_UUID)); - - /* * vm-deadlock-data schema */ static final Key DEADLOCK_DESCRIPTION_KEY = new Key<>("deadLockDescription"); @@ -124,13 +95,13 @@ THREAD_CONTENTION_BLOCKED_TIME_KEY, THREAD_CONTENTION_WAITED_COUNT_KEY, THREAD_CONTENTION_WAITED_TIME_KEY, - THREAD_HEADER_UUID, Key.TIMESTAMP), + ThreadDaoKeys.THREAD_HEADER_UUID, Key.TIMESTAMP), Arrays.>asList(Key.AGENT_ID, Key.VM_ID, THREAD_CONTENTION_BLOCKED_COUNT_KEY, THREAD_CONTENTION_BLOCKED_TIME_KEY, THREAD_CONTENTION_WAITED_COUNT_KEY, THREAD_CONTENTION_WAITED_TIME_KEY, - THREAD_HEADER_UUID, Key.TIMESTAMP)); + ThreadDaoKeys.THREAD_HEADER_UUID, Key.TIMESTAMP)); void saveSummary(ThreadSummary summary); List getSummary(VmRef ref, SessionID session, Range range, int limit); @@ -138,34 +109,13 @@ /** * Returns a list of sessions registered by thread sampling. */ - List getSessions(VmRef ref, Range range, int limit); + List getSessions(VmRef ref, Range range, int limit, Sort order); /** * Save the given session to the database. */ void saveSession(ThreadSession session); - /** - * Gets the total time interval for the entire data related to - * {@link ThreadState}, as a {@link Range}. - * - *

- * - * This {@link Range#getMin()} will return the start probe time for the - * oldest {@link ThreadState} entry while {@link Range#getMax()} will - * contains the end probe time for the most recent {@link ThreadState} - * entry. - * - *

- * - * If no data is contained related to this {@link VmRef}, {@code null} - * will be returned. - * - * @returns a {@link Range} of timestamps (in milliseconds) or null if there - * is no valid data. - */ - Range getThreadStateTotalTimeRange(VmRef ref); - ThreadHarvestingStatus getLatestHarvestingStatus(VmRef vm); void saveHarvestingStatus(ThreadHarvestingStatus status); @@ -177,36 +127,6 @@ * @return the latest data or null if there is none */ VmDeadLockData loadLatestDeadLockStatus(VmRef ref); - - /** - * Returns the list of known {@link ThreadHeader}s for the given VM. - * The list is sorted by timestamp. - */ - List getThreads(VmRef ref); - - /** - * Returns the actual {@link ThreadHeader} in the storage based on th - * input {@link ThreadHeader} template, {@code null} otherwise. - */ - ThreadHeader getThread(ThreadHeader thread); - - /** - * Adds the {@link ThreadHeader} into the target {@link VmRef} storage. - * If the target vm already has such entry the - */ - void saveThread(ThreadHeader thread); - - /** - * Returns the last known {@link ThreadState} in the database for this - * {@link ThreadHeader}. - */ - ThreadState getLastThreadState(ThreadHeader header); - - /** - * Returns the first known {@link ThreadState} in the database for this - * {@link ThreadHeader}. - */ - ThreadState getFirstThreadState(ThreadHeader thread); /** * Adds the given {@link ThreadState} to storage. @@ -214,29 +134,25 @@ void addThreadState(ThreadState thread); /** - * Updates the given {@link ThreadState} - */ - void updateThreadState(ThreadState thread); - - /** - * Return a list of {@link ThreadState} for the given {@link ThreadHeader} - * in the given {@link Range}. - */ - List getThreadStates(ThreadHeader thread, Range range); - - /** - * Adds this {@link ThreadContentionSample} to the database. - * - *

- * - * The sample must be fully created and valid, in particular, its - * {@link ThreadHeader} must be a valid entry in the database. */ void saveContentionSample(ThreadContentionSample contentionSample); /** - * Returns the latest {@link ThreadContentionSample} available for this - * {@link ThreadHeader}. + */ + ThreadContentionSample getLatestContentionSample(VmRef ref, SessionID session); + + + /** + * Return the oldest session registered in the database. */ - ThreadContentionSample getLatestContentionSample(ThreadHeader thread); + ThreadSession getFirstSession(VmRef ref); + + /** + * Return the newest session registered in the database. + */ + ThreadSession getLastSession(VmRef ref); + + void getThreadStates(VmRef ref, SessionID session, + ResultHandler handler, + Range range, int limit, Sort order); } diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistration.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistration.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistration.java Thu Dec 11 11:44:42 2014 +0100 @@ -56,8 +56,6 @@ categories.add(ThreadDao.DEADLOCK_INFO.getName()); categories.add(ThreadDao.THREAD_HARVESTING_STATUS.getName()); - categories.add(ThreadDao.THREAD_HEADER.getName()); - categories.add(ThreadDao.THREAD_STATE.getName()); categories.add(ThreadDao.THREAD_CONTENTION_SAMPLE.getName()); ThreadDaoCategories.register(categories); diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoCategories.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoCategories.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoCategories.java Thu Dec 11 11:44:42 2014 +0100 @@ -39,9 +39,10 @@ import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.storage.core.Category; import com.redhat.thermostat.storage.core.Storage; +import com.redhat.thermostat.storage.core.experimental.statement.CategoryBuilder; import com.redhat.thermostat.storage.model.Pojo; -import com.redhat.thermostat.storage.core.experimental.statement.CategoryBuilder; import com.redhat.thermostat.thread.model.ThreadSession; +import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; import java.util.ArrayList; import java.util.Collection; @@ -58,12 +59,15 @@ public static class Categories { public static final String SUMMARY = "vm-thread-summary"; public static final String SESSION = "vm-thread-session"; + public static final String STATE = "vm-thread-state"; + } static final List> BEANS = new ArrayList<>(); static { BEANS.add(ThreadSummary.class); BEANS.add(ThreadSession.class); + BEANS.add(ThreadState.class); } public static void register(Collection collection) { diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java Thu Dec 11 11:44:42 2014 +0100 @@ -47,20 +47,20 @@ import com.redhat.thermostat.storage.core.StatementExecutionException; import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.VmRef; -import com.redhat.thermostat.storage.model.Pojo; -import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.dao.impl.statement.SessionQuery; -import com.redhat.thermostat.thread.dao.impl.statement.SummaryQuery; import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapter; import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapterBuilder; - +import com.redhat.thermostat.storage.core.experimental.statement.Id; import com.redhat.thermostat.storage.core.experimental.statement.Query; import com.redhat.thermostat.storage.core.experimental.statement.QueryValues; import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler; +import com.redhat.thermostat.storage.model.Pojo; +import com.redhat.thermostat.thread.dao.ThreadDao; +import com.redhat.thermostat.thread.dao.impl.statement.StateQueries; +import com.redhat.thermostat.thread.dao.impl.statement.SessionQueries; +import com.redhat.thermostat.thread.dao.impl.statement.SummaryQuery; import com.redhat.thermostat.thread.model.SessionID; import com.redhat.thermostat.thread.model.ThreadContentionSample; import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; -import com.redhat.thermostat.thread.model.ThreadHeader; import com.redhat.thermostat.thread.model.ThreadSession; import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; @@ -75,10 +75,9 @@ private static final Logger logger = LoggingUtils.getLogger(ThreadDaoImpl.class); - static final BeanAdapter SUMMARY = new BeanAdapterBuilder<>(ThreadSummary.class, new SummaryQuery()).build(); - static final BeanAdapter SESSIONS = new BeanAdapterBuilder<>(ThreadSession.class, new SessionQuery()).build(); - - // Queries + static final BeanAdapter ThreadSummaryAdapter = new BeanAdapterBuilder<>(ThreadSummary.class, new SummaryQuery()).build(); + static final BeanAdapter ThreadSessionAdapter = new BeanAdapterBuilder<>(ThreadSession.class, SessionQueries.asList()).build(); + static final BeanAdapter ThreadStateAdapter = new BeanAdapterBuilder<>(ThreadState.class, StateQueries.asList()).build(); static final String QUERY_LATEST_HARVESTING_STATUS = "QUERY " + THREAD_HARVESTING_STATUS.getName() + " WHERE '" @@ -86,100 +85,24 @@ + Key.VM_ID.getName() + "' = ?s SORT '" + Key.TIMESTAMP.getName() + "' DSC LIMIT 1"; - static final String QUERY_LATEST_THREAD_STATE_FOR_THREAD = "QUERY " - + THREAD_STATE.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + THREAD_HEADER_UUID.getName() + "' = ?s SORT '" - + THREAD_PROBE_END.getName() + "' DSC LIMIT 1"; - - static final String QUERY_FIRST_THREAD_STATE_FOR_THREAD = "QUERY " - + THREAD_STATE.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + THREAD_HEADER_UUID.getName() + "' = ?s SORT '" - + THREAD_PROBE_START.getName() + "' ASC LIMIT 1"; - - static final String QUERY_OLDEST_THREAD_STATE = "QUERY " - + THREAD_STATE.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + Key.VM_ID.getName() + "' = ?s SORT '" - + THREAD_PROBE_START.getName() + "' ASC LIMIT 1"; - - static final String QUERY_LATEST_THREAD_STATE= "QUERY " - + THREAD_STATE.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + Key.VM_ID.getName() + "' = ?s SORT '" - + THREAD_PROBE_END.getName() + "' DSC LIMIT 1"; - static final String QUERY_LATEST_DEADLOCK_INFO = "QUERY " + DEADLOCK_INFO.getName() + " WHERE '" + Key.AGENT_ID.getName() + "' = ?s AND '" + Key.VM_ID.getName() + "' = ?s SORT '" + Key.TIMESTAMP.getName() + "' DSC LIMIT 1"; - static final String QUERY_THREAD_HEADER = "QUERY " - + THREAD_HEADER.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + Key.VM_ID.getName() + "' = ?s AND '" - + THREAD_NAME_KEY.getName() + "' = ?s AND '" - + THREAD_ID_KEY.getName() + "' = ?l LIMIT 1"; - static final String QUERY_ALL_THREAD_HEADERS = "QUERY " - + THREAD_HEADER.getName() + " WHERE '" - + Key.AGENT_ID.getName() + "' = ?s AND '" - + Key.VM_ID.getName() + "' = ?s SORT '" - + Key.TIMESTAMP.getName() + "' DSC"; - - static final String QUERY_THREAD_STATE_PER_THREAD = "QUERY " - + THREAD_STATE.getName() + " WHERE '" - + THREAD_HEADER_UUID.getName() + "' = ?s AND '" - + THREAD_PROBE_END.getName() + "' >= ?l AND '" - + THREAD_PROBE_START.getName() + "' <= ?l SORT '" - + THREAD_PROBE_START.getName() + "' ASC"; - - // Data modifying descriptors - - // ADD vm-thread-harvesting SET 'agentId' = ?s , \ - // 'vmId' = ?s , \ - // 'timeStamp' = ?l , \ - // 'harvesting' = ?b static final String DESC_ADD_THREAD_HARVESTING_STATUS = "ADD " + THREAD_HARVESTING_STATUS.getName() + " SET '" + Key.AGENT_ID.getName() + "' = ?s , " + "'" + Key.VM_ID.getName() + "' = ?s , " + "'" + Key.TIMESTAMP.getName() + "' = ?l , " + "'" + HARVESTING_STATUS_KEY.getName() + "' = ?b"; - // ADD vm-deadlock-data SET 'agentId' = ?s , \ - // 'vmId' = ?s , \ - // 'timeStamp' = ?l , \ - // 'deadLockDescription' = ?s static final String DESC_ADD_THREAD_DEADLOCK_DATA = "ADD " + DEADLOCK_INFO.getName() + " SET '" + Key.AGENT_ID.getName() + "' = ?s , " + "'" + Key.VM_ID.getName() + "' = ?s , " + "'" + Key.TIMESTAMP.getName() + "' = ?l , " + "'" + DEADLOCK_DESCRIPTION_KEY.getName() + "' = ?s"; - static final String ADD_THREAD_HEADER = - "ADD " + THREAD_HEADER.getName() + " " + - "SET '" + Key.AGENT_ID.getName() + "' = ?s , " + - "'" + Key.VM_ID.getName() + "' = ?s , " + - "'" + THREAD_NAME_KEY.getName() + "' = ?s , " + - "'" + THREAD_ID_KEY.getName() + "' = ?l , " + - "'" + Key.TIMESTAMP.getName() + "' = ?l , " + - "'" + THREAD_HEADER_UUID.getName() + "' = ?s"; - - static final String ADD_THREAD_STATE = - "ADD " + THREAD_STATE.getName() + " " + - "SET '" + Key.AGENT_ID.getName() + "' = ?s , " + - "'" + Key.VM_ID.getName() + "' = ?s , " + - "'" + THREAD_STATE_KEY.getName() + "' = ?s , " + - "'" + THREAD_PROBE_START.getName() + "' = ?l , " + - "'" + THREAD_PROBE_END.getName() + "' = ?l , " + - "'" + THREAD_HEADER_UUID.getName() + "' = ?s"; - - static final String DESC_UPDATE_THREAD_STATE = - "UPDATE " + THREAD_STATE.getName() + " " + - "SET '" + THREAD_PROBE_END.getName() + "' = ?l " + - "WHERE '" + THREAD_HEADER_UUID.getName() + "' = ?s AND " + - "'" + THREAD_PROBE_START.getName() + "' = ?l"; static final String ADD_CONTENTION_SAMPLE = "ADD " + THREAD_CONTENTION_SAMPLE.getName() + " " + @@ -189,12 +112,12 @@ "'" + THREAD_CONTENTION_BLOCKED_TIME_KEY.getName() + "' = ?l , " + "'" + THREAD_CONTENTION_WAITED_COUNT_KEY.getName() + "' = ?l , " + "'" + THREAD_CONTENTION_WAITED_TIME_KEY.getName() + "' = ?l , " + - "'" + THREAD_HEADER_UUID.getName() + "' = ?s , " + + "'" + ThreadDaoKeys.THREAD_HEADER_UUID.getName() + "' = ?s , " + "'" + Key.TIMESTAMP.getName() + "' = ?l"; static final String GET_LATEST_CONTENTION_SAMPLE= "QUERY " + THREAD_CONTENTION_SAMPLE.getName() + " WHERE '" - + THREAD_HEADER_UUID.getName() + "' = ?s SORT '" + + ThreadDaoKeys.THREAD_HEADER_UUID.getName() + "' = ?s SORT '" + Key.TIMESTAMP.getName() + "' DSC LIMIT 1"; private Storage storage; @@ -205,264 +128,15 @@ ThreadDaoCategories.register(storage); storage.registerCategory(THREAD_HARVESTING_STATUS); - storage.registerCategory(THREAD_HEADER); - storage.registerCategory(THREAD_STATE); storage.registerCategory(THREAD_CONTENTION_SAMPLE); storage.registerCategory(DEADLOCK_INFO); } @Override - public List getThreads(VmRef ref) { - - List result = null; - - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_HEADER, QUERY_ALL_THREAD_HEADERS); - - PreparedStatement stmt; - try { - - stmt = storage.prepareStatement(desc); - stmt.setString(0, ref.getHostRef().getAgentId()); - stmt.setString(1, ref.getVmId()); - - result = getAllResults(stmt); - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } - - return result; - } - - @Override - public ThreadHeader getThread(ThreadHeader thread) { - - ThreadHeader result = null; - - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_HEADER, QUERY_THREAD_HEADER); - - PreparedStatement prepared; - - try { - prepared = storage.prepareStatement(desc); - prepared.setString(0, thread.getAgentId()); - prepared.setString(1, thread.getVmId()); - prepared.setString(2, thread.getThreadName()); - prepared.setLong(3, thread.getThreadId()); - - result = getFirstResult(prepared); - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } - - return result; - } - - @Override - public void saveThread(ThreadHeader thread) { - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_HEADER, ADD_THREAD_HEADER); - - PreparedStatement prepared; - - try { - prepared = storage.prepareStatement(desc); - prepared.setString(0, thread.getAgentId()); - prepared.setString(1, thread.getVmId()); - prepared.setString(2, thread.getThreadName()); - prepared.setLong(3, thread.getThreadId()); - prepared.setLong(4, thread.getTimeStamp()); - prepared.setString(5, thread.getReferenceID()); - - prepared.execute(); - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } catch (StatementExecutionException e) { - logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); - } - } - - @Override - public ThreadState getLastThreadState(ThreadHeader header) { - - ThreadState result = null; - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_STATE, - QUERY_LATEST_THREAD_STATE_FOR_THREAD); - - PreparedStatement prepared; - try { - - prepared = storage.prepareStatement(desc); - String refId = header.getReferenceID(); - if (refId == null) { - throw new IllegalArgumentException("header.getReferenceID() can't be null"); - } - - prepared.setString(0, header.getAgentId()); - prepared.setString(1, header.getReferenceID()); - - result = getFirstResult(prepared); - if (result != null) { - result.setHeader(header); - } - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } - - return result; - } - - public ThreadState getFirstThreadState(ThreadHeader header) { - - ThreadState result = null; - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_STATE, - QUERY_FIRST_THREAD_STATE_FOR_THREAD); - - PreparedStatement prepared; - try { - - prepared = storage.prepareStatement(desc); - String refId = header.getReferenceID(); - if (refId == null) { - throw new IllegalArgumentException("header.getReferenceID() can't be null"); - } - - prepared.setString(0, header.getAgentId()); - prepared.setString(1, header.getReferenceID()); - - result = getFirstResult(prepared); - if (result != null) { - result.setHeader(header); - } - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } - - return result; - } - - @Override - public void addThreadState(ThreadState thread) { - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_STATE, ADD_THREAD_STATE); - - PreparedStatement prepared; - try { - - prepared = storage.prepareStatement(desc); - - ThreadHeader header = thread.getHeader(); - - prepared.setString(0, header.getAgentId()); - prepared.setString(1, header.getVmId()); - - prepared.setString(2, thread.getState()); - - prepared.setLong(3, thread.getProbeStartTime()); - prepared.setLong(4, thread.getProbeEndTime()); - - prepared.setString(5, header.getReferenceID()); - - prepared.execute(); - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } catch (StatementExecutionException e) { - logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); - } - } - - @Override - public void updateThreadState(ThreadState thread) { - - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_STATE, DESC_UPDATE_THREAD_STATE); - - PreparedStatement prepared; - try { - - prepared = storage.prepareStatement(desc); - - ThreadHeader header = thread.getHeader(); - - prepared.setLong(0, thread.getProbeEndTime()); - prepared.setString(1, header.getReferenceID()); - prepared.setLong(2, thread.getProbeStartTime()); - - prepared.execute(); - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } catch (StatementExecutionException e) { - logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); - } - } - - @Override - public List getThreadStates(ThreadHeader thread, Range range) { - - List result = new ArrayList<>(); - - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_STATE, QUERY_THREAD_STATE_PER_THREAD); - - PreparedStatement prepared; - try { - - prepared = storage.prepareStatement(desc); - - prepared.setString(0, thread.getReferenceID()); - prepared.setLong(1, range.getMin()); - prepared.setLong(2, range.getMax()); - - Cursor cursor = prepared.executeQuery(); - while (cursor.hasNext()) { - ThreadState state = cursor.next(); - state.setHeader(thread); - result.add(state); - } - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } catch (StatementExecutionException e) { - logger.log(Level.SEVERE, "Executing query '" + desc + "' failed!", e); - } - return result; - } - - @Override - public Range getThreadStateTotalTimeRange(VmRef ref) { - - PreparedStatement stmt; - - stmt = prepareQuery(THREAD_STATE, QUERY_OLDEST_THREAD_STATE, ref); - ThreadState oldestData = getFirstResult(stmt); - if (oldestData == null) { - return null; - } - - long oldestTimeStamp = oldestData.getRange().getMin(); - - stmt = prepareQuery(THREAD_STATE, QUERY_LATEST_THREAD_STATE, ref); - ThreadState latestData = getFirstResult(stmt); - long latestTimeStamp = latestData.getRange().getMax(); - - return new Range(oldestTimeStamp, latestTimeStamp); - } - - @Override public void saveSummary(ThreadSummary summary) { try { - SUMMARY.insert(summary, storage); + ThreadSummaryAdapter.insert(summary, storage); } catch (StatementExecutionException e) { logger.log(Level.SEVERE, "Exception saving summary: " + summary, e); @@ -470,20 +144,59 @@ } @Override + public void addThreadState(ThreadState thread) { + try { + ThreadStateAdapter.insert(thread, storage); + + } catch (StatementExecutionException e) { + logger.log(Level.SEVERE, "Exception saving thread state: " + thread, e); + } + } + + @Override + public void getThreadStates(VmRef ref, SessionID session, + final ResultHandler handler, + Range range, int limit, Sort order) + { + Id id = order.equals(Sort.ASCENDING) ? StateQueries.getAscending : + StateQueries.getDescending; + + Query query = ThreadStateAdapter.getQuery(id); + + QueryValues values = query.createValues(); + values.set(StateQueries.CriteriaId.vmId, ref.getVmId()); + values.set(StateQueries.CriteriaId.agentId, ref.getHostRef().getAgentId()); + values.set(StateQueries.CriteriaId.sessionID, session.get()); + + values.set(StateQueries.CriteriaId.timeStampGEQ, range.getMin()); + values.set(StateQueries.CriteriaId.timeStampLEQ, range.getMax()); + values.set(StateQueries.CriteriaId.limit, limit); + + try { + ThreadStateAdapter.query(values, handler, storage); + + } catch (StatementExecutionException e) { + logger.log(Level.SEVERE, "Exception retrieving thread summary", e); + } + } + + @Override public List getSummary(VmRef ref, SessionID session, Range range, int limit) { final List results = new ArrayList<>(); - Query query = SUMMARY.getQuery(SummaryQuery.id); + Query query = ThreadSummaryAdapter.getQuery(SummaryQuery.id); QueryValues values = query.createValues(); - values.set(SummaryQuery.CriteriaId.getVmId, ref.getVmId()); + values.set(SummaryQuery.CriteriaId.vmId, ref.getVmId()); + values.set(SummaryQuery.CriteriaId.agentId, ref.getHostRef().getAgentId()); values.set(SummaryQuery.CriteriaId.sessionID, session.get()); + values.set(SummaryQuery.CriteriaId.timeStampGEQ, range.getMin()); values.set(SummaryQuery.CriteriaId.timeStampLEQ, range.getMax()); values.set(SummaryQuery.CriteriaId.limit, limit); try { - SUMMARY.query(values, new ResultHandler() { + ThreadSummaryAdapter.query(values, new ResultHandler() { @Override public void onResult(ThreadSummary result) { results.add(result); @@ -491,26 +204,47 @@ }, storage); } catch (StatementExecutionException e) { - e.printStackTrace(); + logger.log(Level.SEVERE, "Exception retrieving thread summary", e); } return results; } @Override - public List getSessions(VmRef ref, Range range, int limit) { + public ThreadSession getFirstSession(VmRef ref) { + Range range = new Range<>(Long.MIN_VALUE, Long.MAX_VALUE); + List results = getSessions(ref, range, 1, Sort.ASCENDING); + return results.isEmpty() ? null : results.get(0); + } + + @Override + public ThreadSession getLastSession(VmRef ref) { + Range range = new Range<>(Long.MIN_VALUE, Long.MAX_VALUE); + List results = getSessions(ref, range, 1, Sort.DESCENDING); + return results.isEmpty() ? null : results.get(0); + } + + @Override + public List getSessions(VmRef ref, Range range, + int limit, Sort order) + { final List results = new ArrayList<>(); - Query query = SESSIONS.getQuery(SessionQuery.id); + Id id = order.equals(Sort.ASCENDING) ? SessionQueries.getRangeAscending : + SessionQueries.getRangeDescending; + + Query query = ThreadSessionAdapter.getQuery(id); QueryValues values = query.createValues(); - values.set(SessionQuery.CriteriaId.getVmId, ref.getVmId()); - values.set(SessionQuery.CriteriaId.timeStampGEQ, range.getMin()); - values.set(SessionQuery.CriteriaId.timeStampLEQ, range.getMax()); - values.set(SessionQuery.CriteriaId.limit, limit); + values.set(SessionQueries.CriteriaId.vmId, ref.getVmId()); + values.set(SessionQueries.CriteriaId.agentId, ref.getHostRef().getAgentId()); + + values.set(SessionQueries.CriteriaId.timeStampGEQ, range.getMin()); + values.set(SessionQueries.CriteriaId.timeStampLEQ, range.getMax()); + values.set(SessionQueries.CriteriaId.limit, limit); try { - SESSIONS.query(values, new ResultHandler() { + ThreadSessionAdapter.query(values, new ResultHandler() { @Override public void onResult(ThreadSession result) { results.add(result); @@ -518,7 +252,7 @@ }, storage); } catch (StatementExecutionException e) { - e.printStackTrace(); + logger.log(Level.SEVERE, "Exception retrieving thread session", e); } return results; @@ -526,7 +260,7 @@ public void saveSession(ThreadSession session) { try { - SESSIONS.insert(session, storage); + ThreadSessionAdapter.insert(session, storage); } catch (StatementExecutionException e) { logger.log(Level.SEVERE, "Exception saving session: " + session, e); @@ -593,68 +327,68 @@ @Override public void saveContentionSample(ThreadContentionSample contentionSample) { - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_CONTENTION_SAMPLE, - ADD_CONTENTION_SAMPLE); - PreparedStatement prepared; - ThreadHeader header = contentionSample.getHeader(); - if (header == null || header.getReferenceID() == null) { - throw new IllegalArgumentException("header or header.getReferenceID() can't be null"); - } - - try { - prepared = storage.prepareStatement(desc); - - prepared.setString(0, header.getAgentId()); - prepared.setString(1, header.getVmId()); - - prepared.setLong(2, contentionSample.getBlockedCount()); - prepared.setLong(3, contentionSample.getBlockedTime()); - prepared.setLong(4, contentionSample.getWaitedCount()); - prepared.setLong(5, contentionSample.getWaitedTime()); - - prepared.setString(6, header.getReferenceID()); - - prepared.setLong(7, contentionSample.getTimeStamp()); - - prepared.execute(); - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } catch (StatementExecutionException e) { - logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); - } +// StatementDescriptor desc = +// new StatementDescriptor<>(THREAD_CONTENTION_SAMPLE, +// ADD_CONTENTION_SAMPLE); +// PreparedStatement prepared; +// ThreadHeader header = contentionSample.getHeader(); +// if (header == null || header.getReferenceID() == null) { +// throw new IllegalArgumentException("header or header.getReferenceID() can't be null"); +// } +// +// try { +// prepared = storage.prepareStatement(desc); +// +// prepared.setString(0, header.getAgentId()); +// prepared.setString(1, header.getVmId()); +// +// prepared.setLong(2, contentionSample.getBlockedCount()); +// prepared.setLong(3, contentionSample.getBlockedTime()); +// prepared.setLong(4, contentionSample.getWaitedCount()); +// prepared.setLong(5, contentionSample.getWaitedTime()); +// +// prepared.setString(6, header.getReferenceID()); +// +// prepared.setLong(7, contentionSample.getTimeStamp()); +// +// prepared.execute(); +// +// } catch (DescriptorParsingException e) { +// logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); +// } catch (StatementExecutionException e) { +// logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); +// } } @Override - public ThreadContentionSample getLatestContentionSample(ThreadHeader thread) { + public ThreadContentionSample getLatestContentionSample(VmRef ref, SessionID session) { ThreadContentionSample sample = null; - StatementDescriptor desc = - new StatementDescriptor<>(THREAD_CONTENTION_SAMPLE, - GET_LATEST_CONTENTION_SAMPLE); - PreparedStatement prepared; - - if (thread == null || thread.getReferenceID() == null) { - throw new IllegalArgumentException("header or header.getReferenceID() can't be null"); - } - - try { - prepared = storage.prepareStatement(desc); - - prepared.setString(0, thread.getReferenceID()); - Cursor cursor = prepared.executeQuery(); - if (cursor.hasNext()) { - sample = cursor.next(); - sample.setHeader(thread); - } - - } catch (DescriptorParsingException e) { - logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); - } catch (StatementExecutionException e) { - logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); - } +// StatementDescriptor desc = +// new StatementDescriptor<>(THREAD_CONTENTION_SAMPLE, +// GET_LATEST_CONTENTION_SAMPLE); +// PreparedStatement prepared; +// +// if (thread == null || thread.getReferenceID() == null) { +// throw new IllegalArgumentException("header or header.getReferenceID() can't be null"); +// } +// +// try { +// prepared = storage.prepareStatement(desc); +// +// prepared.setString(0, thread.getReferenceID()); +// Cursor cursor = prepared.executeQuery(); +// if (cursor.hasNext()) { +// sample = cursor.next(); +// sample.setHeader(thread); +// } +// +// } catch (DescriptorParsingException e) { +// logger.log(Level.SEVERE, "Preparing stmt '" + desc + "' failed!", e); +// } catch (StatementExecutionException e) { +// logger.log(Level.SEVERE, "Executing stmt '" + desc + "' failed!", e); +// } return sample; } diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplStatementDescriptorRegistration.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplStatementDescriptorRegistration.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplStatementDescriptorRegistration.java Thu Dec 11 11:44:42 2014 +0100 @@ -38,9 +38,7 @@ import com.redhat.thermostat.storage.core.PreparedParameter; import com.redhat.thermostat.storage.core.auth.DescriptorMetadata; -import com.redhat.thermostat.storage.core.auth.StatementDescriptorMetadataFactory; import com.redhat.thermostat.storage.core.auth.StatementDescriptorRegistration; - import java.util.HashSet; import java.util.Set; @@ -53,35 +51,21 @@ StatementDescriptorRegistration { private final Set descs; - + public ThreadDaoImplStatementDescriptorRegistration() { descs = new HashSet<>(); descs.add(ThreadDaoImpl.QUERY_LATEST_DEADLOCK_INFO); descs.add(ThreadDaoImpl.QUERY_LATEST_HARVESTING_STATUS); // TODO: this needs to go in an helper class - descs.addAll(ThreadDaoImpl.SUMMARY.describeStatements()); - descs.addAll(ThreadDaoImpl.SESSIONS.describeStatements()); + descs.addAll(ThreadDaoImpl.ThreadSummaryAdapter.describeStatements()); + descs.addAll(ThreadDaoImpl.ThreadSessionAdapter.describeStatements()); + descs.addAll(ThreadDaoImpl.ThreadStateAdapter.describeStatements()); descs.add(ThreadDaoImpl.DESC_ADD_THREAD_DEADLOCK_DATA); descs.add(ThreadDaoImpl.DESC_ADD_THREAD_HARVESTING_STATUS); - - descs.add(ThreadDaoImpl.ADD_THREAD_HEADER); - descs.add(ThreadDaoImpl.QUERY_THREAD_HEADER); - descs.add(ThreadDaoImpl.QUERY_ALL_THREAD_HEADERS); - - descs.add(ThreadDaoImpl.ADD_THREAD_STATE); - descs.add(ThreadDaoImpl.QUERY_LATEST_THREAD_STATE_FOR_THREAD); - descs.add(ThreadDaoImpl.QUERY_FIRST_THREAD_STATE_FOR_THREAD); - - descs.add(ThreadDaoImpl.QUERY_OLDEST_THREAD_STATE); - descs.add(ThreadDaoImpl.QUERY_LATEST_THREAD_STATE); - - descs.add(ThreadDaoImpl.QUERY_THREAD_STATE_PER_THREAD); - descs.add(ThreadDaoImpl.ADD_CONTENTION_SAMPLE); descs.add(ThreadDaoImpl.GET_LATEST_CONTENTION_SAMPLE); - descs.add(ThreadDaoImpl.DESC_UPDATE_THREAD_STATE); } @Override diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoKeys.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoKeys.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoKeys.java Thu Dec 11 11:44:42 2014 +0100 @@ -43,18 +43,5 @@ */ public class ThreadDaoKeys { - public static enum Keys { - - vmId, - agentId, - timeStamp, - session, - currentLiveThreads, - currentDaemonThreads, - - } - - public static final Key SESSION = new Key<>(Keys.session.name()); - public static final Key LIVE_THREADS_KEY = new Key(Keys.currentLiveThreads.name()); - public static final Key DAEMON_THREADS_KEY = new Key(Keys.currentDaemonThreads.name()); + public static final Key THREAD_HEADER_UUID = new Key("referenceID"); } diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueries.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueries.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,130 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.dao.impl.statement; + +import com.redhat.thermostat.storage.core.experimental.statement.FieldDescriptor; +import com.redhat.thermostat.storage.core.experimental.statement.Id; +import com.redhat.thermostat.storage.core.experimental.statement.LimitCriterion; +import com.redhat.thermostat.storage.core.experimental.statement.Query; +import com.redhat.thermostat.storage.core.experimental.statement.SortCriterion; +import com.redhat.thermostat.storage.core.experimental.statement.StatementUtils; +import com.redhat.thermostat.storage.core.experimental.statement.TypeMapper; +import com.redhat.thermostat.storage.core.experimental.statement.WhereCriterion; +import com.redhat.thermostat.thread.model.ThreadSession; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * + */ +public class SessionQueries { + + public static final Id getRangeAscending = new Id("SessionQueries::getRangeAscending"); + public static final Id getRangeDescending = new Id("SessionQueries::getRangeDescending"); + + public static class CriteriaId { + public static final Id vmId = new Id("vmId"); + public static final Id agentId = new Id("agentId"); + public static final Id timeStampGEQ = new Id("timeStampGEQ"); + public static final Id timeStampLEQ = new Id("timeStampLEQ"); + public static final Id limit = new Id("limit"); + } + + private static class GetDescending extends Query { + @Override + protected void describe(Criteria criteria) { + List descriptors = StatementUtils.createDescriptors(ThreadSession.class); + final Map map = StatementUtils.createDescriptorMap(descriptors); + + criteria.add(new WhereCriterion(CriteriaId.vmId, map.get("vmId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.agentId, map.get("agentId"), + TypeMapper.Criteria.Equal)); + + criteria.add(new WhereCriterion(CriteriaId.timeStampGEQ, map.get("timeStamp"), + TypeMapper.Criteria.GreaterEqual)); + criteria.add(new WhereCriterion(CriteriaId.timeStampLEQ, map.get("timeStamp"), + TypeMapper.Criteria.LessEqual)); + + criteria.add(new SortCriterion(map.get("timeStamp"), TypeMapper.Sort.Descending)); + criteria.add(new LimitCriterion(CriteriaId.limit)); + } + + @Override + public Id getId() { + return getRangeDescending; + } + } + + private static class GetAscending extends Query { + @Override + protected void describe(Criteria criteria) { + List descriptors = StatementUtils.createDescriptors(ThreadSession.class); + final Map map = StatementUtils.createDescriptorMap(descriptors); + + criteria.add(new WhereCriterion(CriteriaId.vmId, map.get("vmId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.agentId, map.get("agentId"), + TypeMapper.Criteria.Equal)); + + criteria.add(new WhereCriterion(CriteriaId.timeStampGEQ, map.get("timeStamp"), + TypeMapper.Criteria.GreaterEqual)); + criteria.add(new WhereCriterion(CriteriaId.timeStampLEQ, map.get("timeStamp"), + TypeMapper.Criteria.LessEqual)); + + criteria.add(new SortCriterion(map.get("timeStamp"), TypeMapper.Sort.Ascending)); + criteria.add(new LimitCriterion(CriteriaId.limit)); + } + + @Override + public Id getId() { + return getRangeAscending; + } + } + + private static final List> queries = new ArrayList<>(); + static { + queries.add(new GetDescending()); + queries.add(new GetAscending()); + } + + public static List> asList() { + return Collections.unmodifiableList(queries); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQuery.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQuery.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.dao.impl.statement; - -import com.redhat.thermostat.storage.core.experimental.statement.FieldDescriptor; -import com.redhat.thermostat.storage.core.experimental.statement.Id; -import com.redhat.thermostat.storage.core.experimental.statement.LimitCriterion; -import com.redhat.thermostat.storage.core.experimental.statement.Query; -import com.redhat.thermostat.storage.core.experimental.statement.SortCriterion; -import com.redhat.thermostat.storage.core.experimental.statement.StatementUtils; -import com.redhat.thermostat.storage.core.experimental.statement.TypeMapper; -import com.redhat.thermostat.storage.core.experimental.statement.WhereCriterion; -import com.redhat.thermostat.thread.model.ThreadSession; -import java.util.List; -import java.util.Map; - -/** - * - */ -public class SessionQuery extends Query { - - public static final Id id = new Id(ThreadSession.class.getSimpleName()); - - public static class CriteriaId { - public static final Id getVmId = new Id("0"); - public static final Id timeStampGEQ = new Id("1"); - public static final Id timeStampLEQ = new Id("2"); - public static final Id limit = new Id("3"); - - } - - @Override - public Id getId() { - return id; - } - - @Override - protected void describe(Criteria criteria) { - List descriptors = StatementUtils.createDescriptors(ThreadSession.class); - final Map map = StatementUtils.createDescriptorMap(descriptors); - - criteria.add(new WhereCriterion(CriteriaId.getVmId, map.get("vmId"), - TypeMapper.Criteria.Equal)); - criteria.add(new WhereCriterion(CriteriaId.timeStampGEQ, map.get("timeStamp"), - TypeMapper.Criteria.GreaterEqual)); - criteria.add(new WhereCriterion(CriteriaId.timeStampLEQ, map.get("timeStamp"), - TypeMapper.Criteria.LessEqual)); - - criteria.add(new SortCriterion(map.get("timeStamp"), TypeMapper.Sort.Descending)); - criteria.add(new LimitCriterion(CriteriaId.limit)); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/StateQueries.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/StateQueries.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,131 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.dao.impl.statement; + +import com.redhat.thermostat.storage.core.experimental.statement.FieldDescriptor; +import com.redhat.thermostat.storage.core.experimental.statement.Id; +import com.redhat.thermostat.storage.core.experimental.statement.LimitCriterion; +import com.redhat.thermostat.storage.core.experimental.statement.Query; +import com.redhat.thermostat.storage.core.experimental.statement.SortCriterion; +import com.redhat.thermostat.storage.core.experimental.statement.StatementUtils; +import com.redhat.thermostat.storage.core.experimental.statement.TypeMapper; +import com.redhat.thermostat.storage.core.experimental.statement.WhereCriterion; +import com.redhat.thermostat.thread.model.ThreadState; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * + */ +public class StateQueries { + + public static final Id getAscending = new Id("StateQueries::getRangeAscending"); + public static final Id getDescending = new Id("StateQueries::getRangeDescending"); + + public static class CriteriaId { + public static final Id vmId = new Id("vmId"); + public static final Id agentId = new Id("agentId"); + public static final Id timeStampGEQ = new Id("timeStampGEQ"); + public static final Id timeStampLEQ = new Id("timeStampLEQ"); + public static final Id sessionID = new Id("sessionID"); + public static final Id limit = new Id("limit"); + } + + private static class GetDescending extends Query { + @Override + protected void describe(Criteria criteria) { + List descriptors = StatementUtils.createDescriptors(ThreadState.class); + final Map map = StatementUtils.createDescriptorMap(descriptors); + + criteria.add(new WhereCriterion(CriteriaId.vmId, map.get("vmId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.agentId, map.get("agentId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.timeStampGEQ, map.get("timeStamp"), + TypeMapper.Criteria.GreaterEqual)); + criteria.add(new WhereCriterion(CriteriaId.timeStampLEQ, map.get("timeStamp"), + TypeMapper.Criteria.LessEqual)); + criteria.add(new WhereCriterion(CriteriaId.sessionID, map.get("session"), + TypeMapper.Criteria.Equal)); + criteria.add(new SortCriterion(map.get("timeStamp"), TypeMapper.Sort.Descending)); + criteria.add(new LimitCriterion(CriteriaId.limit)); + } + + @Override + public Id getId() { + return getDescending; + } + } + + private static class GetAscending extends Query { + @Override + protected void describe(Criteria criteria) { + List descriptors = StatementUtils.createDescriptors(ThreadState.class); + final Map map = StatementUtils.createDescriptorMap(descriptors); + + criteria.add(new WhereCriterion(CriteriaId.vmId, map.get("vmId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.agentId, map.get("agentId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.timeStampGEQ, map.get("timeStamp"), + TypeMapper.Criteria.GreaterEqual)); + criteria.add(new WhereCriterion(CriteriaId.timeStampLEQ, map.get("timeStamp"), + TypeMapper.Criteria.LessEqual)); + criteria.add(new WhereCriterion(CriteriaId.sessionID, map.get("session"), + TypeMapper.Criteria.Equal)); + criteria.add(new SortCriterion(map.get("timeStamp"), TypeMapper.Sort.Ascending)); + criteria.add(new LimitCriterion(CriteriaId.limit)); + } + + @Override + public Id getId() { + return getAscending; + } + } + + private static final List> queries = new ArrayList<>(); + static { + queries.add(new GetDescending()); + queries.add(new GetAscending()); + } + + public static List> asList() { + return Collections.unmodifiableList(queries); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQuery.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQuery.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQuery.java Thu Dec 11 11:44:42 2014 +0100 @@ -57,11 +57,12 @@ public static final Id id = new Id(SummaryQuery.class.getSimpleName()); public static class CriteriaId { - public static final Id getVmId = new Id("0"); - public static final Id timeStampGEQ = new Id("1"); - public static final Id timeStampLEQ = new Id("2"); - public static final Id sessionID = new Id("3"); - public static final Id limit = new Id("4"); + public static final Id vmId = new Id("vmId"); + public static final Id agentId = new Id("agentId"); + public static final Id timeStampGEQ = new Id("timeStampGEQ"); + public static final Id timeStampLEQ = new Id("timeStampLEQ"); + public static final Id sessionID = new Id("sessionID"); + public static final Id limit = new Id("limit"); } @@ -76,7 +77,9 @@ (ThreadSession.class); final Map map = StatementUtils.createDescriptorMap(descriptors); - criteria.add(new WhereCriterion(CriteriaId.getVmId, map.get("vmId"), + criteria.add(new WhereCriterion(CriteriaId.vmId, map.get("vmId"), + TypeMapper.Criteria.Equal)); + criteria.add(new WhereCriterion(CriteriaId.agentId, map.get("agentId"), TypeMapper.Criteria.Equal)); criteria.add(new WhereCriterion(CriteriaId.sessionID, map.get("session"), TypeMapper.Criteria.Equal)); diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadContentionSample.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadContentionSample.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadContentionSample.java Thu Dec 11 11:44:42 2014 +0100 @@ -38,12 +38,13 @@ import com.redhat.thermostat.storage.core.Entity; import com.redhat.thermostat.storage.core.Persist; +import com.redhat.thermostat.storage.model.BasePojo; import com.redhat.thermostat.storage.model.TimeStampedPojo; /** */ @Entity -public class ThreadContentionSample extends ThreadPojo implements TimeStampedPojo { +public class ThreadContentionSample extends BasePojo implements TimeStampedPojo { private long blockedCount; private long waitedCount; @@ -55,11 +56,11 @@ private long timestamp; public ThreadContentionSample() { - this(null, null); + this(null); } - public ThreadContentionSample(String wID, ThreadHeader header) { - super(wID, header); + public ThreadContentionSample(String wID) { + super(wID); } @Override diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadHeader.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadHeader.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.model; - -import java.util.Objects; -import java.util.UUID; - -import com.redhat.thermostat.storage.core.Entity; -import com.redhat.thermostat.storage.core.Persist; -import com.redhat.thermostat.storage.model.BasePojo; -import com.redhat.thermostat.storage.model.TimeStampedPojo; - -/** - * The common {@link Entity} for Thread related informations. - */ -@Entity -public class ThreadHeader extends BasePojo implements TimeStampedPojo { - - private long timestamp; - private String vmId; - private String name; - private long threadID; - - private String referenceID; - - public ThreadHeader() { - this(null); - } - - public ThreadHeader(String writerId) { - this(writerId, UUID.randomUUID().toString()); - } - - public ThreadHeader(String writerId, String referenceID) { - super(writerId); - this.referenceID = referenceID; - } - - @Persist - public String getReferenceID() { - return referenceID; - } - - @Persist - public void setReferenceID(String referenceID) { - this.referenceID = referenceID; - } - - @Persist - public void setThreadName(String threadName) { - this.name = threadName; - } - - @Persist - public void setThreadId(long threadID) { - this.threadID = threadID; - } - - @Persist - public String getThreadName() { - return name; - } - - @Persist - public long getThreadId() { - return threadID; - } - - @Persist - public void setVmId(String vmId) { - this.vmId = vmId; - } - - @Persist - public String getVmId() { - return vmId; - } - - @Override - @Persist - public long getTimeStamp() { - return timestamp; - } - - @Persist - public void setTimeStamp(long timestamp) { - this.timestamp = timestamp; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + (int) (threadID ^ (threadID >>> 32)); - result = prime * result + ((vmId == null) ? 0 : vmId.hashCode()); - - String agentID = getAgentId(); - result = prime * result + ((agentID == null) ? 0 : agentID.hashCode()); - - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ThreadHeader other = (ThreadHeader) obj; - if (name == null) { - if (other.name != null) { - return false; - } - } else if (!name.equals(other.name)) { - return false; - } - if (threadID != other.threadID) { - return false; - } - if (vmId == null) { - if (other.vmId != null) { - return false; - } - } else if (!vmId.equals(other.vmId)) { - return false; - } - - String agentID = getAgentId(); - String otherAgentID = getAgentId(); - return Objects.equals(agentID, otherAgentID); - } - - @Override - public String toString() { - return "ThreadHeader [name=" + name + ", threadID=" + threadID - + ", vmId=" + vmId + ", timestamp=" + timestamp + "]"; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadPojo.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadPojo.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.model; - -import com.redhat.thermostat.storage.core.Persist; -import com.redhat.thermostat.storage.model.BasePojo; - -/** - */ -public class ThreadPojo extends BasePojo { - - private ThreadHeader header; - private String referenceID; - private String sessionID; - - private String vmId; - - public ThreadPojo() { - this(null, null); - } - - public ThreadPojo(String wID, ThreadHeader header) { - super(wID); - setHeader(header); - } - - public void setHeader(ThreadHeader header) { - this.header = header; - if (header != null) { - referenceID = header.getReferenceID(); - } - } - - @Persist - public void setVmId(String vmId) { - this.vmId = vmId; - } - - @Persist - public String getVmId() { - return vmId; - } - - public ThreadHeader getHeader() { - return header; - } - - @Persist - public void setReferenceID(String referenceID) { - this.referenceID = referenceID; - } - - @Persist - public String getReferenceID() { - return referenceID; - } - - @Persist - public void setSessionID(String sessionID) { - this.sessionID = sessionID; - } - - public String getSessionID() { - return sessionID; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - - ThreadPojo that = (ThreadPojo) o; - - if (header != null ? !header.equals(that.header) : that.header != null) - return false; - if (sessionID != null ? !sessionID.equals(that.sessionID) : that.sessionID != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = 31 * result + (header != null ? header.hashCode() : 0); - result = 31 * result + (sessionID != null ? sessionID.hashCode() : 0); - return result; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadState.java --- a/thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadState.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/model/ThreadState.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,53 +36,71 @@ package com.redhat.thermostat.thread.model; -import com.redhat.thermostat.common.model.Range; import com.redhat.thermostat.storage.core.Entity; import com.redhat.thermostat.storage.core.Persist; +import com.redhat.thermostat.storage.core.experimental.statement.Category; +import com.redhat.thermostat.storage.core.experimental.statement.Indexed; +import com.redhat.thermostat.storage.model.BasePojo; +import com.redhat.thermostat.storage.model.TimeStampedPojo; +import com.redhat.thermostat.thread.dao.impl.ThreadDaoCategories; /** * Represents a single delta variation of a Thread state. */ +@Category(ThreadDaoCategories.Categories.STATE) @Entity -public class ThreadState extends ThreadPojo { +public class ThreadState extends BasePojo implements TimeStampedPojo { - private long probeStartTime; - private long probeEndTime; - + private long timeStamp; + private String vmId; + private String name; private String state; + private String session; + private long id; + private boolean suspended; + private boolean inNative; public ThreadState() { - this(null, null); + this(null); } - public ThreadState(String wID, ThreadHeader header) { - super(wID, header); + public ThreadState(String writerId) { + super(writerId); + } + + @Persist + public String getName() { + return name; } @Persist - public void setProbeEndTime(long probeEndTime) { - this.probeEndTime = probeEndTime; + public void setName(String name) { + this.name = name; + } + + @Indexed + @Persist + public String getVmId() { + return vmId; + } + + @Indexed + @Persist + public void setVmId(String vmId) { + this.vmId = vmId; } @Persist - public void setProbeStartTime(long probeStartTime) { - this.probeStartTime = probeStartTime; - } - - @Persist - public long getProbeEndTime() { - return probeEndTime; + @Override + public long getTimeStamp() { + return timeStamp; } - + @Persist - public long getProbeStartTime() { - return probeStartTime; + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; } - - public Range getRange() { - return new Range(probeStartTime, probeEndTime); - } - + @Persist public String getState() { return state; @@ -95,27 +113,69 @@ @Override public String toString() { - ThreadHeader header = getHeader(); - String name = null; - if (header != null) { - name = header.getThreadName(); - } - return "ThreadState: [name: " + name + "state: " + getState() + ", range: " + getRange() + "]"; + return "ThreadState: [name: " + name + " state: " + getState() + + ", timestamp: " + timeStamp + "]"; + } + + @Persist + public void setSession(String session) { + this.session = session; + } + + @Persist + public String getSession() { + return session; + } + + @Persist + public void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + @Persist + public void setId(long id) { + this.id = id; + } + + @Persist + public long getId() { + return id; + } + + @Persist + public boolean isSuspended() { + return suspended; + } + + @Persist + public void setInNative(boolean inNative) { + this.inNative = inNative; + } + + @Persist + public boolean isInNative() { + return inNative; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; ThreadState that = (ThreadState) o; - if (probeEndTime != that.probeEndTime) return false; - if (probeStartTime != that.probeStartTime) return false; - - if (!super.equals(o)) return false; - - if (state != that.state) return false; + if (id != that.id) return false; + if (inNative != that.inNative) return false; + if (suspended != that.suspended) return false; + if (name != null ? !name.equals(that.name) : that.name != null) + return false; + if (session != null ? !session.equals(that.session) : that.session != null) + return false; + if (state != null ? !state.equals(that.state) : that.state != null) + return false; + if (vmId != null ? !vmId.equals(that.vmId) : that.vmId != null) + return false; return true; } @@ -123,9 +183,13 @@ @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + (int) (probeStartTime ^ (probeStartTime >>> 32)); - result = 31 * result + (int) (probeEndTime ^ (probeEndTime >>> 32)); + result = 31 * result + (vmId != null ? vmId.hashCode() : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (state != null ? state.hashCode() : 0); + result = 31 * result + (session != null ? session.hashCode() : 0); + result = 31 * result + (int) (id ^ (id >>> 32)); + result = 31 * result + (suspended ? 1 : 0); + result = 31 * result + (inNative ? 1 : 0); return result; } } diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistrationTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistrationTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistrationTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -64,8 +64,6 @@ assertFalse("null descriptor not allowed", categories.contains(null)); assertTrue(categories.contains(ThreadDao.DEADLOCK_INFO.getName())); - assertTrue(categories.contains(ThreadDao.THREAD_HEADER.getName())); - assertTrue(categories.contains(ThreadDao.THREAD_STATE.getName())); assertTrue(categories.contains(ThreadDao.THREAD_HARVESTING_STATUS.getName())); assertTrue(categories.contains(ThreadDao.THREAD_CONTENTION_SAMPLE.getName())); diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImplTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -36,7 +36,6 @@ package com.redhat.thermostat.thread.dao.impl; -import com.redhat.thermostat.common.model.Range; import com.redhat.thermostat.storage.core.Cursor; import com.redhat.thermostat.storage.core.DescriptorParsingException; import com.redhat.thermostat.storage.core.HostRef; @@ -48,22 +47,17 @@ import com.redhat.thermostat.storage.model.Pojo; import com.redhat.thermostat.thread.dao.ThreadDao; import com.redhat.thermostat.thread.model.ThreadHarvestingStatus; -import com.redhat.thermostat.thread.model.ThreadHeader; -import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.VmDeadLockData; -import java.util.List; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -92,18 +86,6 @@ String expectedQueryLatestHarvestingStatus = "QUERY vm-thread-harvesting WHERE 'agentId' = ?s AND 'vmId' = ?s SORT 'timeStamp' DSC LIMIT 1"; assertEquals(expectedQueryLatestHarvestingStatus, ThreadDaoImpl.QUERY_LATEST_HARVESTING_STATUS); - String expectedQueryThreadHeader = "QUERY vm-thread-header WHERE 'agentId' = ?s AND 'vmId' = ?s AND 'threadName' = ?s AND 'threadId' = ?l LIMIT 1"; - assertEquals(expectedQueryThreadHeader, ThreadDaoImpl.QUERY_THREAD_HEADER); - - String expectedQueryAllThreadHeaders = "QUERY vm-thread-header WHERE 'agentId' = ?s AND 'vmId' = ?s SORT 'timeStamp' DSC"; - assertEquals(expectedQueryAllThreadHeaders, ThreadDaoImpl.QUERY_ALL_THREAD_HEADERS); - - String expectedQueryLatestThreadStateForThread = "QUERY vm-thread-state WHERE 'agentId' = ?s AND 'referenceID' = ?s SORT 'probeEndTime' DSC LIMIT 1"; - assertEquals(expectedQueryLatestThreadStateForThread, ThreadDaoImpl.QUERY_LATEST_THREAD_STATE_FOR_THREAD); - - String expectedQueryOldestThreadState = "QUERY vm-thread-state WHERE 'agentId' = ?s AND 'vmId' = ?s SORT 'probeStartTime' ASC LIMIT 1"; - assertEquals(expectedQueryOldestThreadState, ThreadDaoImpl.QUERY_OLDEST_THREAD_STATE); - String expectedQueryThreadLatestDeadlockInfo = "QUERY vm-deadlock-data WHERE 'agentId' = ?s AND 'vmId' = ?s SORT 'timeStamp' DSC LIMIT 1"; assertEquals(expectedQueryThreadLatestDeadlockInfo, ThreadDaoImpl.QUERY_LATEST_DEADLOCK_INFO); @@ -119,25 +101,6 @@ "'threadId' = ?l , " + "'timeStamp' = ?l , " + "'referenceID' = ?s"; - assertEquals(addThreadInfo, ThreadDaoImpl.ADD_THREAD_HEADER); - String addDeadlockData = "ADD vm-deadlock-data SET 'agentId' = ?s , " + - "'vmId' = ?s , " + - "'timeStamp' = ?l , " + - "'deadLockDescription' = ?s"; - assertEquals(addDeadlockData, ThreadDaoImpl.DESC_ADD_THREAD_DEADLOCK_DATA); - - String addThreadState = "ADD vm-thread-state SET 'agentId' = ?s , " + - "'vmId' = ?s , 'state' = ?s , " + - "'probeStartTime' = ?l , 'probeEndTime' = ?l , " + - "'referenceID' = ?s"; - assertEquals(addThreadState, ThreadDaoImpl.ADD_THREAD_STATE); - - String getThreadStatesForVM = "QUERY vm-thread-state WHERE " + - "'referenceID' = ?s AND " + - "'probeEndTime' >= ?l AND " + - "'probeStartTime' <= ?l SORT " + - "'probeStartTime' ASC"; - assertEquals(getThreadStatesForVM, ThreadDaoImpl.QUERY_THREAD_STATE_PER_THREAD); String addContentionSample = "ADD thread-contention-sample SET " + "'agentId' = ?s , 'vmId' = ?s , 'blockedCount' = ?l , " + @@ -152,7 +115,6 @@ String getFirstThreadState = "QUERY vm-thread-state WHERE " + "'agentId' = ?s AND 'referenceID' = ?s SORT 'probeStartTime' " + "ASC LIMIT 1"; - assertEquals(getFirstThreadState, ThreadDaoImpl.QUERY_FIRST_THREAD_STATE_FOR_THREAD); } @Test @@ -296,273 +258,5 @@ verifyNoMoreInteractions(add); } - @Test - public void testSaveThread() throws DescriptorParsingException, StatementExecutionException { - final String THREAD_NAME = "name of a thread"; - final long THREAD_ID = 0xcafebabe; - final long TIMESTAMP = 0xdeadbeef; - final String REF_ID = "42"; - - Storage storage = mock(Storage.class); - PreparedStatement add = mock(PreparedStatement.class); - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(add); - - // not using mocks because ThreadHeader is really a data holder (no logic) - ThreadHeader header = new ThreadHeader(); - header.setAgentId(AGENT_ID); - header.setVmId(VM_ID); - header.setThreadName(THREAD_NAME); - header.setThreadId(THREAD_ID); - header.setTimeStamp(TIMESTAMP); - header.setReferenceID(REF_ID); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - dao.saveThread(header); - - verify(add).setString(0, AGENT_ID); - verify(add).setString(1, VM_ID); - verify(add).setString(2, THREAD_NAME); - verify(add).setLong(3, THREAD_ID); - verify(add).setLong(4, TIMESTAMP); - verify(add).setString(5, REF_ID); - - verify(add).execute(); - - verifyNoMoreInteractions(add); - } - - @Test - public void testGetThreadNoData() throws DescriptorParsingException, StatementExecutionException { - final String THREAD_NAME = "name of a thread"; - final long THREAD_ID = 0xcafebabe; - final long TIMESTAMP = 0xdeadbeef; - final String REF_ID = "42"; - - Cursor cursor = mock(Cursor.class); - when(cursor.hasNext()).thenReturn(false); - - Storage storage = mock(Storage.class); - PreparedStatement get = mock(PreparedStatement.class); - when(get.executeQuery()).thenReturn(cursor); - - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(get); - - ThreadHeader header = new ThreadHeader(); - header.setAgentId(AGENT_ID); - header.setVmId(VM_ID); - header.setThreadName(THREAD_NAME); - header.setThreadId(THREAD_ID); - header.setTimeStamp(TIMESTAMP); - header.setReferenceID(REF_ID); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - ThreadHeader result = dao.getThread(header); - assertNull(result); - - verify(get).setString(0, AGENT_ID); - verify(get).setString(1, VM_ID); - verify(get).setString(2, THREAD_NAME); - verify(get).setLong(3, THREAD_ID); - - verify(get).executeQuery(); - - verifyNoMoreInteractions(get); - } - - @Test - public void testGetThreadWithData() throws DescriptorParsingException, StatementExecutionException { - final String THREAD_NAME = "name of a thread"; - final long THREAD_ID = 0xcafebabe; - final long TIMESTAMP = 0xdeadbeef; - final String REF_ID = "42"; - - ThreadHeader header = new ThreadHeader(); - header.setAgentId(AGENT_ID); - header.setVmId(VM_ID); - header.setThreadName(THREAD_NAME); - header.setThreadId(THREAD_ID); - header.setTimeStamp(TIMESTAMP); - header.setReferenceID(REF_ID); - - Cursor cursor = mock(Cursor.class); - when(cursor.hasNext()).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(header).thenReturn(null); - - Storage storage = mock(Storage.class); - PreparedStatement get = mock(PreparedStatement.class); - when(get.executeQuery()).thenReturn(cursor); - - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(get); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - ThreadHeader result = dao.getThread(header); - assertNotNull(result); - assertEquals(header, result); - - verify(get).setString(0, AGENT_ID); - verify(get).setString(1, VM_ID); - verify(get).setString(2, THREAD_NAME); - verify(get).setLong(3, THREAD_ID); - - verify(get).executeQuery(); - - verifyNoMoreInteractions(get); - } - - @Test - public void testGetThreads() throws DescriptorParsingException, StatementExecutionException { - - ThreadHeader header0 = mock(ThreadHeader.class); - ThreadHeader header1 = mock(ThreadHeader.class); - ThreadHeader header2 = mock(ThreadHeader.class); - - Cursor cursor = mock(Cursor.class); - when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(header0).thenReturn(header1).thenReturn(header2).thenReturn(null); - - Storage storage = mock(Storage.class); - PreparedStatement get = mock(PreparedStatement.class); - when(get.executeQuery()).thenReturn(cursor); - - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(get); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - List result = dao.getThreads(vmRef); - assertNotNull(result); - assertEquals(result.size(), 3); - assertEquals(result.get(0), header0); - assertEquals(result.get(1), header1); - assertEquals(result.get(2), header2); - - verify(get).setString(0, AGENT_ID); - verify(get).setString(1, VM_ID); - - verify(get).executeQuery(); - - verifyNoMoreInteractions(get); - } - - @Test - public void testAddThreadState() throws Exception { - final String VM_ID = "vm42"; - final String AGENT_ID = "agent42"; - final String REF_ID = "42"; - final String STATE = "runnable"; - final long START_TIME = 1l; - final long STOP_TIME = 1l; - - ThreadHeader header = new ThreadHeader(AGENT_ID); - header.setVmId(VM_ID); - header.setReferenceID(REF_ID); - - ThreadState template = mock(ThreadState.class); - when(template.getHeader()).thenReturn(header); - when(template.getState()).thenReturn(STATE); - when(template.getProbeStartTime()).thenReturn(START_TIME); - when(template.getProbeEndTime()).thenReturn(STOP_TIME); - - Storage storage = mock(Storage.class); - PreparedStatement set = mock(PreparedStatement.class); - - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(set); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - dao.addThreadState(template); - - verify(set).setString(0, AGENT_ID); - verify(set).setString(1, VM_ID); - verify(set).setString(2, STATE); - verify(set).setLong(3, START_TIME); - verify(set).setLong(4, STOP_TIME); - verify(set).setString(5, REF_ID); - - verify(set).execute(); - } - - @Test - public void testUpdateThreadState() throws Exception { - final String REF_ID = "42"; - final long START_TIME = 0l; - final long STOP_TIME = 1l; - - ThreadHeader header = new ThreadHeader(AGENT_ID); - header.setVmId(VM_ID); - header.setReferenceID(REF_ID); - - ThreadState template = mock(ThreadState.class); - when(template.getHeader()).thenReturn(header); - when(template.getProbeStartTime()).thenReturn(START_TIME); - when(template.getProbeEndTime()).thenReturn(STOP_TIME); - - Storage storage = mock(Storage.class); - PreparedStatement update = mock(PreparedStatement.class); - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(update); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - dao.updateThreadState(template); - - verify(update).setLong(0, STOP_TIME); - verify(update).setString(1, REF_ID); - verify(update).setLong(2, START_TIME); - - verify(update).execute(); - } - - @Test - public void testGetThreadStateTotalTimeRange() throws Exception { - - Range oldest = new Range(0l, 1l); - ThreadState oldestData = mock(ThreadState.class); - when(oldestData.getRange()).thenReturn(oldest); - - Range latest = new Range(2l, 3l); - ThreadState latestData = mock(ThreadState.class); - when(latestData.getRange()).thenReturn(latest); - - Cursor cursor = mock(Cursor.class); - when(cursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false); - when(cursor.next()).thenReturn(oldestData).thenReturn(latestData); - - Storage storage = mock(Storage.class); - PreparedStatement get = mock(PreparedStatement.class); - when(get.executeQuery()).thenReturn(cursor); - - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(get); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - Range result = dao.getThreadStateTotalTimeRange(vmRef); - assertNotNull(result); - - verify(get, times(2)).setString(0, AGENT_ID); - verify(get, times(2)).setString(1, VM_ID); - - verify(get, times(2)).executeQuery(); - - verifyNoMoreInteractions(get); - } - - @Test - public void testGetThreadStateTotalTimeRangeNoData() throws Exception { - - Cursor cursor = mock(Cursor.class); - when(cursor.hasNext()).thenReturn(false); - - Storage storage = mock(Storage.class); - PreparedStatement get = mock(PreparedStatement.class); - when(get.executeQuery()).thenReturn(cursor); - - when(storage.prepareStatement(any(StatementDescriptor.class))).thenReturn(get); - - ThreadDaoImpl dao = new ThreadDaoImpl(storage); - Range result = dao.getThreadStateTotalTimeRange(vmRef); - assertNull(result); - - verify(get).setString(0, AGENT_ID); - verify(get).setString(1, VM_ID); - - verify(get).executeQuery(); - - verifyNoMoreInteractions(get); - } } diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueriesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueriesTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2014 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.dao.impl.statement; + +import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapter; +import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapterBuilder; +import com.redhat.thermostat.thread.model.ThreadSession; +import java.util.Set; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SessionQueriesTest { + + @Test + public void testDescribe() throws Exception { + BeanAdapter session = + new BeanAdapterBuilder<>(ThreadSession.class, + SessionQueries.asList()).build(); + Set statements = session.describeStatements(); + assertEquals(3, statements.size()); + + String expected = "QUERY vm-thread-session WHERE 'vmId' = ?s AND 'agentId' = ?s AND 'timeStamp' >= ?l AND 'timeStamp' <= ?l SORT 'timeStamp' ASC LIMIT ?i"; + assertTrue(statements.contains(expected)); + + expected = "QUERY vm-thread-session WHERE 'vmId' = ?s AND 'agentId' = ?s AND 'timeStamp' >= ?l AND 'timeStamp' <= ?l SORT 'timeStamp' DSC LIMIT ?i"; + assertTrue(statements.contains(expected)); + } +} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueryTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueryTest.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.dao.impl.statement; - -import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapter; -import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapterBuilder; -import com.redhat.thermostat.thread.model.ThreadSession; -import java.util.Set; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class SessionQueryTest { - - @Test - public void testDescribe() throws Exception { - BeanAdapter session = - new BeanAdapterBuilder<>(ThreadSession.class, - new SessionQuery()).build(); - Set statements = session.describeStatements(); - assertEquals(2, statements.size()); - - String expected = "QUERY vm-thread-session WHERE 'vmId' = ?s AND 'timeStamp' >= ?l AND 'timeStamp' <= ?l SORT 'timeStamp' DSC LIMIT ?i"; - assertTrue(statements.contains(expected)); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQueryTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQueryTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQueryTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -54,7 +54,7 @@ Set statements = session.describeStatements(); assertEquals(2, statements.size()); - String expected = "QUERY vm-thread-summary WHERE 'vmId' = ?s AND 'session' = ?s AND 'timeStamp' >= ?l AND 'timeStamp' <= ?l SORT 'timeStamp' DSC LIMIT ?i"; + String expected = "QUERY vm-thread-summary WHERE 'vmId' = ?s AND 'agentId' = ?s AND 'session' = ?s AND 'timeStamp' >= ?l AND 'timeStamp' <= ?l SORT 'timeStamp' DSC LIMIT ?i"; assertTrue(statements.contains(expected)); } } diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadHeaderTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadHeaderTest.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.model; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -public class ThreadHeaderTest { - - @Test - public void testEqualsAndHashCode() throws Exception { - // same thread, will they be equals? - ThreadHeader header1 = new ThreadHeader("1234"); - header1.setReferenceID("vm42"); - header1.setThreadName("main"); - header1.setThreadId(1); - - ThreadHeader header2 = new ThreadHeader("1234"); - header2.setReferenceID("vm42"); - header2.setThreadName("main"); - header2.setThreadId(1); - - assertEquals(header1, header2); - assertEquals(header1.hashCode(), header2.hashCode()); - } - - @Test - public void testNotEqualsAndHashCode() throws Exception { - // same thread, will they be equals? - ThreadHeader header1 = new ThreadHeader("1234"); - header1.setReferenceID("vm42"); - header1.setThreadName("main"); - header1.setThreadId(2); - - ThreadHeader header2 = new ThreadHeader("1234"); - header2.setReferenceID("vm42"); - header2.setThreadName("main"); - header2.setThreadId(1); - - assertFalse(header1.equals(header2)); - assertFalse(header1.hashCode() == header2.hashCode()); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadModelPojosTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadModelPojosTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadModelPojosTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -47,7 +47,6 @@ private static final Class[] CLASSES_LIST = new Class[] { ThreadHarvestingStatus.class, ThreadState.class, - ThreadHeader.class, ThreadSummary.class, ThreadContentionSample.class, VmDeadLockData.class, diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadPojoTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadPojoTest.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.model; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -public class ThreadPojoTest { - - @Test - public void testEqualsAndHashCode() throws Exception { - - ThreadHeader header1 = new ThreadHeader("1234"); - header1.setReferenceID("vm42"); - header1.setThreadName("main"); - header1.setThreadId(1); - - ThreadPojo pojo1 = new ThreadPojo("1234", header1); - ThreadPojo pojo2 = new ThreadPojo("1234", header1); - - assertEquals(pojo1, pojo2); - assertEquals(pojo1.hashCode(), pojo2.hashCode()); - - ThreadHeader header2 = new ThreadHeader("12344"); - pojo2.setHeader(header2); - - assertFalse(pojo1.equals(pojo2)); - assertFalse(pojo1.hashCode() == pojo2.hashCode()); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadStateTest.java --- a/thread/collector/src/test/java/com/redhat/thermostat/thread/model/ThreadStateTest.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.model; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -public class ThreadStateTest { - - @Test - public void testEqualsAndHashCode() throws Exception { - - ThreadHeader header1 = new ThreadHeader("1234"); - header1.setReferenceID("vm42"); - header1.setThreadName("main"); - header1.setThreadId(1); - - ThreadState state1 = new ThreadState("1234", header1); - state1.setProbeStartTime(0l); - state1.setProbeEndTime(1l); - state1.setState("NEW"); - - ThreadState state2 = new ThreadState("1234", header1); - state2.setProbeStartTime(0l); - state2.setProbeEndTime(1l); - state2.setState("NEW"); - - assertEquals(state1, state2); - assertEquals(state1.hashCode(), state2.hashCode()); - - ThreadHeader header2 = new ThreadHeader("12344"); - state2.setHeader(header2); - - assertFalse(state1.equals(state2)); - assertFalse(state1.hashCode() == state2.hashCode()); - - state2.setHeader(header1); - state2.setProbeStartTime(1l); - state2.setProbeEndTime(1l); - state2.setState("NEW"); - - assertFalse(state1.equals(state2)); - assertFalse(state1.hashCode() == state2.hashCode()); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/HarvesterHelper.java --- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/HarvesterHelper.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/HarvesterHelper.java Thu Dec 11 11:44:42 2014 +0100 @@ -39,8 +39,6 @@ import com.redhat.thermostat.common.Clock; import com.redhat.thermostat.storage.core.WriterID; import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.model.ThreadContentionSample; -import com.redhat.thermostat.thread.model.ThreadHeader; import com.redhat.thermostat.thread.model.ThreadSession; import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; @@ -55,24 +53,21 @@ private String vmId; private ThreadSummaryHelper summaryHelper; - private ThreadHeaderHelper headerHelper; private ThreadStateHelper stateHelper; private ThreadContentionHelper contentionHelper; private ThreadSessionHelper sessionHelper; HarvesterHelper(ThreadDao threadDao, Clock clock, String vmId, WriterID writerId) { - this(threadDao, clock, vmId, + this(clock, vmId, new ThreadSummaryHelper(threadDao, writerId, vmId), - new ThreadHeaderHelper(threadDao, writerId, vmId), new ThreadStateHelper(threadDao, writerId, vmId), new ThreadContentionHelper(threadDao, writerId, vmId), new ThreadSessionHelper(threadDao, writerId, vmId, clock)); } - HarvesterHelper(ThreadDao threadDao, Clock clock, String vmId, + HarvesterHelper(Clock clock, String vmId, ThreadSummaryHelper summaryHelper, - ThreadHeaderHelper headerHelper, ThreadStateHelper stateHelper, ThreadContentionHelper contentionHelper, ThreadSessionHelper sessionHelper) @@ -81,7 +76,6 @@ this.clock = clock; this.summaryHelper = summaryHelper; - this.headerHelper = headerHelper; this.stateHelper = stateHelper; this.contentionHelper = contentionHelper; @@ -116,21 +110,19 @@ ThreadInfo beanInfo = threadInfos[i]; - // common header - ThreadHeader header = headerHelper.createThreadHeader(beanInfo, timestamp); - header = headerHelper.checkAndSaveThreadHeader(header); - // state information - ThreadState state = stateHelper.createThreadState(header, beanInfo, - timestamp); + ThreadState state = + stateHelper.createThreadState(beanInfo, + session.getSessionID(), + timestamp); stateHelper.saveThreadState(state); - - // contention information - ThreadContentionSample contentionSample = - contentionHelper.createThreadContentionSample(header, - beanInfo, - timestamp); - contentionHelper.saveContentionSample(contentionSample); +// +// // contention information +// ThreadContentionSample contentionSample = +// contentionHelper.createThreadContentionSample(header, +// beanInfo, +// timestamp); +// contentionHelper.saveContentionSample(contentionSample); } } diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadContentionHelper.java --- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadContentionHelper.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadContentionHelper.java Thu Dec 11 11:44:42 2014 +0100 @@ -38,9 +38,6 @@ import com.redhat.thermostat.storage.core.WriterID; import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.model.ThreadContentionSample; -import com.redhat.thermostat.thread.model.ThreadHeader; -import java.lang.management.ThreadInfo; /** */ @@ -56,23 +53,23 @@ this.vmId = vmId; } - public ThreadContentionSample createThreadContentionSample(ThreadHeader header, - ThreadInfo beanInfo, - long timestamp) - { - String wId = writerId.getWriterID(); - - ThreadContentionSample sample = new ThreadContentionSample(wId, header); - sample.setTimeStamp(timestamp); - sample.setBlockedCount(beanInfo.getBlockedCount()); - sample.setBlockedTime(beanInfo.getBlockedTime()); - sample.setWaitedCount(beanInfo.getWaitedCount()); - sample.setWaitedTime(beanInfo.getWaitedTime()); - - return sample; - } - - public void saveContentionSample(ThreadContentionSample contentionSample) { - threadDao.saveContentionSample(contentionSample); - } +// public ThreadContentionSample createThreadContentionSample(ThreadHeader header, +// ThreadInfo beanInfo, +// long timestamp) +// { +// String wId = writerId.getWriterID(); +// +// ThreadContentionSample sample = new ThreadContentionSample(wId); +// sample.setTimeStamp(timestamp); +// sample.setBlockedCount(beanInfo.getBlockedCount()); +// sample.setBlockedTime(beanInfo.getBlockedTime()); +// sample.setWaitedCount(beanInfo.getWaitedCount()); +// sample.setWaitedTime(beanInfo.getWaitedTime()); +// +// return sample; +// } +// +// public void saveContentionSample(ThreadContentionSample contentionSample) { +// threadDao.saveContentionSample(contentionSample); +// } } diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHeaderHelper.java --- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHeaderHelper.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.harvester; - -import java.lang.management.ThreadInfo; - -import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.model.ThreadHeader; -import com.redhat.thermostat.thread.model.ThreadState; - -/** - */ -class ThreadHeaderHelper { - - private ThreadDao threadDao; - private String vmId; - private WriterID writerId; - - public ThreadHeaderHelper(ThreadDao threadDao, WriterID writerId, String vmId) - { - this.threadDao = threadDao; - this.vmId = vmId; - this.writerId = writerId; - } - - public ThreadHeader createThreadHeader(ThreadInfo beanInfo, long timestamp) - { - String wId = writerId.getWriterID(); - - ThreadHeader header = new ThreadHeader(wId); - header.setThreadName(beanInfo.getThreadName()); - header.setThreadId(beanInfo.getThreadId()); - header.setTimeStamp(timestamp); - header.setVmId(vmId); - - return header; - } - - /** - * Checks if the template is in the database. If the template is not in - * the database, it is added and the same object is returned, otherwise - * the database object is returned with the correct referenceID field. - * The input template header itself is never updated. - */ - public ThreadHeader checkAndSaveThreadHeader(ThreadHeader template) { - ThreadHeader inStorage = threadDao.getThread(template); - if (inStorage == null || !template.equals(inStorage)) { - threadDao.saveThread(template); - inStorage = template; - } - return inStorage; - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadStateHelper.java --- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadStateHelper.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadStateHelper.java Thu Dec 11 11:44:42 2014 +0100 @@ -38,50 +38,43 @@ import com.redhat.thermostat.storage.core.WriterID; import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.model.ThreadHeader; +import com.redhat.thermostat.thread.model.SessionID; import com.redhat.thermostat.thread.model.ThreadState; - import java.lang.management.ThreadInfo; public class ThreadStateHelper { private ThreadDao threadDao; - private WriterID writerId; - private String vmId; + private final WriterID writerId; + private final String vmId; - public ThreadStateHelper(ThreadDao threadDao, WriterID writerId, String vmId) { + public ThreadStateHelper(ThreadDao threadDao, + WriterID writerId, String vmId) + { + this.threadDao = threadDao; this.writerId = writerId; this.vmId = vmId; - this.threadDao = threadDao; } - public ThreadState createThreadState(ThreadHeader header, ThreadInfo beanInfo, + public ThreadState createThreadState(ThreadInfo beanInfo, + SessionID sessionID, long timestamp) { - String wId = writerId.getWriterID(); + ThreadState state = new ThreadState(writerId.getWriterID()); - ThreadState state = new ThreadState(wId, header); state.setState(beanInfo.getThreadState().name()); - state.setProbeStartTime(timestamp); - state.setProbeEndTime(timestamp); + state.setTimeStamp(timestamp); + state.setSession(sessionID.get()); + state.setVmId(vmId); + state.setName(beanInfo.getThreadName()); + state.setId(beanInfo.getThreadId()); + state.setSuspended(beanInfo.isSuspended()); + state.setInNative(beanInfo.isInNative()); return state; } - public ThreadState saveThreadState(ThreadState thread) { - - ThreadHeader header = thread.getHeader(); - ThreadState lastState = threadDao.getLastThreadState(header); - if (lastState == null || !lastState.getState().equals(thread.getState())) - { - threadDao.addThreadState(thread); - lastState = thread; - - } else { - // update - lastState.setProbeEndTime(thread.getProbeEndTime()); - threadDao.updateThreadState(lastState); - } - return lastState; + public void saveThreadState(ThreadState thread) { + threadDao.addThreadState(thread); } } diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelper.java --- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelper.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadSummaryHelper.java Thu Dec 11 11:44:42 2014 +0100 @@ -49,15 +49,15 @@ private String vmId; private WriterID writerId; private ThreadDao threadDao; - ThreadSummaryHelper(ThreadDao threadDao, WriterID writerId, String vmId) { this.vmId = vmId; this.writerId = writerId; this.threadDao = threadDao; } - ThreadSummary createThreadSummary(ThreadMXBean collectorBean, long timestamp, ThreadSession session) { - + ThreadSummary createThreadSummary(ThreadMXBean collectorBean, + long timestamp, ThreadSession session) + { String wId = writerId.getWriterID(); ThreadSummary summary = new ThreadSummary(wId); diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterHelperTest.java --- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterHelperTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/HarvesterHelperTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -38,7 +38,6 @@ import com.redhat.thermostat.common.Clock; import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.model.ThreadHeader; import com.redhat.thermostat.thread.model.ThreadSession; import com.redhat.thermostat.thread.model.ThreadState; import com.redhat.thermostat.thread.model.ThreadSummary; @@ -50,7 +49,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -66,7 +64,6 @@ private String vmId; private ThreadSummaryHelper summaryHelper; - private ThreadHeaderHelper headerHelper; private ThreadStateHelper stateHelper; private ThreadContentionHelper contentionHelper; private ThreadSessionHelper threadSessionHelper; @@ -76,7 +73,6 @@ @Before public void setUp() { summaryHelper = mock(ThreadSummaryHelper.class); - headerHelper = mock(ThreadHeaderHelper.class); stateHelper = mock(ThreadStateHelper.class); contentionHelper = mock(ThreadContentionHelper.class); @@ -104,9 +100,8 @@ session)). thenReturn(summary); - HarvesterHelper harvester = new HarvesterHelper(threadDao, clock, vmId, + HarvesterHelper harvester = new HarvesterHelper(clock, vmId, summaryHelper, - headerHelper, stateHelper, contentionHelper, threadSessionHelper); @@ -125,9 +120,8 @@ long[] ids = new long[] {0l, 1l, 2l}; when(collectorBean.getAllThreadIds()).thenReturn(ids); - HarvesterHelper harvester = new HarvesterHelper(threadDao, clock, vmId, + HarvesterHelper harvester = new HarvesterHelper(clock, vmId, summaryHelper, - headerHelper, stateHelper, contentionHelper, threadSessionHelper); @@ -151,35 +145,21 @@ when(collectorBean.getThreadInfo(any(long[].class), eq(true), eq(true))).thenReturn(infos); - ThreadHeader header1 = mock(ThreadHeader.class); - ThreadHeader header2 = mock(ThreadHeader.class); - - when(headerHelper.createThreadHeader(infos[0], DEFAULT_TIMESTAMP)).thenReturn(header1); - when(headerHelper.createThreadHeader(infos[1], DEFAULT_TIMESTAMP)).thenReturn(header2); - when(headerHelper.createThreadHeader(infos[2], DEFAULT_TIMESTAMP)).thenReturn(header1); - - when(headerHelper.checkAndSaveThreadHeader(header1)).thenReturn(header1); - when(headerHelper.checkAndSaveThreadHeader(header2)).thenReturn(header2); - ThreadState state1 = mock(ThreadState.class); ThreadState state2 = mock(ThreadState.class); ThreadState state3 = mock(ThreadState.class); - when(stateHelper.createThreadState(header1, infos[0], DEFAULT_TIMESTAMP)).thenReturn(state1); - when(stateHelper.createThreadState(header2, infos[1], DEFAULT_TIMESTAMP)).thenReturn(state2); - when(stateHelper.createThreadState(header1, infos[2], DEFAULT_TIMESTAMP)).thenReturn(state3); + when(stateHelper.createThreadState(eq(infos[0]),eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state1); + when(stateHelper.createThreadState(eq(infos[1]), eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state2); + when(stateHelper.createThreadState(eq(infos[2]), eq(session.getSessionID()), eq(DEFAULT_TIMESTAMP))).thenReturn(state3); - HarvesterHelper harvester = new HarvesterHelper(threadDao, clock, vmId, + HarvesterHelper harvester = new HarvesterHelper(clock, vmId, summaryHelper, - headerHelper, stateHelper, contentionHelper, threadSessionHelper); harvester.collectAndSaveThreadData(session, collectorBean); - verify(headerHelper, times(2)).checkAndSaveThreadHeader(header1); - verify(headerHelper).checkAndSaveThreadHeader(header2); - verify(stateHelper).saveThreadState(state1); verify(stateHelper).saveThreadState(state2); verify(stateHelper).saveThreadState(state3); diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHeaderHelperTest.java --- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHeaderHelperTest.java Thu Dec 11 01:35:29 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * Copyright 2012-2014 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.thread.harvester; - -import com.redhat.thermostat.storage.core.WriterID; -import com.redhat.thermostat.thread.dao.ThreadDao; -import com.redhat.thermostat.thread.model.ThreadHeader; -import org.junit.Before; -import org.junit.Test; - -import java.lang.management.ThreadInfo; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.Mockito.times; - -/* - */ -public class ThreadHeaderHelperTest { - - private static String DEFAULT_W_ID = "0xcafe"; - private static String DEFAULT_THREAD_NAME = "Thread42"; - private static long DEFAULT_THREAD_ID = 42; - - private String vmId; - private WriterID writerId; - private ThreadDao threadDao; - - private ThreadInfo info; - - @Before - public void setUp() throws Exception { - vmId = "testVM"; - writerId = mock(WriterID.class); - when(writerId.getWriterID()).thenReturn(DEFAULT_W_ID); - - threadDao = mock(ThreadDao.class); - - info = mock(ThreadInfo.class); - when(info.getThreadName()).thenReturn(DEFAULT_THREAD_NAME); - when(info.getThreadId()).thenReturn(DEFAULT_THREAD_ID); - } - - @Test - public void testCreateThreadHeader() throws Exception { - - ThreadHeaderHelper helper = new ThreadHeaderHelper(threadDao, writerId, vmId); - long timestamp = -1l; - - ThreadHeader header = helper.createThreadHeader(info, timestamp); - assertNotNull(header); - - verify(writerId).getWriterID(); - - assertEquals(header.getVmId(), vmId); - assertEquals(header.getAgentId(), DEFAULT_W_ID); - assertEquals(header.getTimeStamp(), timestamp); - assertEquals(header.getThreadName(), DEFAULT_THREAD_NAME); - assertEquals(header.getThreadId(), DEFAULT_THREAD_ID); - } - - @Test - public void testSaveThreadHeader() throws Exception { - ThreadHeaderHelper helper = new ThreadHeaderHelper(threadDao, writerId, vmId); - - ThreadHeader template = new ThreadHeader(DEFAULT_W_ID); - template.setReferenceID("1234"); - template.setVmId(vmId); - template.setThreadName(DEFAULT_THREAD_NAME); - template.setThreadId(DEFAULT_THREAD_ID); - template.setTimeStamp(-1l); - - // first time around, object not present in database - when(threadDao.getThread(template)).thenReturn(null); - - ThreadHeader result = helper.checkAndSaveThreadHeader(template); - assertNotNull(result); - - verify(threadDao).getThread(template); - verify(threadDao).saveThread(template); - - assertEquals(result.getVmId(), template.getVmId()); - assertEquals(result.getAgentId(), template.getAgentId()); - assertEquals(result.getTimeStamp(), template.getTimeStamp()); - assertEquals(result.getThreadName(), template.getThreadName()); - assertEquals(result.getThreadId(), template.getThreadId()); - assertEquals(result, template); - } - - @Test - public void testSaveThreadHeader2() throws Exception { - ThreadHeaderHelper helper = new ThreadHeaderHelper(threadDao, writerId, vmId); - - ThreadHeader template = new ThreadHeader(DEFAULT_W_ID); - template.setReferenceID("1234"); - template.setVmId(vmId); - template.setThreadName(DEFAULT_THREAD_NAME); - template.setThreadId(DEFAULT_THREAD_ID); - template.setTimeStamp(-1l); - - ThreadHeader expected = new ThreadHeader(DEFAULT_W_ID); - expected.setReferenceID("0000"); - expected.setVmId(vmId); - expected.setThreadName(DEFAULT_THREAD_NAME); - expected.setThreadId(DEFAULT_THREAD_ID); - expected.setTimeStamp(-2l); - - // second time around, object is present in database, we need - // to check that the two headers are actually the same, but the - // returned value has the correct refId and timestamp - when(threadDao.getThread(template)).thenReturn(expected); - - ThreadHeader result = helper.checkAndSaveThreadHeader(template); - assertNotNull(result); - - verify(threadDao).getThread(template); - verify(threadDao, times(0)).saveThread(template); - - assertEquals(result.getVmId(), expected.getVmId()); - assertEquals(result.getAgentId(), expected.getAgentId()); - assertEquals(result.getTimeStamp(), expected.getTimeStamp()); - assertEquals(result.getThreadName(), expected.getThreadName()); - assertEquals(result.getThreadId(), expected.getThreadId()); - assertEquals(result, expected); - } -} diff -r 504adea43d70 -r b1306c7c7422 thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadStateHelperTest.java --- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadStateHelperTest.java Thu Dec 11 01:35:29 2014 -0700 +++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadStateHelperTest.java Thu Dec 11 11:44:42 2014 +0100 @@ -37,24 +37,17 @@ package com.redhat.thermostat.thread.harvester; import com.redhat.thermostat.storage.core.WriterID; - import com.redhat.thermostat.thread.dao.ThreadDao; - -import com.redhat.thermostat.thread.model.ThreadHeader; +import com.redhat.thermostat.thread.model.SessionID; import com.redhat.thermostat.thread.model.ThreadState; - +import java.lang.management.ThreadInfo; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; -import java.lang.management.ThreadInfo; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; - import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -64,12 +57,13 @@ private static String DEFAULT_W_ID = "0xcafe"; private static String DEFAULT_HEADER_REF_ID = "42"; + private static String DEFAULT_SESSION_ID = "This Session"; private String vmId; private WriterID writerId; private ThreadDao threadDao; - private ThreadHeader header; + private SessionID sessionID; @Before public void setUp() throws Exception { @@ -79,50 +73,33 @@ threadDao = mock(ThreadDao.class); - header = mock(ThreadHeader.class); - when(header.getReferenceID()).thenReturn(DEFAULT_HEADER_REF_ID); + sessionID = mock(SessionID.class); + when(sessionID.get()).thenReturn(DEFAULT_SESSION_ID); } @Test public void testCreateThreadState() throws Exception { - ThreadStateHelper helper = - new ThreadStateHelper(threadDao, writerId, vmId); + ThreadStateHelper helper = new ThreadStateHelper(threadDao, writerId, vmId); ThreadInfo info = mock(ThreadInfo.class); when(info.getThreadState()).thenReturn(Thread.State.BLOCKED); long timestamp = -1l; - ThreadState state = helper.createThreadState(header, info, timestamp); + ThreadState state = helper.createThreadState(info, sessionID, timestamp); assertNotNull(state); - assertEquals(state.getProbeStartTime(), timestamp); - assertEquals(state.getProbeEndTime(), timestamp); - assertEquals(state.getState(), Thread.State.BLOCKED.name()); - assertEquals(state.getHeader(), header); - assertEquals(state.getReferenceID(), DEFAULT_HEADER_REF_ID); + assertEquals(timestamp, state.getTimeStamp()); + assertEquals(Thread.State.BLOCKED.name(), state.getState()); + assertEquals(DEFAULT_SESSION_ID, state.getSession()); } @Test public void testSaveThreadState() throws Exception { - // this test assumes there is no data in the database yet, - // so a database entry will be created with the template - // object as input - ThreadStateHelper helper = - new ThreadStateHelper(threadDao, writerId, vmId); - - ThreadHeader header = mock(ThreadHeader.class); + ThreadStateHelper helper = new ThreadStateHelper(threadDao, writerId, vmId); ThreadState state = mock(ThreadState.class); - when(state.getState()).thenReturn(Thread.State.BLOCKED.name()); - when(state.getHeader()).thenReturn(header); - when(threadDao.getLastThreadState(header)).thenReturn(null); - - ThreadState result = helper.saveThreadState(state); - assertNotNull(result); - - verify(threadDao).getLastThreadState(header); - verify(state, times(0)).getState(); + helper.saveThreadState(state); ArgumentCaptor captor = ArgumentCaptor.forClass(ThreadState.class); @@ -130,77 +107,5 @@ ThreadState argumentToDao = captor.getValue(); assertEquals(argumentToDao, state); - assertEquals(result, state); - } - - @Test - public void testSaveThreadStateInsertNew() throws Exception { - // this test assumes there is already data in the database, - // but the data object has a different state, hence a new one - // will be created. This is mostly similar in behaviour to the - // first test, except that the dao returns a non null state - // object - ThreadStateHelper helper = - new ThreadStateHelper(threadDao, writerId, vmId); - - ThreadHeader header = mock(ThreadHeader.class); - ThreadState state = mock(ThreadState.class); - when(state.getState()).thenReturn(Thread.State.BLOCKED.name()); - when(state.getHeader()).thenReturn(header); - - ThreadState inDao = mock(ThreadState.class); - when(inDao.getState()).thenReturn(Thread.State.TIMED_WAITING.name()); - when(inDao.getHeader()).thenReturn(header); - - when(threadDao.getLastThreadState(header)).thenReturn(inDao); - - ThreadState result = helper.saveThreadState(state); - assertNotNull(result); - - verify(threadDao).getLastThreadState(header); - verify(inDao).getState(); - - ArgumentCaptor captor = - ArgumentCaptor.forClass(ThreadState.class); - verify(threadDao).addThreadState(captor.capture()); - - ThreadState argumentToDao = captor.getValue(); - assertEquals(argumentToDao, state); - assertEquals(result, state); - } - - @Test - public void testSaveThreadStateUpdateExisting() throws Exception { - // this test assumes there is already data in the database, - // and the object has the same state as the one passed as input, - // so an update will be performed - ThreadStateHelper helper = - new ThreadStateHelper(threadDao, writerId, vmId); - - ThreadHeader header = mock(ThreadHeader.class); - ThreadState state = mock(ThreadState.class); - when(state.getState()).thenReturn(Thread.State.BLOCKED.name()); - when(state.getHeader()).thenReturn(header); - when(state.getProbeEndTime()).thenReturn(42l); - - ThreadState inDao = mock(ThreadState.class); - when(inDao.getState()).thenReturn(Thread.State.BLOCKED.name()); - when(inDao.getHeader()).thenReturn(header); - - when(threadDao.getLastThreadState(header)).thenReturn(inDao); - - ThreadState result = helper.saveThreadState(state); - assertNotNull(result); - - verify(threadDao).getLastThreadState(header); - verify(inDao).getState(); - verify(state).getProbeEndTime(); - - verify(inDao).setProbeEndTime(42l); - - verify(threadDao).updateThreadState(inDao); - - assertEquals(result, inDao); - assertNotSame(result, state); } }