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

org.eclipse.jetty.io.IdleTimeout Maven / Gradle / Ivy

There is a newer version: 12.1.0.alpha0
Show newest version
//
//  ========================================================================
//  Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.io;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;

/**
 * An Abstract implementation of an Idle Timeout.
 * 

* This implementation is optimised that timeout operations are not cancelled on * every operation. Rather timeout are allowed to expire and a check is then made * to see when the last operation took place. If the idle timeout has not expired, * the timeout is rescheduled for the earliest possible time a timeout could occur. */ public abstract class IdleTimeout { private static final Logger LOG = Log.getLogger(IdleTimeout.class); private final Scheduler _scheduler; private final AtomicReference _timeout = new AtomicReference<>(); private volatile long _idleTimeout; private volatile long _idleTimestamp = System.nanoTime(); /** * @param scheduler A scheduler used to schedule checks for the idle timeout. */ public IdleTimeout(Scheduler scheduler) { _scheduler = scheduler; } public Scheduler getScheduler() { return _scheduler; } /** * @return the period of time, in milliseconds, that this object was idle */ public long getIdleFor() { return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - _idleTimestamp); } /** * @return the idle timeout in milliseconds * @see #setIdleTimeout(long) */ public long getIdleTimeout() { return _idleTimeout; } /** *

Sets the idle timeout in milliseconds.

*

A value that is less than or zero disables the idle timeout checks.

* * @param idleTimeout the idle timeout in milliseconds * @see #getIdleTimeout() */ public void setIdleTimeout(long idleTimeout) { long old = _idleTimeout; _idleTimeout = idleTimeout; // Do we have an old timeout if (old > 0) { // if the old was less than or equal to the new timeout, then nothing more to do if (old <= idleTimeout) return; // old timeout is too long, so cancel it. deactivate(); } // If we have a new timeout, then check and reschedule if (isOpen()) activate(); } /** * This method should be called when non-idle activity has taken place. */ public void notIdle() { _idleTimestamp = System.nanoTime(); } private void idleCheck() { long idleLeft = checkIdleTimeout(); if (idleLeft >= 0) scheduleIdleTimeout(idleLeft > 0 ? idleLeft : getIdleTimeout()); } private void scheduleIdleTimeout(long delay) { Scheduler.Task newTimeout = null; if (isOpen() && delay > 0 && _scheduler != null) newTimeout = _scheduler.schedule(this::idleCheck, delay, TimeUnit.MILLISECONDS); Scheduler.Task oldTimeout = _timeout.getAndSet(newTimeout); if (oldTimeout != null) oldTimeout.cancel(); } public void onOpen() { activate(); } private void activate() { if (_idleTimeout > 0) idleCheck(); } public void onClose() { deactivate(); } private void deactivate() { Scheduler.Task oldTimeout = _timeout.getAndSet(null); if (oldTimeout != null) oldTimeout.cancel(); } protected long checkIdleTimeout() { if (isOpen()) { long idleTimestamp = _idleTimestamp; long idleElapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - idleTimestamp); long idleTimeout = getIdleTimeout(); long idleLeft = idleTimeout - idleElapsed; if (LOG.isDebugEnabled()) LOG.debug("{} idle timeout check, elapsed: {} ms, remaining: {} ms", this, idleElapsed, idleLeft); if (idleTimeout > 0) { if (idleLeft <= 0) { if (LOG.isDebugEnabled()) LOG.debug("{} idle timeout expired", this); try { onIdleExpired(new TimeoutException("Idle timeout expired: " + idleElapsed + "/" + idleTimeout + " ms")); } finally { notIdle(); } } } return idleLeft >= 0 ? idleLeft : 0; } return -1; } /** * This abstract method is called when the idle timeout has expired. * * @param timeout a TimeoutException */ protected abstract void onIdleExpired(TimeoutException timeout); /** * This abstract method should be called to check if idle timeouts * should still be checked. * * @return True if the entity monitored should still be checked for idle timeouts */ public abstract boolean isOpen(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy