au.edu.uts.eng.remotelabs.schedserver.rigprovider.impl.StatusTimeoutChecker.java Source code

Java tutorial

Introduction

Here is the source code for au.edu.uts.eng.remotelabs.schedserver.rigprovider.impl.StatusTimeoutChecker.java

Source

/**
 * SAHARA Scheduling Server
 *
 * Schedules and assigns local laboratory rigs.
 *
 * @license See LICENSE in the top level directory for complete license terms.
 *
 * Copyright (c) 2010, University of Technology, Sydney
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 *  * 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.
 *  * Neither the name of the University of Technology, Sydney nor the names 
 *    of its contributors may be used to endorse or promote products derived from 
 *    this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS 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 THE COPYRIGHT HOLDER OR 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.
 *
 * @author Michael Diponio (mdiponio)
 * @date 21st February 2010
 */
package au.edu.uts.eng.remotelabs.schedserver.rigprovider.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.criterion.Restrictions;

import au.edu.uts.eng.remotelabs.schedserver.dataaccess.DataAccessActivator;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.dao.RigLogDao;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.Rig;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.Session;
import au.edu.uts.eng.remotelabs.schedserver.logger.Logger;
import au.edu.uts.eng.remotelabs.schedserver.logger.LoggerActivator;
import au.edu.uts.eng.remotelabs.schedserver.rigprovider.RigEventListener;
import au.edu.uts.eng.remotelabs.schedserver.rigprovider.RigEventListener.RigStateChangeEvent;
import au.edu.uts.eng.remotelabs.schedserver.rigprovider.RigProviderActivator;

/**
 * Puts rigs offline if they have not provided a status update with the
 * configured rig timeout period. For a rig to be considered timeout, the
 * following conditions must hold true:
 * <ul>
 *  <li>The rig must be managed.</li>
 *  <li>The rig must be active.</li>
 *  <li>The rig must be online.</li>
 *  <li>The rig must not be in session.</li>
 *  <li>The last time the rig provided a status update must be before the
 *  current time minus the timeout period.</li>
 * </ul>
 * If the above is true for a rig, the rig is set to be offline, with
 * the offline reason as 'Timed out' and set to inactive.
 * <br />
 * The time out period may be configured with the <tt>Rig_Timeout_Period</tt>
 * which specifies the time out period in seconds. The default timeout period
 * is 300 seconds.
 */
public class StatusTimeoutChecker implements Runnable {
    /** The default timeout in minutes. */
    public static final int DEFAULT_TIMEOUT = 100;

    /** The period a rig must provide a status update, otherwise the rig
     *  is put offline. */
    private int timeout;

    /** Logger. */
    private Logger logger;

    /**
     * Constructor which loads the time out period from configuration.
     */
    public StatusTimeoutChecker() {
        this.logger = LoggerActivator.getLogger();

        String tmStr = RigProviderActivator.getConfigurationProperty("Rig_Timeout_Period",
                String.valueOf(StatusTimeoutChecker.DEFAULT_TIMEOUT));
        try {
            this.timeout = Integer.parseInt(tmStr);
            this.logger.info("Rig time out for providing a status update is " + this.timeout + " seconds.");

        } catch (NumberFormatException nfe) {
            this.timeout = StatusTimeoutChecker.DEFAULT_TIMEOUT;
            this.logger.debug("Configured rig time out period '" + tmStr
                    + "' is not valid, using the default value " + " of " + this.timeout + " seconds.");
        }
    }

    /**
     * Constructor.
     * 
     * @param tm timeout period in seconds
     */
    public StatusTimeoutChecker(int tm) {
        this.logger = LoggerActivator.getLogger();

        this.timeout = tm;
        this.logger.info("Rig time out for providing a status update is " + this.timeout + " seconds.");
    }

    @Override
    @SuppressWarnings("unchecked")
    public void run() {
        org.hibernate.Session db = null;
        try {
            db = DataAccessActivator.getNewSession();
            if (db == null) {
                this.logger.error("Unable to obtain a database session for the rig status time out checker. "
                        + "Ensure the database is running and configured database details are correct.");
                return;
            }

            RigLogDao rigLogDao = new RigLogDao(db);

            /* Get all the rigs that have timed out. */
            List<Rig> timedOut = db.createCriteria(Rig.class).add(Restrictions.eq("managed", true)) // Unmanaged rigs need not provide a status update
                    .add(Restrictions.eq("active", true)).add(Restrictions.lt("lastUpdateTimestamp",
                            new Date(System.currentTimeMillis() - this.timeout * 1000)))
                    .list();

            for (Rig rig : timedOut) {
                Calendar cal = Calendar.getInstance();
                cal.setTime(rig.getLastUpdateTimestamp());

                this.logger.warn("Rig " + rig.getName() + " has timed out with last status update received at "
                        + cal.get(Calendar.DATE) + '/' + (cal.get(Calendar.MONTH) + 1) + '/'
                        + cal.get(Calendar.YEAR) + " - " + cal.get(Calendar.HOUR_OF_DAY) + ':'
                        + cal.get(Calendar.MINUTE) + ':' + cal.get(Calendar.SECOND) + ". Making rig inactive.");

                if (rig.getSession() != null) {
                    this.logger.warn("Timed out rig " + rig.getName() + " is in session so the session is being "
                            + "terminated.");
                    Session ses = rig.getSession();

                    ses.setActive(false);
                    ses.setRemovalReason("Rig timed out");
                    ses.setRemovalTime(new Date());

                    rig.setInSession(false);
                    rig.setSession(null);
                }

                rig.setActive(false);
                rig.setOnline(false);
                rig.setOfflineReason("Timed out.");

                rigLogDao.addUnRegisteredLog(rig, "Timed out.");

                db.beginTransaction();
                db.flush();
                db.getTransaction().commit();

                /* Fire a notification the rig has gone offline. */
                for (RigEventListener list : RigProviderActivator.getRigEventListeners()) {
                    list.eventOccurred(RigStateChangeEvent.OFFLINE, rig, db);
                }
            }
        } catch (HibernateException hex) {
            this.logger.error("Failed to query database to check rig status. Exception: " + hex.getClass().getName()
                    + ", Message:" + hex.getMessage());

            if (db != null && db.getTransaction() != null) {
                try {
                    db.getTransaction().rollback();
                } catch (HibernateException ex) {
                    this.logger.error("Exception rolling back up status timeout transaction (Exception: "
                            + ex.getClass().getName() + "," + " Message: " + ex.getMessage() + ").");
                }
            }
        } finally {
            try {
                if (db != null)
                    db.close();
            } catch (HibernateException ex) {
                this.logger.error("Exception cleaning up database session (Exception: " + ex.getClass().getName()
                        + "," + " Message: " + ex.getMessage() + ").");
            }
        }
    }
}