1 /* 2 * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.jvmstat.perfdata.monitor.protocol.local; 27 28 import sun.jvmstat.monitor.*; 29 import sun.jvmstat.monitor.event.*; 30 import sun.jvmstat.perfdata.monitor.*; 31 import java.util.*; 32 import java.net.*; 33 34 /** 35 * Concrete implementation of the MonitoredHost interface for the 36 * <em>local</em> protocol of the HotSpot PerfData monitoring implementation. 37 * 38 * @author Brian Doherty 39 * @since 1.5 40 */ 41 public class MonitoredHostProvider extends MonitoredHost { 42 private static final int DEFAULT_POLLING_INTERVAL = 1000; 43 44 private ArrayList<HostListener> listeners; 45 private NotifierTask task; 46 private HashSet<Integer> activeVms; 47 private LocalVmManager vmManager; 48 49 /** 50 * Create a MonitoredHostProvider instance using the given HostIdentifier. 51 * 52 * @param hostId the host identifier for this MonitoredHost 53 */ 54 public MonitoredHostProvider(HostIdentifier hostId) { 55 this.hostId = hostId; 56 this.listeners = new ArrayList<HostListener>(); 57 this.interval = DEFAULT_POLLING_INTERVAL; 58 this.activeVms = new HashSet<Integer>(); 59 this.vmManager = new LocalVmManager(); 60 } 61 62 /** 63 * {@inheritDoc} 64 */ 65 public MonitoredVm getMonitoredVm(VmIdentifier vmid) 66 throws MonitorException { 67 return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL); 68 } 69 70 /** 71 * {@inheritDoc} 72 */ 73 public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval) 74 throws MonitorException { 75 try { 76 VmIdentifier nvmid = hostId.resolve(vmid); 77 return new LocalMonitoredVm(nvmid, interval); 78 } catch (URISyntaxException e) { 79 /* 80 * the VmIdentifier is expected to be a valid and it should 81 * resolve reasonably against the host identifier. A 82 * URISyntaxException here is most likely a programming error. 83 */ 84 throw new IllegalArgumentException("Malformed URI: " 85 + vmid.toString(), e); 86 } 87 } 88 89 /** 90 * {@inheritDoc} 91 */ 92 public void detach(MonitoredVm vm) { 93 vm.detach(); 94 } 95 96 /** 97 * {@inheritDoc} 98 */ 99 public void addHostListener(HostListener listener) { 100 synchronized(listeners) { 101 listeners.add(listener); 102 if (task == null) { 103 task = new NotifierTask(); 104 LocalEventTimer timer = LocalEventTimer.getInstance(); 105 timer.schedule(task, interval, interval); 106 } 107 } 108 } 109 110 /** 111 * {@inheritDoc} 112 */ 113 public void removeHostListener(HostListener listener) { 114 synchronized(listeners) { 115 listeners.remove(listener); 116 if (listeners.isEmpty() && (task != null)) { 117 task.cancel(); 118 task = null; 119 } 120 } 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 public void setInterval(int newInterval) { 127 synchronized(listeners) { 128 if (newInterval == interval) { 129 return; 130 } 131 132 int oldInterval = interval; 133 super.setInterval(newInterval); 134 135 if (task != null) { 136 task.cancel(); 137 NotifierTask oldTask = task; 138 task = new NotifierTask(); 139 LocalEventTimer timer = LocalEventTimer.getInstance(); 140 CountedTimerTaskUtils.reschedule(timer, oldTask, task, 141 oldInterval, newInterval); 142 } 143 } 144 } 145 146 /** 147 * {@inheritDoc} 148 */ 149 public Set<Integer> activeVms() { 150 return vmManager.activeVms(); 151 } 152 153 /** 154 * Fire VmEvent events. 155 * 156 * @param active a set of Integer objects containing the vmid of 157 * the active Vms 158 * @param started a set of Integer objects containing the vmid of 159 * new Vms started since last interval. 160 * @param terminated a set of Integer objects containing the vmid of 161 * terminated Vms since last interval. 162 */ 163 private void fireVmStatusChangedEvents(Set active, Set started, 164 Set terminated) { 165 ArrayList registered = null; 166 VmStatusChangeEvent ev = null; 167 168 synchronized(listeners) { 169 registered = (ArrayList)listeners.clone(); 170 } 171 172 for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) { 173 HostListener l = (HostListener)i.next(); 174 if (ev == null) { 175 ev = new VmStatusChangeEvent(this, active, started, terminated); 176 } 177 l.vmStatusChanged(ev); 178 } 179 } 180 181 /** 182 * Class to poll the local system and generate event notifications. 183 */ 184 private class NotifierTask extends CountedTimerTask { 185 public void run() { 186 super.run(); 187 188 // save the last set of active JVMs 189 Set lastActiveVms = activeVms; 190 191 // get the current set of active JVMs 192 activeVms = (HashSet<Integer>)vmManager.activeVms(); 193 194 if (activeVms.isEmpty()) { 195 return; 196 } 197 Set<Integer> startedVms = new HashSet<Integer>(); 198 Set<Object> terminatedVms = new HashSet<Object>(); 199 200 for (Iterator i = activeVms.iterator(); i.hasNext(); /* empty */) { 201 Integer vmid = (Integer)i.next(); 202 if (!lastActiveVms.contains(vmid)) { 203 // a new file has been detected, add to set 204 startedVms.add(vmid); 205 } 206 } 207 208 for (Iterator i = lastActiveVms.iterator(); i.hasNext(); 209 /* empty */) { 210 Object o = i.next(); 211 if (!activeVms.contains(o)) { 212 // JVM has terminated, remove it from the active list 213 terminatedVms.add(o); 214 } 215 } 216 217 if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) { 218 fireVmStatusChangedEvents(activeVms, startedVms, 219 terminatedVms); 220 } 221 } 222 } 223 }