blob: 9722660fdc8d6cb18c2999891abf8c0eaa49cfb1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.jvmstat.perfdata.monitor.protocol.local;
27
28import java.util.*;
29import java.lang.reflect.*;
30import java.io.*;
31
32import sun.jvmstat.monitor.*;
33import sun.jvmstat.monitor.event.*;
34import sun.jvmstat.perfdata.monitor.*;
35
36/**
37 * Concrete implementation of the AbstractMonitoredVm class for the
38 * <em>local:</em> protocol for the HotSpot PerfData monitoring implementation.
39 * <p>
40 * This class provides the ability to attach to the instrumentation buffer
41 * of a live target Java Virtual Machine through a HotSpot specific attach
42 * mechanism.
43 *
44 * @author Brian Doherty
45 * @since 1.5
46 */
47public class LocalMonitoredVm extends AbstractMonitoredVm {
48
49 /**
50 * List of registered listeners.
51 */
52 private ArrayList<VmListener> listeners;
53
54 /**
55 * Task performing listener notification.
56 */
57 private NotifierTask task;
58
59 /**
60 * Create a LocalMonitoredVm instance.
61 *
62 * @param vmid the vm identifier specifying the target JVM
63 * @param interval the sampling interval
64 */
65 public LocalMonitoredVm(VmIdentifier vmid, int interval)
66 throws MonitorException {
67 super(vmid, interval);
68 this.pdb = new PerfDataBuffer(vmid);
69 listeners = new ArrayList<VmListener>();
70 }
71
72 /**
73 * {@inheritDoc}.
74 */
75 public void detach() {
76 if (interval > 0) {
77 /*
78 * if the notifier task is running, stop it, otherwise it can
79 * access non-existent memory once we've detached from the
80 * underlying buffer.
81 */
82 if (task != null) {
83 task.cancel();
84 task = null;
85 }
86 }
87 super.detach();
88 }
89
90 /**
91 * {@inheritDoc}.
92 */
93 public void addVmListener(VmListener l) {
94 synchronized(listeners) {
95 listeners.add(l);
96 if (task == null) {
97 task = new NotifierTask();
98 LocalEventTimer timer = LocalEventTimer.getInstance();
99 timer.schedule(task, interval, interval);
100 }
101 }
102 }
103
104 /**
105 * {@inheritDoc}.
106 */
107 public void removeVmListener(VmListener l) {
108 synchronized(listeners) {
109 listeners.remove(l);
110 if (listeners.isEmpty() && task != null) {
111 task.cancel();
112 task = null;
113 }
114 }
115 }
116
117 /**
118 * {@inheritDoc}.
119 */
120 public void setInterval(int newInterval) {
121 synchronized(listeners) {
122 if (newInterval == interval) {
123 return;
124 }
125
126 int oldInterval = interval;
127 super.setInterval(interval);
128
129 if (task != null) {
130 task.cancel();
131 NotifierTask oldTask = task;
132 task = new NotifierTask();
133 LocalEventTimer timer = LocalEventTimer.getInstance();
134 CountedTimerTaskUtils.reschedule(timer, oldTask, task,
135 oldInterval, newInterval);
136 }
137 }
138 }
139
140 /**
141 * Fire MonitoredVmStructureChanged events.
142 *
143 * @param inserted List of Monitor objects inserted.
144 * @param removed List of Monitor objects removed.
145 */
146 void fireMonitorStatusChangedEvents(List inserted, List removed) {
147 MonitorStatusChangeEvent ev = null;
148 ArrayList registered = null;
149
150 synchronized (listeners) {
151 registered = (ArrayList)listeners.clone();
152 }
153
154 for (Iterator i = registered.iterator(); i.hasNext(); /* empty */) {
155 VmListener l = (VmListener)i.next();
156 // lazily create the event object;
157 if (ev == null) {
158 ev = new MonitorStatusChangeEvent(this, inserted, removed);
159 }
160 l.monitorStatusChanged(ev);
161 }
162 }
163
164 /**
165 * Fire MonitoredUpdated events.
166 */
167 void fireMonitorsUpdatedEvents() {
168 VmEvent ev = null;
169 ArrayList<VmListener> registered = null;
170
171 synchronized (listeners) {
172 registered = cast(listeners.clone());
173 }
174
175 for (VmListener l : registered) {
176 // lazily create the event object;
177 if (ev == null) {
178 ev = new VmEvent(this);
179 }
180 l.monitorsUpdated(ev);
181 }
182 }
183
184 /**
185 * Class to notify listeners of Monitor related events for
186 * the target JVM.
187 */
188 private class NotifierTask extends CountedTimerTask {
189 public void run() {
190 super.run();
191 try {
192 MonitorStatus status = getMonitorStatus();
193 List inserted = status.getInserted();
194 List removed = status.getRemoved();
195
196 if (!inserted.isEmpty() || !removed.isEmpty()) {
197 fireMonitorStatusChangedEvents(inserted, removed);
198 }
199 fireMonitorsUpdatedEvents();
200 } catch (MonitorException e) {
201 // XXX: use logging api
202 System.err.println("Exception updating monitors for "
203 + getVmIdentifier());
204 e.printStackTrace();
205 }
206 }
207 }
208 // Suppress unchecked cast warning msg.
209 @SuppressWarnings("unchecked")
210 static <T> T cast(Object x) {
211 return (T) x;
212 }
213}