/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.visualvm.modules.tracer.impl; import com.sun.tools.visualvm.core.datasource.DataSource; import com.sun.tools.visualvm.core.datasupport.Positionable; import com.sun.tools.visualvm.modules.tracer.PackageStateHandler; import com.sun.tools.visualvm.modules.tracer.ProbeStateHandler; import com.sun.tools.visualvm.modules.tracer.TracerPackage; import com.sun.tools.visualvm.modules.tracer.TracerProbe; import com.sun.tools.visualvm.modules.tracer.TracerProbeDescriptor; import com.sun.tools.visualvm.modules.tracer.impl.timeline.TimelineSupport; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; import org.openide.util.RequestProcessor; /** * * @author Jiri Sedlacek */ final class TracerModel { private static final Logger LOGGER = Logger.getLogger(TracerController.class.getName()); private final DataSource dataSource; private final Map<TracerPackage, List<TracerProbe>> probesCache = new HashMap(); private final Map<TracerProbe, TracerProbeDescriptor> descriptorsCache = new HashMap(); private final Set<Listener> listeners = new HashSet(); private final TimelineSupport timelineSupport; // --- Constructor --------------------------------------------------------- TracerModel(DataSource dataSource) { this.dataSource = dataSource; final TimelineSupport[] timelineSupportArr = new TimelineSupport[1]; try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { timelineSupportArr[0] = new TimelineSupport(new TimelineSupport.DescriptorResolver() { public TracerProbeDescriptor getDescriptor(TracerProbe p) { return TracerModel.this.getDescriptor(p); } }); } }); } catch (Exception e) { LOGGER.severe("Failed to create TimelineSupport for " + dataSource); // NOI18N } timelineSupport = timelineSupportArr[0]; } // --- DataSource ---------------------------------------------------------- DataSource getDataSource() { return dataSource; } // --- Packages ------------------------------------------------------------ List<TracerPackage> getPackages() { try { return TracerSupportImpl.getInstance().getPackages(dataSource); } catch (Throwable t) { LOGGER.log(Level.INFO, "Package exception in getPackages", t); // NOI18N return null; } } // --- Probes -------------------------------------------------------------- void addDescriptor(final TracerPackage<DataSource> p, final TracerProbeDescriptor d) { RequestProcessor.getDefault().post(new Runnable() { public void run() { addProbe(p, d); } }); } void removeDescriptor(final TracerPackage<DataSource> p, final TracerProbeDescriptor d) { RequestProcessor.getDefault().post(new Runnable() { public void run() { removeProbe(p, d); } }); } TracerProbeDescriptor getDescriptor(TracerProbe p) { synchronized(descriptorsCache) { return descriptorsCache.get(p); } } // Must be called in EDT List<TracerProbe> getDefinedProbes() { List<TracerProbe> probes = new ArrayList(); probes.addAll(timelineSupport.getProbes()); return probes; } Set<Map.Entry<TracerPackage, List<TracerProbe>>> getDefinedProbeSets() { Comparator<Map.Entry<TracerPackage, List<TracerProbe>>> comp = new Comparator<Map.Entry<TracerPackage, List<TracerProbe>>>() { public int compare(Entry<TracerPackage, List<TracerProbe>> o1, Entry<TracerPackage, List<TracerProbe>> o2) { return Positionable.STRONG_COMPARATOR.compare(o1.getKey(), o2.getKey()); } }; Set<Map.Entry<TracerPackage, List<TracerProbe>>> probes = new TreeSet(comp); synchronized(probesCache) { probes.addAll(probesCache.entrySet()); } return probes; } boolean areProbesDefined() { synchronized(probesCache) { return !probesCache.isEmpty(); } } private void addProbe(TracerPackage<DataSource> p, TracerProbeDescriptor d) { TracerProbe<DataSource> r = p.getProbe(d); synchronized(descriptorsCache) { descriptorsCache.put(r, d); } synchronized(probesCache) { List<TracerProbe> probes = probesCache.get(p); if (probes == null) { probes = new ArrayList(); probesCache.put(p, probes); } probes.add(r); } timelineSupport.addProbe(r); notifyProbeAdded(p, r); fireProbeAdded(r); } private void removeProbe(TracerPackage<DataSource> p, TracerProbeDescriptor d) { TracerProbe probe = null; boolean probesDefined = true; synchronized(descriptorsCache) { Iterator<Map.Entry<TracerProbe, TracerProbeDescriptor>> iter = descriptorsCache.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<TracerProbe, TracerProbeDescriptor> entry = iter.next(); if (entry.getValue() == d) { probe = entry.getKey(); break; } } descriptorsCache.remove(probe); } synchronized(probesCache) { List<TracerProbe> probes = probesCache.get(p); probes.remove(probe); if (probes.isEmpty()) { probesCache.remove(p); probesDefined = !probesCache.isEmpty(); } } timelineSupport.removeProbe(probe); notifyProbeRemoved(p, probe); fireProbeRemoved(probe, probesDefined); } private void notifyProbeAdded(TracerPackage p, TracerProbe<DataSource> r) { PackageStateHandler ph = p.getStateHandler(); if (ph != null) try { ph.probeAdded(r, dataSource); } catch (Throwable t) { LOGGER.log(Level.INFO, "Package exception in probeAdded", t); // NOI18N } ProbeStateHandler rh = r.getStateHandler(); if (rh != null) try { rh.probeAdded(dataSource); } catch (Throwable t) { LOGGER.log(Level.INFO, "Probe exception in probeAdded", t); // NOI18N } } private void notifyProbeRemoved(TracerPackage p, TracerProbe<DataSource> r) { PackageStateHandler ph = p.getStateHandler(); if (ph != null) try { ph.probeRemoved(r, dataSource); } catch (Throwable t) { LOGGER.log(Level.INFO, "Package exception in probeRemoved", t); // NOI18N } ProbeStateHandler rh = r.getStateHandler(); if (rh != null) try { rh.probeRemoved(dataSource); } catch (Throwable t) { LOGGER.log(Level.INFO, "Probe exception in probeRemoved", t); // NOI18N } } // --- Events support ------------------------------------------------------ void addListener(Listener listener) { synchronized(listeners) { listeners.add(listener); } } void removeListener(Listener listener) { synchronized(listeners) { listeners.remove(listener); } } private void fireProbeAdded(final TracerProbe probe) { final Set<Listener> toNotify = new HashSet(); synchronized(listeners) { toNotify.addAll(listeners); } SwingUtilities.invokeLater(new Runnable() { public void run() { for (Listener listener : toNotify) listener.probeAdded(probe); } }); } private void fireProbeRemoved(final TracerProbe probe, final boolean probesDefined) { final Set<Listener> toNotify = new HashSet(); synchronized(listeners) { toNotify.addAll(listeners); } SwingUtilities.invokeLater(new Runnable() { public void run() { for (Listener listener : toNotify) listener.probeRemoved(probe, probesDefined); } }); } static interface Listener { public void probeAdded(TracerProbe probe); public void probeRemoved(TracerProbe probe, boolean probesDefined); } // --- Timeline ------------------------------------------------------------ TimelineSupport getTimelineSupport() { return timelineSupport; } }