2 * Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
4 * The Sun Project JXTA(TM) Software License
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. The end-user documentation included with the redistribution, if any, must
17 * include the following acknowledgment: "This product includes software
18 * developed by Sun Microsystems, Inc. for JXTA(TM) technology."
19 * Alternately, this acknowledgment may appear in the software itself, if
20 * and wherever such third-party acknowledgments normally appear.
22 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
23 * not be used to endorse or promote products derived from this software
24 * without prior written permission. For written permission, please contact
25 * Project JXTA at http://www.jxta.org.
27 * 5. Products derived from this software may not be called "JXTA", nor may
28 * "JXTA" appear in their name, without prior written permission of Sun.
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN
33 * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
36 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * JXTA is a registered trademark of Sun Microsystems, Inc. in the United
42 * States and other countries.
44 * Please see the license information page at :
45 * <http://www.jxta.org/project/www/license.html> for instructions on use of
46 * the license in source files.
48 * ====================================================================
50 * This software consists of voluntary contributions made by many individuals
51 * on behalf of Project JXTA. For more information on Project JXTA, please see
52 * http://www.jxta.org.
54 * This license is based on the BSD license adopted by the Apache Foundation.
57 package net.jxta.impl.meter;
60 import net.jxta.document.Advertisement;
61 import net.jxta.exception.JxtaException;
62 import net.jxta.id.ID;
63 import net.jxta.impl.util.TimeUtils;
64 import net.jxta.meter.MonitorEvent;
65 import net.jxta.meter.MonitorException;
66 import net.jxta.meter.MonitorFilter;
67 import net.jxta.meter.MonitorFilterException;
68 import net.jxta.meter.MonitorListener;
69 import net.jxta.meter.MonitorReport;
70 import net.jxta.meter.MonitorResources;
71 import net.jxta.meter.PeerMonitorInfo;
72 import net.jxta.meter.ServiceMetric;
73 import net.jxta.meter.ServiceMonitor;
74 import net.jxta.meter.ServiceMonitorFilter;
75 import net.jxta.peergroup.PeerGroup;
76 import net.jxta.peergroup.PeerGroupID;
77 import net.jxta.platform.ModuleClassID;
78 import net.jxta.protocol.ModuleImplAdvertisement;
79 import net.jxta.service.Service;
80 import net.jxta.util.documentSerializable.DocumentSerializableUtilities;
81 import net.jxta.util.documentSerializable.DocumentSerializationException;
83 import java.util.Enumeration;
84 import java.util.Hashtable;
85 import java.util.Iterator;
86 import java.util.LinkedList;
89 public class MonitorManager implements Service {
90 private final static long timeZero = System.currentTimeMillis();
91 public static final int NOT_PULSING = -1;
93 private static final int NO_PRIOR_REPORT = 0;
95 private static long supportedReportRates[] = new long[] {
96 500, TimeUtils.ASECOND, 5 * TimeUtils.ASECOND, 10 * TimeUtils.ASECOND, 15 * TimeUtils.ASECOND, 30 * TimeUtils.ASECOND
98 TimeUtils.AMINUTE, 5 * TimeUtils.AMINUTE, 10 * TimeUtils.AMINUTE, 15 * TimeUtils.AMINUTE, 30 * TimeUtils.AMINUTE
100 TimeUtils.ANHOUR, 3 * TimeUtils.ANHOUR, 6 * TimeUtils.ANHOUR, 12 * TimeUtils.ANHOUR, TimeUtils.ADAY, TimeUtils.AWEEK};
102 private int pulsesPerRate[] = new int[supportedReportRates.length];
103 private long startTime = System.currentTimeMillis();
105 private LinkedList<MonitorListenerInfo> monitorListenerInfos = new LinkedList<MonitorListenerInfo>();
106 private Hashtable<ModuleClassID, ServiceMonitorPulseInfo> serviceMonitorPulseInfos = new Hashtable<ModuleClassID, ServiceMonitorPulseInfo>();
107 private int filtersPerRate[] = new int[supportedReportRates.length];
108 private long previousReportTimes[] = new long[supportedReportRates.length];
110 private PeerGroup peerGroup;
111 private Thread reportThread;
113 private long pulseRate = NOT_PULSING;
114 private int pulseRateIndex = NOT_PULSING;
115 private int pulseNumber = 0;
116 private long nextPulseTime = NO_PRIOR_REPORT;
117 private boolean isRunning = true; // true until monitor is destroyed, triggers termination of report thread
119 private ModuleClassID[] supportedModuleClassIDs;
120 private ModuleImplAdvertisement implAdvertisement;
121 private long lastResetTime = System.currentTimeMillis();
123 public Advertisement getImplAdvertisement() {
124 return implAdvertisement;
127 public Service getInterface() {
128 // This is good enough. No need to get fancy.
132 // public MonitorManager(PeerGroup peerGroup) {
134 public void init(PeerGroup peerGroup, ID assignedID, Advertisement implAdvertisement) {
135 this.implAdvertisement = (ModuleImplAdvertisement) implAdvertisement;
136 this.peerGroup = peerGroup;
137 createReportThread();
139 for (int i = 0; i < previousReportTimes.length; i++) {
140 pulsesPerRate[i] = (int) (supportedReportRates[i] / supportedReportRates[0]);
144 public int startApp(java.lang.String[] args) {
148 public void stopApp() {
152 private class MonitorListenerInfo {
153 MonitorListener monitorListener;
154 MonitorFilter monitorFilter;
157 boolean sendCumulativeFirst = false;
158 boolean wasCumulativeSent = false;
160 MonitorListenerInfo(MonitorListener monitorListener, long reportRate, MonitorFilter monitorFilter, boolean cumulativeFirst) {
161 this.monitorListener = monitorListener;
162 this.monitorFilter = monitorFilter;
163 this.reportRate = reportRate;
164 this.sendCumulativeFirst = cumulativeFirst;
165 this.reportRateIndex = getReportRateIndex(reportRate);
169 public static long[] getReportRates() { // return copy so that users can't modify.
170 long copy[] = new long[supportedReportRates.length];
172 System.arraycopy(supportedReportRates, 0, copy, 0, supportedReportRates.length);
176 public boolean isLocalMonitoringAvailable(ModuleClassID moduleClassID) {
177 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
179 return (serviceMonitor != null);
182 public PeerGroup getPeerGroup() {
186 // Cooperate with the code that loaded this module to replace the strong
187 // group interface given by init() with a non-counted one.
188 private void setPeerGroup(PeerGroup pg) {
189 PeerGroup tmp = peerGroup;
196 public PeerMonitorInfo getPeerMonitorInfo() {
197 long[] reportRates = getReportRates(); // makes a copy
198 ModuleClassID[] moduleClassIDs = getMonitorableServiceTypes(); // ensures that array is initialized.
199 long runningTime = System.currentTimeMillis() - lastResetTime;
201 return new PeerMonitorInfo(MeterBuildSettings.METERING, moduleClassIDs, reportRates, lastResetTime, runningTime);
204 public int getReportRatesCount() {
205 return supportedReportRates.length;
208 public int getReportRateIndex(long reportRate) {
209 for (int i = 0; i < supportedReportRates.length; i++) {
210 if (supportedReportRates[i] == reportRate) {
218 public boolean isSupportedReportRate(long reportRate) {
219 return getReportRateIndex(reportRate) >= 0;
222 public long getReportRate(int index) {
223 return supportedReportRates[index];
226 public long getBestReportRate(long desiredReportRate) {
227 for (long supportedReportRate : supportedReportRates) {
228 if (desiredReportRate <= supportedReportRate) {
229 return supportedReportRate;
233 return supportedReportRates[supportedReportRates.length - 1];
236 public ServiceMonitor getServiceMonitor(ModuleClassID moduleClassID) {
237 ServiceMonitorPulseInfo serviceMonitorPulseInfo = serviceMonitorPulseInfos.get(moduleClassID);
239 if (serviceMonitorPulseInfo != null) {
240 return serviceMonitorPulseInfo.serviceMonitor;
244 ModuleImplAdvertisement moduleImplAdvertisement = MonitorResources.getServiceMonitorImplAdvertisement(
245 moduleClassID, implAdvertisement);
246 ServiceMonitor serviceMonitor = (ServiceMonitor) peerGroup.loadModule(moduleClassID, moduleImplAdvertisement);
248 MonitorResources.registerServiceMonitorModuleImplAdvertisement(moduleImplAdvertisement);
250 if (serviceMonitor instanceof ServiceMonitorImpl) {
251 ((ServiceMonitorImpl) serviceMonitor).init(this);
255 serviceMonitorPulseInfo = new ServiceMonitorPulseInfo(this, serviceMonitor);
256 serviceMonitorPulseInfos.put(moduleClassID, serviceMonitorPulseInfo);
257 return serviceMonitor;
258 } catch (JxtaException e) {
259 throw new RuntimeException("Unable to load Service Monitor: " + moduleClassID + "\n\tException: " + e);
264 private void resetPulseRate() {
265 int oldPulseRateIndex = pulseRateIndex;
267 pulseRateIndex = NOT_PULSING;
268 pulseRate = NOT_PULSING;
270 for (int i = 0; i < filtersPerRate.length; i++) {
271 if (filtersPerRate[i] != 0) {
273 pulseRate = getReportRate(pulseRateIndex);
278 if (oldPulseRateIndex == pulseRateIndex) {
282 long now = System.currentTimeMillis();
284 if (oldPulseRateIndex == NOT_PULSING) { // case 1: No pulse to pulse
285 for (int i = 0; i < filtersPerRate.length; i++) {
286 if (filtersPerRate[i] != 0) {
287 previousReportTimes[i] = now;
289 previousReportTimes[i] = NO_PRIOR_REPORT;
294 nextPulseTime = now + pulseRate;
295 } else if (pulseRateIndex == NOT_PULSING) {// case 2: pulse to No pulse
297 } else if (pulseRateIndex < oldPulseRateIndex) { // case 3: pulse going to a faster pulse
298 for (int i = pulseRateIndex; i < (oldPulseRateIndex - 1); i++) {
299 if (filtersPerRate[i] != 0) {
300 previousReportTimes[i] = now;
302 previousReportTimes[i] = NO_PRIOR_REPORT;
306 long timeToNextPulse = nextPulseTime - now;
308 if (pulseRate < timeToNextPulse) {
309 int numPulsesToNow = (int) (timeToNextPulse / pulseRate);
310 int numNewToOldPulses = (int) (supportedReportRates[oldPulseRateIndex] / supportedReportRates[pulseRateIndex]);
312 pulseNumber += (numNewToOldPulses - numPulsesToNow) * pulsesPerRate[pulseRateIndex];
313 timeToNextPulse = now - (numPulsesToNow * pulseRate);
315 pulseNumber += (pulsesPerRate[oldPulseRateIndex] - pulsesPerRate[pulseRateIndex]);
318 } else if (pulseRateIndex > oldPulseRateIndex) { // case 3: pulse going to a slower pulse
319 int nextPulseNumber = pulseNumber + pulsesPerRate[oldPulseRateIndex];
321 pulseNumber = ((nextPulseNumber - 1) / pulsesPerRate[pulseRateIndex]) * pulsesPerRate[pulseRateIndex];
322 nextPulseTime += (nextPulseNumber - pulseNumber) * supportedReportRates[0];
324 for (int i = 0; i < pulseRateIndex; i++) {
325 previousReportTimes[i] = NO_PRIOR_REPORT;
329 reportThread.interrupt();
332 private MonitorReport getMonitorReport(MonitorFilter monitorFilter, long reportRate, long previousDeltaTime, long beginReportTime) {
333 MonitorReport monitorReport = new MonitorReport(previousDeltaTime, beginReportTime, false);
335 for (Iterator i = monitorFilter.getModuleClassIDs(); i.hasNext();) {
336 ModuleClassID moduleClassID = (ModuleClassID) i.next();
338 ServiceMonitorFilter serviceMonitorFilter = monitorFilter.getServiceMonitorFilter(moduleClassID);
340 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
342 if (serviceMonitorFilter != null) {
343 ServiceMetric serviceMetric = serviceMonitor.getServiceMetric(serviceMonitorFilter, previousDeltaTime
345 beginReportTime, getReportRateIndex(reportRate), reportRate);
347 if (serviceMetric != null) {
348 monitorReport.addServiceMetric(serviceMetric);
352 return monitorReport;
355 public void validateCumulativeMonitorFilter(MonitorFilter monitorFilter) throws MonitorFilterException {
356 boolean isAnyServiceFilters = false;
358 for (Iterator i = monitorFilter.getServiceMonitorFilters(); i.hasNext();) {
359 ServiceMonitorFilter serviceMonitorFilter = (ServiceMonitorFilter) i.next();
361 ModuleClassID moduleClassID = serviceMonitorFilter.getModuleClassID();
362 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
364 if (serviceMonitor == null) {
365 throw new MonitorFilterException(MonitorFilterException.SERVICE_NOT_SUPPORTED, moduleClassID);
368 serviceMonitor.validateCumulativeServiceMonitorFilter(serviceMonitorFilter);
369 isAnyServiceFilters = true;
372 if (!isAnyServiceFilters) {
373 throw new MonitorFilterException("Empty Monitor Filter");
378 public void validateMonitorFilter(MonitorFilter monitorFilter, long reportRate) throws MonitorFilterException {
380 if (!isSupportedReportRate(reportRate)) {
381 throw new MonitorFilterException(MonitorFilterException.REPORT_RATE_NOT_SUPPORTED, reportRate);
384 boolean isAnyServiceFilters = false;
386 for (Iterator i = monitorFilter.getServiceMonitorFilters(); i.hasNext();) {
387 ServiceMonitorFilter serviceMonitorFilter = (ServiceMonitorFilter) i.next();
389 ModuleClassID moduleClassID = serviceMonitorFilter.getModuleClassID();
390 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
392 if (serviceMonitor == null) {
393 throw new MonitorFilterException(MonitorFilterException.SERVICE_NOT_SUPPORTED, moduleClassID);
396 serviceMonitor.validateServiceMonitorFilter(serviceMonitorFilter, reportRate);
397 isAnyServiceFilters = true;
400 if (!isAnyServiceFilters) {
401 throw new MonitorFilterException("Empty Monitor Filter");
405 public MonitorFilter createSupportedCumulativeMonitorFilter(MonitorFilter monitorFilter) throws MonitorFilterException {
406 MonitorFilter newMonitorFilter = new MonitorFilter(monitorFilter.getDescription());
407 boolean anythingAdded = false;
409 for (Iterator i = monitorFilter.getServiceMonitorFilters(); i.hasNext();) {
410 ServiceMonitorFilter serviceMonitorFilter = (ServiceMonitorFilter) i.next();
412 ModuleClassID moduleClassID = serviceMonitorFilter.getModuleClassID();
413 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
415 if (serviceMonitor == null) {
419 ServiceMonitorFilter newServiceMonitorFilter = serviceMonitor.createSupportedCumulativeServiceMonitorFilter(
420 serviceMonitorFilter);
422 if (newServiceMonitorFilter != null) {
423 newMonitorFilter.addServiceMonitorFilter(newServiceMonitorFilter);
424 anythingAdded = true;
429 return newMonitorFilter;
435 public MonitorFilter createSupportedMonitorFilter(MonitorFilter monitorFilter, long reportRate) throws MonitorFilterException {
436 MonitorFilter newMonitorFilter = new MonitorFilter(monitorFilter.getDescription());
437 boolean anythingAdded = false;
439 for (Iterator i = monitorFilter.getServiceMonitorFilters(); i.hasNext();) {
440 ServiceMonitorFilter serviceMonitorFilter = (ServiceMonitorFilter) i.next();
442 ModuleClassID moduleClassID = serviceMonitorFilter.getModuleClassID();
443 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
445 if (serviceMonitor == null) {
449 ServiceMonitorFilter newServiceMonitorFilter = serviceMonitor.createSupportedServiceMonitorFilter(serviceMonitorFilter
453 if (newServiceMonitorFilter != null) {
454 newMonitorFilter.addServiceMonitorFilter(newServiceMonitorFilter);
455 anythingAdded = true;
460 return newMonitorFilter;
466 public synchronized long addMonitorListener(MonitorFilter monitorFilter, long reportRate, boolean includeCumulative, MonitorListener monitorListener) throws MonitorException {
468 validateMonitorFilter(monitorFilter, reportRate); // if validation fails, it will throw an exception
470 if (includeCumulative) {
471 validateCumulativeMonitorFilter(monitorFilter);
472 } // if validation fails, it will throw an exception
474 int reportRateIndex = getReportRateIndex(reportRate);
477 monitorFilter = (MonitorFilter) DocumentSerializableUtilities.copyDocumentSerializable(monitorFilter); // make a copy of the filter
478 } catch (DocumentSerializationException e) {
479 throw new MonitorException(MonitorException.SERIALIZATION, "Error trying to copy MonitorFilter");
482 MonitorListenerInfo monitorListenerInfo = new MonitorListenerInfo(monitorListener, reportRate, monitorFilter
486 monitorListenerInfos.add(monitorListenerInfo);
487 filtersPerRate[reportRateIndex]++;
489 if ((filtersPerRate[reportRateIndex] == 1) && (pulseRateIndex != NOT_PULSING) && (reportRateIndex > pulseRateIndex)) {
490 previousReportTimes[reportRateIndex] = previousReportTimes[pulseRateIndex];
493 for (Iterator i = monitorFilter.getModuleClassIDs(); i.hasNext();) {
494 ModuleClassID moduleClassID = (ModuleClassID) i.next();
496 ServiceMonitorFilter serviceMonitorFilter = monitorFilter.getServiceMonitorFilter(moduleClassID);
497 ServiceMonitorPulseInfo serviceMonitorPulseInfo = serviceMonitorPulseInfos.get(moduleClassID);
499 serviceMonitorPulseInfo.registerServiceMonitorFilter(serviceMonitorFilter, reportRateIndex, reportRate);
507 private MonitorListenerInfo getMonitorListenerInfo(MonitorListener monitorListener) {
508 for (Object monitorListenerInfo1 : monitorListenerInfos) {
509 MonitorListenerInfo monitorListenerInfo = (MonitorListenerInfo) monitorListenerInfo1;
511 if (monitorListenerInfo.monitorListener == monitorListener) {
512 return monitorListenerInfo;
518 public synchronized int removeMonitorListener(MonitorListener monitorListener) {
521 for (;;) { // remove all instances of this listener
522 MonitorListenerInfo monitorListenerInfo = getMonitorListenerInfo(monitorListener);
524 if (monitorListenerInfo == null) {
527 MonitorFilter monitorFilter = monitorListenerInfo.monitorFilter;
528 long reportRate = monitorListenerInfo.reportRate;
529 int reportRateIndex = monitorListenerInfo.reportRateIndex;
531 monitorListenerInfos.remove(monitorListenerInfo);
533 filtersPerRate[reportRateIndex]--;
535 for (Iterator i = monitorFilter.getModuleClassIDs(); i.hasNext();) {
536 ModuleClassID moduleClassID = (ModuleClassID) i.next();
538 ServiceMonitorFilter serviceMonitorFilter = monitorFilter.getServiceMonitorFilter(moduleClassID);
539 ServiceMonitorPulseInfo serviceMonitorPulseInfo = serviceMonitorPulseInfos.get(moduleClassID);
541 serviceMonitorPulseInfo.deregisterServiceMonitorFilter(serviceMonitorFilter, reportRateIndex, reportRate);
551 public synchronized MonitorReport getCumulativeMonitorReport(MonitorFilter monitorFilter) throws MonitorException {
552 validateCumulativeMonitorFilter(monitorFilter);
554 long beginReportTime = System.currentTimeMillis();
556 MonitorReport monitorReport = new MonitorReport(startTime, beginReportTime, true);
558 for (Iterator i = monitorFilter.getModuleClassIDs(); i.hasNext();) {
559 ModuleClassID moduleClassID = (ModuleClassID) i.next();
561 ServiceMonitorFilter serviceMonitorFilter = monitorFilter.getServiceMonitorFilter(moduleClassID);
562 ServiceMonitor serviceMonitor = getServiceMonitor(moduleClassID);
564 ServiceMetric serviceMetric = serviceMonitor.getCumulativeServiceMetric(serviceMonitorFilter, timeZero
568 monitorReport.addServiceMetric(moduleClassID, serviceMetric);
571 return monitorReport;
574 public ModuleClassID[] getMonitorableServiceTypes() {
575 if (supportedModuleClassIDs == null) {
576 ModuleClassID[] registeredModuleClassIDs = MonitorResources.getRegisteredModuleClassIDs();
577 LinkedList<ModuleClassID> supportedModuleClassIDsList = new LinkedList<ModuleClassID>();
579 for (ModuleClassID registeredModuleClassID : registeredModuleClassIDs) {
580 if (isLocalMonitoringAvailable(registeredModuleClassID)) {
581 supportedModuleClassIDsList.add(registeredModuleClassID);
585 supportedModuleClassIDs = supportedModuleClassIDsList.toArray(new ModuleClassID[0]);
587 return supportedModuleClassIDs;
590 // fastest pulse rate registered anywhere
591 public long getPulseRate() {
592 return getReportRate(pulseRateIndex);
595 // index of fastest pulse anywhere
596 public int getPulseRateIndex() {
597 return pulseRateIndex;
600 // pulse rate for this monitor
601 public long getPulseRate(ServiceMonitor serviceMonitor) {
602 ServiceMonitorPulseInfo serviceMonitorPulseInfo = serviceMonitorPulseInfos.get(serviceMonitor.getModuleClassID());
604 if (serviceMonitorPulseInfo != null) {
605 return serviceMonitorPulseInfo.getPulseRate();
607 return ServiceMonitorPulseInfo.NOT_PULSING;
611 // index of pulse rate for this monitor
612 public long getPulseRateIndex(ServiceMonitor serviceMonitor) {
613 ServiceMonitorPulseInfo serviceMonitorPulseInfo = serviceMonitorPulseInfos.get(serviceMonitor.getModuleClassID());
615 if (serviceMonitorPulseInfo != null) {
616 return serviceMonitorPulseInfo.getPulseRateIndex();
618 return ServiceMonitorPulseInfo.NOT_PULSING;
622 private void generateReports() {
623 long beginReportTime = System.currentTimeMillis();
625 for (Enumeration<ServiceMonitorPulseInfo> e = serviceMonitorPulseInfos.elements(); e.hasMoreElements();) {
626 ServiceMonitorPulseInfo serviceMonitorPulseInfo = e.nextElement();
627 int servicePulseRateIndex = serviceMonitorPulseInfo.getPulseRateIndex();
629 if ((serviceMonitorPulseInfo.serviceMonitor instanceof ServiceMonitorImpl)
630 && isEvenPulseForRateIndex(servicePulseRateIndex)) {
631 ((ServiceMonitorImpl) serviceMonitorPulseInfo.serviceMonitor).beginPulse(serviceMonitorPulseInfo);
635 for (Object monitorListenerInfo1 : monitorListenerInfos) {
636 MonitorListenerInfo monitorListenerInfo = (MonitorListenerInfo) monitorListenerInfo1;
637 MonitorFilter monitorFilter = monitorListenerInfo.monitorFilter;
638 MonitorListener monitorListener = monitorListenerInfo.monitorListener;
640 int reportRateIndex = monitorListenerInfo.reportRateIndex;
641 long reportRate = monitorListenerInfo.reportRate;
643 if (isEvenPulseForRateIndex(reportRateIndex)) {
644 MonitorReport monitorReport = null;
647 if (monitorListenerInfo.sendCumulativeFirst && !monitorListenerInfo.wasCumulativeSent) {
648 monitorReport = getCumulativeMonitorReport(monitorFilter);
650 MonitorEvent monitorEvent = new MonitorEvent(peerGroup.getPeerGroupID(), monitorReport);
652 monitorListener.processMonitorReport(monitorEvent);
653 monitorListenerInfo.wasCumulativeSent = true;
655 monitorReport = getMonitorReport(monitorFilter, reportRate, previousReportTimes[reportRateIndex]
658 MonitorEvent monitorEvent = new MonitorEvent(peerGroup.getPeerGroupID(), monitorReport);
660 monitorListener.processMonitorReport(monitorEvent);
662 } catch (Throwable e) {
664 // Fix-Me: Where should we report an uncaught exception in one of our listeners?
669 for (int rateIndex = 0; rateIndex < supportedReportRates.length; rateIndex++) {
670 if (isEvenPulseForRateIndex(rateIndex)) {
671 if (filtersPerRate[rateIndex] != 0) {
672 previousReportTimes[rateIndex] = beginReportTime;
674 previousReportTimes[rateIndex] = NO_PRIOR_REPORT;
679 for (Enumeration<ServiceMonitorPulseInfo> e = serviceMonitorPulseInfos.elements(); e.hasMoreElements();) {
680 ServiceMonitorPulseInfo serviceMonitorPulseInfo = e.nextElement();
681 int servicePulseRateIndex = serviceMonitorPulseInfo.getPulseRateIndex();
683 if ((serviceMonitorPulseInfo.serviceMonitor instanceof ServiceMonitorImpl)
684 && isEvenPulseForRateIndex(servicePulseRateIndex)) {
685 ((ServiceMonitorImpl) serviceMonitorPulseInfo.serviceMonitor).endPulse(serviceMonitorPulseInfo);
690 boolean isEvenPulseForRateIndex(int pulseRateIndex) {
691 if (pulseRateIndex < 0 || pulseRateIndex > pulsesPerRate.length) {
694 return ((pulseNumber % pulsesPerRate[pulseRateIndex]) == 0);
697 private void createReportThread() {
698 reportThread = new Thread(new Runnable() {
702 synchronized (MonitorManager.this) { // no new listeners while reporting
703 while (pulseRate == NOT_PULSING) {
705 MonitorManager.this.wait();
706 } catch (InterruptedException e) {
711 while (pulseRate != NOT_PULSING) {
712 if (Thread.interrupted()) {
716 long now = System.currentTimeMillis();
719 long waitTime = nextPulseTime - now;
722 MonitorManager.this.wait(nextPulseTime - now);
725 pulseNumber += pulsesPerRate[pulseRateIndex];
727 nextPulseTime += pulseRate;
728 } catch (InterruptedException e) {
729 if (pulseRateIndex == NOT_PULSING) {
732 } catch (Exception ex) {
733 // don't die forever on exceptions!!
734 ex.printStackTrace(); // fix-me: report this
740 }, "Meter-Monitor-Report");
742 reportThread.setDaemon(true);
743 reportThread.start();
746 public synchronized void destroy() {
748 reportThread.interrupt();
750 for (Enumeration<ServiceMonitorPulseInfo> e = serviceMonitorPulseInfos.elements(); e.hasMoreElements();) {
751 ServiceMonitorPulseInfo serviceMonitorPulseInfo = e.nextElement();
752 ServiceMonitor serviceMonitor = serviceMonitorPulseInfo.serviceMonitor;
754 serviceMonitor.destroy();
759 * DO NOT USE THIS FIELD: It will be deprecated when MonitorManager becomes a
760 * FULL FLEDGED SERVICE
763 private static Hashtable<PeerGroupID, MonitorManager> monitorManagers = new Hashtable<PeerGroupID, MonitorManager>();
766 * DO NOT USE THIS METHOD: It will be deprecated when MonitorManager becomes a
767 * FULL FLEDGED SERVICE
770 public static MonitorManager registerMonitorManager(PeerGroup peerGroup) throws JxtaException {
771 PeerGroupID peerGroupID = peerGroup.getPeerGroupID();
772 MonitorManager monitorManager = monitorManagers.get(peerGroupID);
774 if (monitorManager == null) {
775 boolean includeTransports = true;
776 ModuleImplAdvertisement moduleImplAdvertisement = MonitorResources.getReferenceAllPurposeMonitorServiceImplAdvertisement(
779 monitorManager = (MonitorManager) peerGroup.loadModule(MonitorResources.refMonitorServiceSpecID
781 moduleImplAdvertisement);
782 monitorManagers.put(peerGroupID, monitorManager);
784 // FIXME jice@jxta.org - 20021103 : this
785 // monitorManager is not a real group service:
786 // it is being loadModule()'d by another as a
787 // result, it holds a counted reference to the
788 // group. Idealy, we'd need the groupAPI to
789 // offer a means to loadModule() without
790 // making a counted reference, so that group
791 // services can loadModule() things without
792 // preventing group termination. This could be
793 // achieved elegantly by making this only
794 // behaviour available through a weak
795 // GroupInterface. So it would be enough to
796 // obtain a weak interface from one's group
797 // and then use its loadmodule method rather
798 // than that of the strong group interface.
799 // However that's a bit too big a change to be
800 // decided without more carefull
801 // consideration. Instead, we just simulate
802 // it for now: we give to the monitor manager
803 // the real group reference after loadModule
804 // is done, and it discards the strong
805 // interface object that was passed to its
808 monitorManager.setPeerGroup(peerGroup);
810 return monitorManager;
814 * DO NOT USE THIS METHOD: It will be deprecated when MonitorManager becomes a
815 * FULL FLEDGED SERVICE
818 public static void unregisterMonitorManager(PeerGroup peerGroup) {
819 PeerGroupID peerGroupID = peerGroup.getPeerGroupID();
821 monitorManagers.remove(peerGroupID);
824 public static ServiceMonitor getServiceMonitor(PeerGroup peerGroup, ModuleClassID serviceClassID) {
826 PeerGroupID peerGroupID = peerGroup.getPeerGroupID();
827 MonitorManager monitorManager = monitorManagers.get(peerGroupID);
829 return monitorManager.getServiceMonitor(serviceClassID);
830 } catch (Exception e) { // Fix-Me: This is a bit sloppy
831 throw new RuntimeException("Unable to find MonitorManager or MonitorService");