org.coos.messaging.routing.LatencyAnalyzer Maven / Gradle / Ivy
/**
* COOS - Connected Objects Operating System (www.connectedobjects.org).
*
* Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* You may also contact one of the following for additional information:
* Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
* Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
*/
package org.coos.messaging.routing;
import java.util.Hashtable;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.coos.messaging.Link;
import org.coos.messaging.Message;
import org.coos.messaging.ProcessorException;
import org.coos.messaging.ProcessorInterruptException;
import org.coos.messaging.Service;
import org.coos.messaging.impl.DefaultMessage;
import org.coos.messaging.impl.DefaultProcessor;
import org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
/**
* @author Knut Eilif Husa, Tellu AS
*
*/
public class LatencyAnalyzer extends DefaultProcessor implements RouterProcessor, Service {
private static final String MESSAGE_NAME_PING = "pingLatency";
private static final String MESSAGE_NAME_PONG = "pongLatency";
private static final String QOSCLASS_LATENCY = "latency";
private static final String PROPERTY_UPDATE_COST = "updateCost";
private static final String PROPERTY_MEASURE_INTERVAL = "updateInterval";
private static final String PROPERTY_LATENCY_ANALYZER_NAME = "analyzerName";
private static final Log logger = LogFactory.getLog(LatencyAnalyzer.class);
private String analyzerName = "latencyAnalyzer";
private boolean updateCost = false;
private Router router;
private long samples = 0;
private double meanLatency;
private long measureInterval = 0;
private Timer timer;
private MBeanServer mbs;
ObjectName name;
public void processMessage(Message msg) throws ProcessorException {
if (msg.getHeader(Message.TYPE).equals(Message.TYPE_ANALYZE)) {
Link inLink = msg.getMessageContext().getInBoundLink();
if (msg.getHeader(Message.MESSAGE_NAME).equals(MESSAGE_NAME_PONG)) {
String ts = msg.getHeader(Message.TIME_STAMP);
long latency = (System.currentTimeMillis() - Long.parseLong(ts)) / 2;
logger.debug("latency: " + latency);
if (updateCost) {
inLink.setCost(QOSCLASS_LATENCY, (int) latency);
}
meanLatency = (meanLatency * samples + latency) / (samples + 1);
samples++;
} else if (msg.getHeader(Message.MESSAGE_NAME).equals(MESSAGE_NAME_PING)) {
msg.setHeader(Message.MESSAGE_NAME, MESSAGE_NAME_PONG);
inLink.getChannel().getOutLink().processMessage(msg);
}
// Stop the routing
throw new ProcessorInterruptException();
}
}
public void start() throws Exception {
if (measureInterval != 0) {
timer = new Timer();
timer.schedule(new LatencyAnalyzerTask(), measureInterval);
}
}
@Override
public void setProperties(Hashtable properties) {
super.setProperties(properties);
if (properties.get(PROPERTY_LATENCY_ANALYZER_NAME) != null) {
analyzerName = (String) properties.get(PROPERTY_LATENCY_ANALYZER_NAME);
}
String measureIntervalStr = (String) properties.get(PROPERTY_MEASURE_INTERVAL);
if (measureIntervalStr != null) {
measureInterval = Long.parseLong(measureIntervalStr);
}
if (properties.get(PROPERTY_UPDATE_COST) != null
&& ((String) properties.get(PROPERTY_UPDATE_COST)).equalsIgnoreCase("true")) {
updateCost = true;
}
}
public void stop() throws Exception {
if (timer != null) {
timer.cancel();
}
}
public void setRouter(Router router) {
this.router = router;
}
private class LatencyAnalyzerTask extends TimerTask {
public void run() {
Map links = router.getLinks();
for (Link link : links.values()) {
// todo check if latency shall be metered and updated for this
// link, xml config
Message ping = new DefaultMessage();
ping.setHeader(Message.TYPE, Message.TYPE_ANALYZE);
ping.setHeader(Message.MESSAGE_NAME, MESSAGE_NAME_PING);
ping.setHeader(Message.TIME_STAMP, String.valueOf(System.currentTimeMillis()));
try {
if (link.getChannel() != null) {
link.processMessage(ping);
}
} catch (ProcessorException e) {
e.printStackTrace();
}
}
try {
timer.schedule(new LatencyAnalyzerTask(), measureInterval);
} catch (IllegalStateException e) {
// Timer was cancelled but we started to run.
}
}
}
public double getRoundTripLatency() {
return meanLatency;
}
}