/*
* 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);
}
}