All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.messaging.routing.LatencyAnalyzer Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/**
 * 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;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy