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

org.restcomm.timers.TimerTask Maven / Gradle / Ivy

There is a newer version: 7.0.0.16
Show newest version
/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2016, Telestax Inc and individual contributors
 * by the @authors tag.
 *
 * This program is free software: you can redistribute it and/or modify
 * under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see 
 */

package org.restcomm.timers;

import java.util.concurrent.ScheduledFuture;

import org.apache.log4j.Logger;

/**
 * The base class to implement a task to be scheduled and executed by an {@link FaultTolerantScheduler}.
 * 
 * @author martins
 *
 */
public abstract class TimerTask implements Runnable {
	/**
	 * 
	 */
	private static final Logger logger = Logger.getLogger(TimerTask.class);
	/**
	 * the data associated with the task
	 */
	private final TimerTaskData data;
	
	/**
	 * the schedule future object that returns from the task scheduling
	 */
	
	private ScheduledFuture scheduledFuture;
	
	/**
	 * the tx action to set the timer when the tx commits, not used in a non tx environment 
	 */
	private SetTimerAfterTxCommitRunnable action;
	
	/**
	 * the scheduler to remove the task locally and from the cluster once it has fired
	 */
	private FaultTolerantScheduler scheduler;
	
	/**
	 * if true the task is removed from the scheduler when it is executed the last time
	 */
	protected boolean autoRemoval = true;
	
	/**
	 * 
	 * @param data
	 */
	public TimerTask(TimerTaskData data) {
		this.data = data;
	}
	
	/**
	 * Retrieves the data associated with the task.
	 * @return
	 */
	public TimerTaskData getData() {
		return data;
	}
	
	/**
	 * Retrieves the tx action to set the timer when the tx commits, not used in a non tx environment.
	 * @return
	 */
	protected SetTimerAfterTxCommitRunnable getSetTimerTransactionalAction() {
		return action;
	}

	/**
	 * Sets the tx action to set the timer when the tx commits, not used in a non tx environment.
	 * @param action
	 */
	void setSetTimerTransactionalAction(
			SetTimerAfterTxCommitRunnable action) {
		this.action = action;
	}

	/**
	 * Retrieves the schedule future object that returns from the task scheduling.
	 * @return
	 */
	public ScheduledFuture getScheduledFuture() {
		return scheduledFuture;
	}
	
	/**
	 * Sets the schedule future object that returns from the task scheduling.
	 * @param scheduledFuture
	 */
	protected void setScheduledFuture(ScheduledFuture scheduledFuture) {
		this.scheduledFuture = scheduledFuture;
		// it may happen that the cancel() is invoked before this is 
		// invoked 
		if (cancel) {
			this.scheduledFuture.cancel(false);
		}
	}

	private transient boolean cancel; 
	
	/**
	 * Cancels the execution of the task.
	 * Note, this doesn't remove the task from the scheduler.
	 */
	protected void cancel() {
		cancel = true;
		if (scheduledFuture != null) {
			scheduledFuture.cancel(false);
		}
	}
	
	public final void run() {		
		// Fix for Issue 1612 : Restcomm Cluster does not remove non recurring tasks when they fired
		if(data.getPeriod() < 0 && autoRemoval) {
			if (logger.isDebugEnabled()) {
				logger.debug("Task with id "
						+ data.getTaskID() + " is not recurring, so removing it locally and in the cluster");
			}
			// once the task has been fired, remove it locally and in the cluster, only if it is a non recurring task
			removeFromScheduler();
		} else {
			if (logger.isDebugEnabled()) {
				logger.debug("Task with id "
						+ data.getTaskID() + " is recurring, not removing it locally nor in the cluster");
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Firing Timer with id "
					+ data.getTaskID());
		}
		runTask();
	}
	
	/**
	 * Self removal from the scheduler. Note that this method does not cancel the task execution.
	 */
	protected void removeFromScheduler() {
		scheduler.remove(data.getTaskID(),true);
	}
	
	/**
	 * The method executed by the scheduler
	 */
	public abstract void runTask();
	
	/**
	 * Invoked before a task is recovered, after fail over, by default simply adjust start time if it is a periodic timer.
	 */
	public void beforeRecover() {
		if (data.getPeriod() > 0) {			
			final long now = System.currentTimeMillis();
			long startTime = data.getStartTime();
			while(startTime <= now) {
				startTime += data.getPeriod();
				data.setStartTime(startTime);				
			}			
			if (logger.isDebugEnabled()) {
				logger.debug("Task with id "
						+ data.getTaskID() + " start time reset to " + data.getStartTime());
			}
		}
	}

	/**
	 * @param scheduler the scheduler to set
	 */
	public void setScheduler(FaultTolerantScheduler scheduler) {
		this.scheduler = scheduler;
	}

	/**
	 * @return the scheduler
	 */
	public FaultTolerantScheduler getScheduler() {
		return scheduler;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy