/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@ow2.org
 *
 * 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 2.1 of the License, or any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.resource.internal.pool.lib;

import org.ow2.jonas.lib.util.Log;
import org.ow2.jonas.resource.internal.pool.Pool;

import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.BasicLevel;

/**
 * Keeps pool as small as possible (after conn's has reached MaxAge)
 * @author Eric Hardesty
 * Contributor(s):
 */
public class HArrayPoolMonitor extends Thread {

    /**
     * Pool that is being monitored
     */
    private Pool pool;
    /**
     * Main logger
     */
    private Logger logger = null;

    /**
     * Default adjust period of 30 sec
     */
    private long adjustPeriod = 30 * 1000L;  // default = 30s in ms
    /**
     * Default sampling period of 60 sec
     */
    private long samplingPeriod = 60 * 1000L;  // default = 60s in ms
    /**
     * Default validation period of 10 min
     */
    private long validationPeriod = 10 * 60 * 1000L;  //default = 10 min in ms

    /**
     * Adjust period
     */
    private long adjustTime = 0;
    /**
     * Sampling time
     */
    private long samplingTime = 0;
    /**
     * Validation time
     */
    private long validationTime = 0;

    private boolean stopped = false;
    /**
     * Pool monitor constructor
     * @param pool Pool to monitor
     */
    public HArrayPoolMonitor(Pool pool) {
        super("HArrayPoolMonitor");
        setDaemon(true);
        this.pool = pool;
        logger = Log.getLogger(Log.JONAS_JCA_PREFIX);
    }

    /**
     * Set the adjust period.
     * Moreover, this can be reconfigured later.
     * @param sec adjust period in sec.
     */
    public void setAdjustPeriod(int sec) {
        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, " to " + sec);
        }
        adjustPeriod = sec * 1000L;
    }

    /**
     * Set the sampling period.
     * Moreover, this can be reconfigured later.
     * @param sec sampling period in sec.
     */
    public void setSamplingPeriod(int sec) {
        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, " to " + sec);
        }
        samplingPeriod = sec * 1000L;
    }

    /**
     * Set the validation period.
     * Moreover, this can be reconfigured later.
     * @param sec validation period in sec.
     */
    public void setValidationPeriod(int sec) {
        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, " to " + sec);
        }
        validationPeriod = sec * 1000L;
    }

    /**
     * Stop this thread.
     */
    public void stopit() {
        stopped  = true;
    }

    /**
     * Run the array pool monitor
     */
    public void run() {
        long timeout;
        resetTimes();
        while (!stopped) {
            timeout = adjustTime;
            if (samplingTime < timeout) {
                timeout = samplingTime;
            }
            if (validationTime < timeout) {
                timeout = validationTime;
            }
            try {
                sleep(timeout);
                adjustTime -= timeout;
                samplingTime -= timeout;
                validationTime -= timeout;
                if (adjustTime <= 0) {
                    pool.adjust();
                    adjustTime = adjustPeriod;
                }
                if (samplingTime <= 0) {
                    pool.sampling();
                    samplingTime = samplingPeriod;
                }
                if (validationTime <= 0) {
                    pool.validateMCs();
                    validationTime = validationPeriod;
                }
            } catch (NullPointerException e) {
                logger.log(BasicLevel.ERROR, "HArrayPoolMonitor NPE:" + e);
                e.printStackTrace();
                resetTimes();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "HArrayPoolMonitor error:" + e);
                e.printStackTrace();
                resetTimes();
            }
        }
    }

    private void resetTimes() {
        adjustTime = adjustPeriod;
        samplingTime = samplingPeriod;
        validationTime = validationPeriod;
    }
}
