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

org.coos.messaging.routing.GuaranteedDelivery 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 org.coos.messaging.util.Log;
import org.coos.messaging.util.LogFactory;
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.DefaultProcessor;
import org.coos.messaging.util.URIHelper;
import org.coos.messaging.util.UuidGenerator;

import java.util.Hashtable;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Knut Eilif Husa, Tellu AS A guaranteed delivery router processor
 */
public class GuaranteedDelivery extends DefaultProcessor implements RouterProcessor, Service {

	public static final String PARAMETER_CHECK_INTERVAL = "checkInterval";

	private Router router;
	private Map waitingMessages = new ConcurrentHashMap();
	private UuidGenerator uuidGenerator;
	private Timer timer = new Timer();
	private long checkInterval = 0;

	private static final Log logger = LogFactory.getLog(GuaranteedDelivery.class);

	public void setRouter(Router router) {
		this.router = router;
		uuidGenerator = new UuidGenerator(router.getCOOSInstanceName());
	}

	/**
	 * Processes the message
	 * 
	 * @param msg
	 *            the message to be processed
	 */
	public void processMessage(Message msg) throws ProcessorException {
		// check if message has guaranteed delivery enabled
		String gdStr = msg.getHeader(Message.ROBUST_DELIVERY_TIME);
		long gdTime = 0;
		if (gdStr != null) {
			try {
				gdTime = Long.valueOf(gdStr);
			} catch (NumberFormatException e) {
				e.printStackTrace();
			}
		}
		if (gdTime == 0) {
			// no guaranteed delivery, return
			return;
		}
		// get the outgoing link to see if the message is being routed
		if (msg.getMessageContext().getNextLink() != null) {
			// There exists a path to the endpoint, return
			// todo check for receipt in case of retransmission
			return;
		}
		String tId = uuidGenerator.generateId();
		msg.setHeader(Message.TRANSACTION_ID, tId);
		waitingMessages.put(tId, new TimedMessage(System.currentTimeMillis() + gdTime, msg));
		logger.info("Saving message with transactionId: " + tId);
		throw new ProcessorInterruptException();
	}

	@Override
	public void setProperties(Hashtable properties) {
		super.setProperties(properties);
		String measureIntervalStr = (String) properties.get(PARAMETER_CHECK_INTERVAL);
		if (measureIntervalStr != null) {
			checkInterval = Long.parseLong(measureIntervalStr);

		}
	}

	/**
	 * Starts the service
	 * 
	 * @throws Exception
	 *             Exception thrown if starting of service fails
	 */
	public void start() throws Exception {
		String measureIntervalStr = (String) properties.get(PARAMETER_CHECK_INTERVAL);
		if (checkInterval != 0) {
			timer = new Timer();
			timer.schedule(new MessageHandlerTask(), 0, checkInterval);
		}
	}

	/**
	 * Stops the service
	 * 
	 * @throws Exception
	 *             Exception thrown if stopping of service fails
	 */
	public void stop() throws Exception {
		timer.cancel();
	}

	private class TimedMessage {

		public TimedMessage(long time, Message message) {
			this.time = time;
			this.message = message;
		}

		long time;
		Message message;

	}

	private class MessageHandlerTask extends TimerTask {

		/**
		 * The action to be performed by this timer task.
		 */
		public void run() {
			for (TimedMessage tm : waitingMessages.values()) {
				Message msg = tm.message;

				URIHelper helper = new URIHelper(msg.getReceiverEndpointUri());

				String qosClass = msg.getHeader(Message.QOS_CLASS);
				if (qosClass == null) {
					qosClass = router.getDefaultQoSClass();
				}
				Map routingTable = (Map) router.getRoutingTables().get(qosClass);

				String uuid = router.resolveAlias(msg);
				Link link = router.route(uuid, msg, routingTable);

				if (link != null) {
					try {
						String tId = msg.getHeader(Message.TRANSACTION_ID);
						link.processMessage(msg);
						waitingMessages.remove(tId);
						logger.info("Successfully delivered message with transactionId: " + tId + " to :"
								+ link.getDestinationUuid());
					} catch (ProcessorException e) {
						if (System.currentTimeMillis() > tm.time) {
							waitingMessages.remove(msg.getHeader(Message.TRANSACTION_ID));
							router.replyErrorReason(msg, "Guaranteed delivery timed out. No route.");
						}
					}
				} else {
					if (System.currentTimeMillis() > tm.time) {
						waitingMessages.remove(msg.getHeader(Message.TRANSACTION_ID));
						logger.warn("Message timed out: " + msg.getHeader(Message.TRANSACTION_ID));
						router.replyErrorReason(msg, "Guaranteed delivery timed out. No route.");
					}
				}
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy