/* * Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved. * * The Sun Project JXTA(TM) Software License * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by Sun Microsystems, Inc. for JXTA(TM) technology." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must * not be used to endorse or promote products derived from this software * without prior written permission. For written permission, please contact * Project JXTA at http://www.jxta.org. * * 5. Products derived from this software may not be called "JXTA", nor may * "JXTA" appear in their name, without prior written permission of Sun. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * JXTA is a registered trademark of Sun Microsystems, Inc. in the United * States and other countries. * * Please see the license information page at : * <http://www.jxta.org/project/www/license.html> for instructions on use of * the license in source files. * * ==================================================================== * * This software consists of voluntary contributions made by many individuals * on behalf of Project JXTA. For more information on Project JXTA, please see * http://www.jxta.org. * * This license is based on the BSD license adopted by the Apache Foundation. */ package net.jxta.impl.peer; import java.util.Hashtable; import java.util.Iterator; import java.util.Random; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import net.jxta.document.Element; import net.jxta.exception.PeerGroupException; import net.jxta.impl.util.threads.SelfCancellingTask; import net.jxta.impl.util.threads.TaskManager; import net.jxta.logging.Logging; import net.jxta.meter.MonitorEvent; import net.jxta.meter.MonitorException; import net.jxta.meter.MonitorFilter; import net.jxta.meter.MonitorFilterException; import net.jxta.meter.MonitorListener; import net.jxta.meter.MonitorReport; import net.jxta.meter.MonitorResources; import net.jxta.meter.PeerMonitorInfo; import net.jxta.meter.PeerMonitorInfoEvent; import net.jxta.meter.PeerMonitorInfoListener; import net.jxta.meter.ServiceMonitorFilter; import net.jxta.peer.PeerID; import net.jxta.peer.PeerInfoService; import net.jxta.peergroup.PeerGroup; import net.jxta.peergroup.PeerGroupID; import net.jxta.protocol.PeerInfoQueryMessage; import net.jxta.protocol.PeerInfoResponseMessage; import net.jxta.util.documentSerializable.DocumentSerializableUtilities; import net.jxta.util.documentSerializable.DocumentSerializationException; class RemoteMonitorPeerInfoHandler implements PeerInfoHandler { public static final String MONITOR_HANDLER_NAME = "Monitor"; public static final int MAX_LEASE = 5 * 60 * 1000; // 5 minutes public static final int MIN_LEASE = 60 * 1000; // 1 minute private static final Random rand = new Random(); private final static Logger LOG = Logger.getLogger(RemoteMonitorPeerInfoHandler.class.getName()); private Hashtable<Integer, RequestInfo> requestInfos = new Hashtable<Integer, RequestInfo>(); private Hashtable<Integer, LeaseInfo> leaseInfos = new Hashtable<Integer, LeaseInfo>(); private Hashtable<Integer, Long> timeouts = new Hashtable<Integer, Long>(); private PeerGroup peerGroup; private PeerInfoServiceImpl peerInfoServiceImpl; private ScheduledExecutorService executor; RemoteMonitorPeerInfoHandler(PeerGroup peerGroup, PeerInfoServiceImpl peerInfoServiceImpl) { this.peerGroup = peerGroup; this.peerInfoServiceImpl = peerInfoServiceImpl; this.executor = TaskManager.getTaskManager().getLocalScheduledExecutorService("RemoteMonitorPeerInfoHandler"); } public void stop() { this.executor.shutdownNow(); } private int getNextLeaseId() { int id; synchronized (rand) { id = rand.nextInt(Integer.MAX_VALUE); } return id; } private class RequestInfo { long requestTime = System.currentTimeMillis(); PeerID peerId; int queryId; int origRequestId; MonitorListener monitorListener; PeerMonitorInfoListener peerMonitorInfoListener; long timeout; long validUntil; boolean responseReceived = false; int leaseId; // other guys leaseId. long requestedLease; PeerInfoMessenger peerInfoMessenger; RequestInfo(PeerID peerId, int queryId, MonitorListener monitorListener, long timeout, PeerInfoMessenger peerInfoMessenger) { this(peerId, queryId, timeout, peerInfoMessenger); this.monitorListener = monitorListener; } RequestInfo(PeerID peerId, int queryId, PeerMonitorInfoListener peerMonitorInfoListener, long timeout, PeerInfoMessenger peerInfoMessenger) { this(peerId, queryId, timeout, peerInfoMessenger); this.peerMonitorInfoListener = peerMonitorInfoListener; } RequestInfo(PeerID peerId, int queryId, long timeout, PeerInfoMessenger peerInfoMessenger) { this.peerId = peerId; this.queryId = queryId; this.timeout = timeout; this.peerInfoMessenger = peerInfoMessenger; this.validUntil = System.currentTimeMillis() + timeout; } } private class LeaseInfo { int leaseId; PeerID peerID; // Peer that requested the lease int queryId; // The other guy's query Id MonitorListener monitorListener; long validUntil; boolean listenerAddedToWorldGroup = false; PeerGroup worldGroup; PeerInfoMessenger peerInfoMessenger; LeaseInfo(int leaseId, PeerID peerID, int queryId, MonitorListener monitorListener, long leaseLength, PeerInfoMessenger peerInfoMessenger) { this.leaseId = leaseId; this.peerID = peerID; this.queryId = queryId; this.monitorListener = monitorListener; this.peerInfoMessenger = peerInfoMessenger; validUntil = System.currentTimeMillis() + leaseLength; } } public void getPeerMonitorInfo(final PeerID peerID, PeerMonitorInfoListener peerMonitorInfoListener, long timeout, PeerInfoMessenger peerInfoMessenger) throws MonitorException { int queryId = peerInfoServiceImpl.getNextQueryId(); RemoteMonitorQuery remoteMonitorQuery = RemoteMonitorQuery.createPeerMonitorInfoQuery(); peerInfoMessenger.sendPeerInfoRequest(queryId, peerID, MONITOR_HANDLER_NAME, remoteMonitorQuery); final RequestInfo requestInfo = new RequestInfo(peerID, queryId, peerMonitorInfoListener, timeout, peerInfoMessenger); requestInfos.put(queryId, requestInfo); executor.schedule(new Runnable() { public void run() { if (!requestInfo.responseReceived) { PeerMonitorInfoEvent peerMonitorInfoEvent = new PeerMonitorInfoEvent(peerID, null); requestInfo.peerMonitorInfoListener.peerMonitorInfoNotReceived(peerMonitorInfoEvent); requestInfos.remove(requestInfo.queryId); } } }, timeout, TimeUnit.MILLISECONDS); } public void getCumulativeMonitorReport(PeerID peerID, MonitorFilter monitorFilter, MonitorListener monitorListener, long timeout, PeerInfoMessenger peerInfoMessenger) throws MonitorException { int queryId = peerInfoServiceImpl.getNextQueryId(); RemoteMonitorQuery remoteMonitorQuery = RemoteMonitorQuery.createGetCumulativeReportQuery(monitorFilter); peerInfoMessenger.sendPeerInfoRequest(queryId, peerID, MONITOR_HANDLER_NAME, remoteMonitorQuery); final RequestInfo requestInfo = new RequestInfo(peerID, queryId, monitorListener, timeout, peerInfoMessenger); requestInfos.put(queryId, requestInfo); executor.schedule(new Runnable() { public void run() { if (!requestInfo.responseReceived) { requestInfos.remove(requestInfo.queryId); } } }, timeout, TimeUnit.MILLISECONDS); } public void addRemoteMonitorListener(PeerID peerID, MonitorFilter monitorFilter, long reportRate, boolean includeCumulative, MonitorListener monitorListener, long lease, long timeout, PeerInfoMessenger peerInfoMessenger) throws MonitorException { int queryId = peerInfoServiceImpl.getNextQueryId(); RemoteMonitorQuery remoteMonitorQuery = RemoteMonitorQuery.createRegisterMonitorQuery(includeCumulative, monitorFilter, reportRate, lease); peerInfoMessenger.sendPeerInfoRequest(queryId, peerID, MONITOR_HANDLER_NAME, remoteMonitorQuery); final RequestInfo requestInfo = new RequestInfo(peerID, queryId, monitorListener, timeout, peerInfoMessenger); requestInfo.requestedLease = lease; requestInfos.put(queryId, requestInfo); executor.schedule(new Runnable() { public void run() { if (!requestInfo.responseReceived) { MonitorEvent monitorEvent = MonitorEvent.createFailureEvent(MonitorEvent.TIMEOUT, requestInfo.peerId, requestInfo.queryId); requestInfo.monitorListener.monitorRequestFailed(monitorEvent); requestInfos.remove(requestInfo.queryId); } } }, timeout, TimeUnit.MILLISECONDS); scheduleTimeout(requestInfo); } public void removeRemoteMonitorListener(PeerID peerID, MonitorListener monitorListener, long timeout, PeerInfoMessenger peerInfoMessenger) throws MonitorException { int queryId = peerInfoServiceImpl.getNextQueryId(); RequestInfo oldRequestInfo = null; for (RequestInfo ri : requestInfos.values()) { if (ri.monitorListener == monitorListener) { oldRequestInfo = ri; break; } } if (oldRequestInfo != null) { RemoteMonitorQuery remoteMonitorQuery = RemoteMonitorQuery.createRemoveMonitorListenerQuery(oldRequestInfo.leaseId); peerInfoMessenger.sendPeerInfoRequest(queryId, peerID, MONITOR_HANDLER_NAME, remoteMonitorQuery); final RequestInfo requestInfo = new RequestInfo(peerID, queryId, monitorListener, timeout, peerInfoMessenger); requestInfo.origRequestId = oldRequestInfo.queryId; requestInfos.put(queryId, requestInfo); } final RequestInfo requestInfo = oldRequestInfo; executor.schedule(new Runnable() { public void run() { requestInfos.remove(new Integer(requestInfo.queryId)); } }, timeout, TimeUnit.MILLISECONDS); } public void removeRemoteMonitorListener(MonitorListener monitorListener, long timeout, PeerInfoMessenger peerInfoMessenger) throws MonitorException { for (RequestInfo requestInfo : requestInfos.values()) { if (requestInfo.monitorListener == monitorListener) { removeRemoteMonitorListener(requestInfo.peerId, monitorListener, timeout, peerInfoMessenger); } } } public void processRequest(int queryId, PeerID requestSourceID, PeerInfoQueryMessage peerInfoQueryMessage, Element requestElement, PeerInfoMessenger peerInfoMessenger) { try { RemoteMonitorQuery remoteMonitorQuery = (RemoteMonitorQuery) DocumentSerializableUtilities.getDocumentSerializable(requestElement, RemoteMonitorQuery.class); if (remoteMonitorQuery.isRegisterMonitorQuery()) { handleRegisterMonitorQuery(queryId, requestSourceID, remoteMonitorQuery, peerInfoMessenger); } else if (remoteMonitorQuery.isCumulativeReportQuery()) { handleCumulativeReportQuery(queryId, requestSourceID, remoteMonitorQuery.getMonitorFilter(), peerInfoMessenger); } else if (remoteMonitorQuery.isRemoveMonitorQuery()) { handleRemoveMonitorQuery(queryId, requestSourceID, remoteMonitorQuery, peerInfoMessenger); } else if (remoteMonitorQuery.isPeerMonitorInfoQuery()) { handlePeerMonitorInfoQuery(queryId, requestSourceID, peerInfoMessenger); } else if (remoteMonitorQuery.isLeaseRenewal()) { handleLeaseRenewalQuery(queryId, requestSourceID, remoteMonitorQuery, peerInfoMessenger); } } catch (Exception e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Monitor failed in processQuery", e); } } } public void processResponse(int queryId, PeerInfoResponseMessage peerInfoResponseMessage, Element responseElement, PeerInfoMessenger peerInfoMessenger) { RemoteMonitorResponse remoteMonitorResponse; try { remoteMonitorResponse = (RemoteMonitorResponse) DocumentSerializableUtilities.getDocumentSerializable(responseElement, RemoteMonitorResponse.class); RequestInfo requestInfo = requestInfos.get(new Integer(queryId)); if (requestInfo != null) { requestInfo.responseReceived = true; resetTimeout(requestInfo); if (remoteMonitorResponse.isMonitorRegistered()) { int leaseId = remoteMonitorResponse.getLeaseId(); long leaseLength = remoteMonitorResponse.getLease(); requestInfo.leaseId = leaseId; scheduleLeaseRenewal(requestInfo, leaseLength); } else if (remoteMonitorResponse.isMonitorRemoved()) { requestInfos.remove(new Integer(requestInfo.origRequestId)); requestInfos.remove(new Integer(queryId)); } else if (remoteMonitorResponse.isCumulativeReport() || remoteMonitorResponse.isMonitorReport()) { MonitorReport monitorReport = remoteMonitorResponse.getMonitorReport(); MonitorEvent monitorEvent = MonitorEvent.createRemoteMonitorReportEvent(requestInfo.peerId, requestInfo.queryId, monitorReport); requestInfo.monitorListener.processMonitorReport(monitorEvent); } else if (remoteMonitorResponse.isInvalidFilter()) { MonitorEvent monitorEvent = MonitorEvent.createFailureEvent(MonitorEvent.INVALID_MONITOR_FILTER, requestInfo.peerId, requestInfo.queryId); requestInfo.monitorListener.monitorRequestFailed(monitorEvent); requestInfos.remove(new Integer(queryId)); } else if (remoteMonitorResponse.isInvalidReportRate()) { MonitorEvent monitorEvent = MonitorEvent.createFailureEvent(MonitorEvent.INVALID_REPORT_RATE, requestInfo.peerId, requestInfo.queryId); requestInfo.monitorListener.monitorRequestFailed(monitorEvent); requestInfos.remove(new Integer(queryId)); } else if (remoteMonitorResponse.isMeteringNotSupported()) { MonitorEvent monitorEvent = MonitorEvent.createFailureEvent(MonitorEvent.REFUSED, requestInfo.peerId, requestInfo.queryId); requestInfo.monitorListener.monitorRequestFailed(monitorEvent); requestInfos.remove(new Integer(queryId)); } else if (remoteMonitorResponse.isRequestDenied()) { MonitorEvent monitorEvent = MonitorEvent.createFailureEvent(MonitorEvent.REFUSED, requestInfo.peerId, requestInfo.queryId); requestInfo.monitorListener.monitorRequestFailed(monitorEvent); } else if (remoteMonitorResponse.isPeerMonitorInfo()) { PeerMonitorInfoEvent peerMonitorInfoEvent = new PeerMonitorInfoEvent(requestInfo.peerId, remoteMonitorResponse.getPeerMonitorInfo()); requestInfo.peerMonitorInfoListener.peerMonitorInfoReceived(peerMonitorInfoEvent); requestInfos.remove(new Integer(queryId)); } else if (remoteMonitorResponse.isLeaseRenewed()) { long lease = remoteMonitorResponse.getLease(); int origRequestId = requestInfo.origRequestId; RequestInfo origRequest = requestInfos.get(new Integer(origRequestId)); scheduleLeaseRenewal(origRequest, lease); requestInfos.remove(new Integer(queryId)); } } } catch (DocumentSerializationException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Document Serialization Failed", e); } } } private void resetTimeout(RequestInfo requestInfo) { timeouts.put(requestInfo.queryId, requestInfo.timeout + System.currentTimeMillis()); } private long getTimeout(int queryId) { return timeouts.get(queryId); } private void scheduleTimeout(final RequestInfo requestInfo) { final int queryId = requestInfo.queryId; SelfCancellingTask task = new SelfCancellingTask() { public void execute() { if (requestInfos.containsKey(new Integer(queryId))) { try { if (System.currentTimeMillis() > getTimeout(queryId)) { MonitorEvent monitorEvent = MonitorEvent.createFailureEvent(MonitorEvent.TIMEOUT, requestInfo.peerId, queryId); requestInfo.monitorListener.monitorRequestFailed(monitorEvent); } } catch (Exception e) { //ignored } } else { cancel(); } } }; task.setHandle(executor.scheduleAtFixedRate(task, requestInfo.timeout, requestInfo.timeout, TimeUnit.MILLISECONDS)); } private void scheduleLeaseRenewal(RequestInfo requestInfo, long leaseLength) { long roundTrip = requestInfo.requestTime - System.currentTimeMillis(); long renewTime = leaseLength - roundTrip - 30 * 1000L; // 30s comfort // zone. final int queryId = requestInfo.queryId; if (renewTime > MIN_LEASE) { executor.schedule(new Runnable() { public void run() { try { renewLease(queryId); } catch (Exception e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Lease Renewal Failed", e); } } } }, renewTime, TimeUnit.MILLISECONDS); } } private void handleRegisterMonitorQuery(final int queryId, final PeerID requestSourceID, RemoteMonitorQuery remoteMonitorQuery, final PeerInfoMessenger peerInfoMessenger) { MonitorFilter monitorFilter = remoteMonitorQuery.getMonitorFilter(); long lease = remoteMonitorQuery.getLease(); long reportRate = remoteMonitorQuery.getReportRate(); boolean includeCumulative = remoteMonitorQuery.isIncludeCumulative(); MonitorListener monitorListener = new MonitorListener() { public void processMonitorReport(MonitorEvent monitorEvent) { MonitorReport monitorReport = monitorEvent.getMonitorReport(); try { RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createMonitorReportResponse(queryId, monitorReport); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } catch (Exception e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(e.toString()); } } } public void monitorReportingCancelled(MonitorEvent monitorEvent) { throw new RuntimeException("METHOD NOT IMPLEMENTED"); } public void monitorRequestFailed(MonitorEvent monitorEvent) { throw new RuntimeException("METHOD NOT IMPLEMENTED"); } }; int leaseId = getNextLeaseId(); final LeaseInfo leaseInfo = new LeaseInfo(leaseId, requestSourceID, queryId, monitorListener, lease, peerInfoMessenger); long leaseTime = getLeaseTime(lease); setupLeaseTimeout(leaseInfo.leaseId, leaseTime); try { /* * Currently we can neither ask peers in the netgroup for transport * metrics, nor discover peers in the world group. Therefore we're * asking peers in the netgroup to send TransportMetrics, but that * peer is actually attaching the MonitorFilter to it's WorldGroup * peer. */ for (Iterator i = monitorFilter.getServiceMonitorFilters(); i.hasNext();) { ServiceMonitorFilter serviceMonitorFilter = (ServiceMonitorFilter) i.next(); if (serviceMonitorFilter.getModuleClassID().equals(MonitorResources.transportServiceMonitorClassID)) { try { MonitorFilter worldGroupFilter = new MonitorFilter("worldGroupFilter"); worldGroupFilter.addServiceMonitorFilter(serviceMonitorFilter); i.remove(); PeerGroup worldGroup = peerGroup.newGroup(PeerGroupID.worldPeerGroupID); PeerInfoService worldService = worldGroup.getPeerInfoService(); worldService.addMonitorListener(worldGroupFilter, remoteMonitorQuery.getReportRate(), includeCumulative, monitorListener); leaseInfo.listenerAddedToWorldGroup = true; leaseInfo.worldGroup = worldGroup; } catch (PeerGroupException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(e.toString()); } } } } if (monitorFilter.getServiceMonitorFilterCount() > 0) { peerInfoServiceImpl.addMonitorListener(monitorFilter, reportRate, includeCumulative, monitorListener); } leaseInfos.put(leaseId, leaseInfo); RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createMonitorRegisteredResponse(queryId, leaseId, leaseTime); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } catch (MonitorFilterException e) { RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createInvalidFilterResponse(queryId); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } catch (MonitorException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(e.toString()); } } } private void handleRemoveMonitorQuery(int queryId, PeerID requestSourceID, RemoteMonitorQuery remoteMonitorQuery, PeerInfoMessenger peerInfoMessenger) { try { int leaseId = remoteMonitorQuery.getLeaseId(); LeaseInfo leaseInfo = leaseInfos.get(new Integer(leaseId)); if (leaseInfo != null) { MonitorListener monitorListener = leaseInfo.monitorListener; peerInfoServiceImpl.removeMonitorListener(monitorListener); if (leaseInfo.listenerAddedToWorldGroup) { PeerInfoService peerInfoService = leaseInfo.worldGroup.getPeerInfoService(); peerInfoService.removeMonitorListener(monitorListener); } RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createMonitorRemovedResponse(queryId); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } } catch (MonitorException e) { // Currently not thrown by MonitorManager.removeMonitorListener() if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(e.toString()); } } } private void handleCumulativeReportQuery(int queryId, PeerID requestSourceID, MonitorFilter monitorFilter, PeerInfoMessenger peerInfoMessenger) throws MonitorException, DocumentSerializationException { MonitorReport monitorReport = peerInfoServiceImpl.getCumulativeMonitorReport(monitorFilter); RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createCumulativeReportResponse(queryId, monitorReport); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } private void handlePeerMonitorInfoQuery(int queryId, PeerID requestSourceID, PeerInfoMessenger peerInfoMessenger) throws DocumentSerializationException { // FIX-ME: /* Asking the NetGroup Peer won't tell me if it supports transport * monitoring or not, but asking the world group guy gives me * everything I need because as currently implemented you can't turn * monitoring on or off at the PeerGroup level, only the device level. */ try { PeerGroup worldGroup = peerGroup.newGroup(PeerGroupID.worldPeerGroupID); PeerInfoService worldService = worldGroup.getPeerInfoService(); PeerMonitorInfo peerMonitorInfo = worldService.getPeerMonitorInfo(); RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createPeerMonitorInfoResponse(queryId, peerMonitorInfo); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } catch (PeerGroupException e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.fine(e.toString()); } } } private void handleLeaseRenewalQuery(int queryId, PeerID requestSourceID, RemoteMonitorQuery remoteMonitorQuery, PeerInfoMessenger peerInfoMessenger) throws DocumentSerializationException { int leaseId = remoteMonitorQuery.getLeaseId(); LeaseInfo leaseInfo = leaseInfos.get(new Integer(leaseId)); if (leaseInfo != null) { long reqLease = remoteMonitorQuery.getLease(); long lease = getLeaseTime(reqLease); leaseInfo.validUntil = System.currentTimeMillis() + lease; setupLeaseTimeout(leaseInfo.leaseId, lease); RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createLeaseRenewedResponse(queryId, leaseInfo.leaseId, lease); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } else { RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createDeniedResponse(queryId); peerInfoMessenger.sendPeerInfoResponse(queryId, requestSourceID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } } long getLeaseTime(long requestedLease) { long leaseTime = requestedLease < MAX_LEASE ? requestedLease : MAX_LEASE; leaseTime = leaseTime > MIN_LEASE ? leaseTime : MIN_LEASE; return leaseTime; } private void cancelLease(LeaseInfo leaseInfo) throws MonitorException, DocumentSerializationException { if (leaseInfo.listenerAddedToWorldGroup) { leaseInfo.worldGroup.getPeerInfoService().removeMonitorListener(leaseInfo.monitorListener); } RemoteMonitorResponse remoteMonitorResponse = RemoteMonitorResponse.createLeaseEndedResponse(leaseInfo.queryId, leaseInfo.leaseId); leaseInfo.peerInfoMessenger.sendPeerInfoResponse(leaseInfo.queryId, leaseInfo.peerID, MONITOR_HANDLER_NAME, remoteMonitorResponse); } private void renewLease(int queryId) { try { RequestInfo requestInfo = requestInfos.get(new Integer(queryId)); if (requestInfo != null) { int renewalQueryId = peerInfoServiceImpl.getNextQueryId(); PeerID peerID = requestInfo.peerId; long timeout = requestInfo.timeout; RemoteMonitorQuery remoteMonitorQuery = RemoteMonitorQuery.createLeaseRenewalQuery(requestInfo.leaseId, requestInfo.requestedLease); requestInfo.peerInfoMessenger.sendPeerInfoRequest(queryId, peerID, MONITOR_HANDLER_NAME, remoteMonitorQuery); final RequestInfo renewalRequestInfo = new RequestInfo(peerID, queryId, timeout, requestInfo.peerInfoMessenger); renewalRequestInfo.requestedLease = requestInfo.requestedLease; renewalRequestInfo.origRequestId = queryId; requestInfos.put(renewalQueryId, renewalRequestInfo); } } catch (Exception e) { if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "error while attempting Monitor lease renewal", e); } } } private void setupLeaseTimeout(final int leaseId, long lease) { executor.schedule(new Runnable() { public void run() { LeaseInfo leaseInfo = leaseInfos.get(new Integer(leaseId)); if (leaseInfo != null) { long currentTime = System.currentTimeMillis(); if (leaseInfo.validUntil <= currentTime) { try { cancelLease(leaseInfo); } catch (Exception e) { // ignored } finally { leaseInfos.remove(leaseInfo.queryId); } } } } }, lease, TimeUnit.MILLISECONDS); } }