package org.ovirt.engine.ui.uicommonweb.models; import java.util.logging.Logger; import org.ovirt.engine.ui.uicommonweb.Configurator; import org.ovirt.engine.ui.uicommonweb.TypeResolver; import org.ovirt.engine.ui.uicommonweb.models.GridTimerStateChangeEvent.GridTimerStateChangeEventHandler; import org.ovirt.engine.ui.uicommonweb.models.GridTimerStateChangeEvent.HasGridTimerStateChangeEventHandlers; import org.ovirt.engine.ui.uicompat.ConstantsManager; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.GwtEvent; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Timer; /** * The GridTimer holds information about the current refresh rate. * The GridTimer can work in one of two modes: * 1. Normal mode - in this mode the rate will be determined by selecting one out * of 5 intervals (5,10,20,30,60 sec). * 2. Fast-Forward mode - in this mode the timer enters a cycle: * - 3 fast (2 sec) refresh rotations * - 30 medium (4 sec) refresh rotations * - 3 slow (8 sec) refresh rotations * After completing the cycle the GridTimer will return to Normal mode (with the last set * refresh rate). This mode is triggered by the fastForward() method. each call reset the cycle * to the start point. */ public abstract class GridTimer extends Timer implements HasGridTimerStateChangeEventHandlers { private enum RATE { FAST { @Override int getInterval() { return 500; } @Override int getRepetitions() { return 4; } @Override public String toString() { return "Fast"; //$NON-NLS-1$ } }, MEDIUM { @Override int getInterval() { return 1000; } @Override int getRepetitions() { return 3; } @Override public String toString() { return "Medium"; //$NON-NLS-1$ } }, NORMAL { @Override int getInterval() { return -1; } @Override int getRepetitions() { // this interval is set dynamically return -1; } @Override public String toString() { return "Normal"; //$NON-NLS-1$ } }, SLOW { @Override int getInterval() { return 2000; } @Override int getRepetitions() { return 2; } @Override public String toString() { return "Slow"; //$NON-NLS-1$ } }; abstract int getInterval(); abstract int getRepetitions(); } public static final int DEFAULT_NORMAL_RATE = ((Configurator) TypeResolver.getInstance() .resolve(Configurator.class)).getPollingTimerInterval(); private static final Logger logger = Logger.getLogger(GridTimer.class.getName()); private int currentRate = 0; private final EventBus eventBus; private final String name; private boolean active; private boolean paused; private int normalInterval = DEFAULT_NORMAL_RATE; private final RATE[] rateCycle = { RATE.NORMAL, RATE.FAST, RATE.MEDIUM, RATE.SLOW }; private int repetitions; /** * Constructor. * @param name The name of the timer * @param eventBus The GWT event bus. */ public GridTimer(String name, final EventBus eventBus) { assert eventBus != null : "EventBus cannot be null"; //$NON-NLS-1$ this.name = name; this.eventBus = eventBus; } @Override public HandlerRegistration addGridTimerStateChangeEventHandler(GridTimerStateChangeEventHandler handler) { return eventBus.addHandler(GridTimerStateChangeEvent.getType(), handler); } /** * This method will be called when a timer fires. Override it to implement the timer's logic. */ public abstract void execute(); /** * Speed Up the search interval for a limited number of repetitions. */ public void fastForward() { logger.fine("GridTimer[" + name + "].fastForward()"); //$NON-NLS-1$ //$NON-NLS-2$ if (isFastForwarding()) { // there is already a fast forward running - reset to normal and start over reset(); } cycleRate(); } @Override public void fireEvent(GwtEvent<?> event) { eventBus.fireEvent(event); } /** * Get the refresh rate. * @return refresh rate in milliseconds. */ public int getRefreshRate() { RATE rate = rateCycle[currentRate]; return rate == RATE.NORMAL ? normalInterval : rate.getInterval(); } /** * Is this GridTimer currently running on Fast-Forward mode. * @return - true if running in Fast-Forward mode. false otherwise. */ public boolean isFastForwarding() { return rateCycle[currentRate] != RATE.NORMAL; } @Override public final void run() { logger.fine("GridTimer[" + name + "].run() called"); //$NON-NLS-1$ //$NON-NLS-2$ if (repetitions > 0) { repetitions--; } else if (repetitions == 0) { cycleRate(); } logger.fine("GridTimer[" + name + "] Executing! Current Rate: " //$NON-NLS-1$ //$NON-NLS-2$ + rateCycle[currentRate] + ":" + getRefreshRate() //$NON-NLS-1$ + " Reps: " //$NON-NLS-1$ + repetitions); execute(); } /** * Set the refresh rate and fire an event that the state of the timer has changed. * * @param interval in seconds */ public void setRefreshRate(int interval) { setRefreshRate(interval, true); } /** * Set the refresh rate and fire an event that the state of the timer has changed. * * @param interval in seconds */ public void setRefreshRate(int interval, boolean fireEvent) { if (getRefreshRate() == interval) { return; } logger.fine("GridTimer[" + name + "]: Refresh Rate set to: " + interval); //$NON-NLS-1$ //$NON-NLS-2$ // set the NORMAL interval normalInterval = interval; if (fireEvent) { GridTimerStateChangeEvent.fire(this, getRefreshRate()); } } /** * Start an inactive timer. */ public void start() { logger.fine("GridTimer[" + name + "].start()"); //$NON-NLS-1$ //$NON-NLS-2$ active = true; scheduleRepeating(getRefreshRate()); } /** * Stop an active timer. */ public void stop() { logger.fine("GridTimer[" + name + "].stop()"); //$NON-NLS-1$ //$NON-NLS-2$ active = false; doStop(); } /** * Pause an active timer. */ public void pause() { logger.fine("GridTimer[" + name + "].pause()"); //$NON-NLS-1$ //$NON-NLS-2$ if (active) { paused = true; doStop(); } } /** * Resume a paused timer, will NOT start an inactive timer. */ public void resume() { logger.fine("GridTimer[" + name + "].resume()"); //$NON-NLS-1$ //$NON-NLS-2$ if (active) { paused = false; start(); } } /** * Is the timer paused? * @return {@code true} if paused, {@code false} otherwise */ public boolean isPaused() { return paused; } /** * Is the timer active? * @return {@code true} if active, {@code false} otherwise */ public boolean isActive() { return active; } public String getTimerRefreshStatus() { logger.fine((isActive() ? "Refresh Status: Active(" : "Inactive(") + (isPaused() ? "paused)" : "running)") + ":" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + " Rate: " + rateCycle[currentRate] + "(" + getRefreshRate() / 1000 + " sec)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$); } return ConstantsManager.getInstance().getMessages().refreshInterval(getRefreshRate() / 1000); } /** * Stop the timer, fire event with the new refresh rate. */ private void doStop() { reset(); cancel(); } /** * Cycle the current refresh rate. The rate goes from FAST, MEDIUM, SLOW, NORMAL. Each rate has a number of * repetitions associated with it. Once those repetitions for that rate are exhausted the rate is switched to * the next rate until the rate is normal. */ private void cycleRate() { currentRate = (currentRate + 1) % rateCycle.length; RATE rate = rateCycle[currentRate]; repetitions = rate.getRepetitions(); logger.fine("GridTimer[" + name + "] Rate Cycled: Current Rate: " + rate //$NON-NLS-1$ //$NON-NLS-2$ + " Reps: " + repetitions + " Interval: " //$NON-NLS-1$ //$NON-NLS-2$ + rate.getInterval()); cancel(); start(); if (rate == RATE.NORMAL) { GridTimerStateChangeEvent.fire(this, getRefreshRate()); } } /** * Reset the GridTimer rate back to normal. */ private void reset() { // reset rate to NORMAL currentRate = 0; repetitions = RATE.NORMAL.getRepetitions(); } }