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

org.eclipse.jetty.http.content.ValidatingCachingHttpContentFactory Maven / Gradle / Ivy

There is a newer version: 12.1.0.alpha0
Show newest version
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.http.content;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.NanoTime;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.thread.Scheduler;

/**
 * 

* {@link HttpContent.Factory} implementation of {@link CachingHttpContentFactory} which evicts invalid entries from the cache. * Uses a validationTime parameter to check files when they are accessed and/or sweepDelay parameter for a periodic sweep * for invalid entries in the cache. *

*

* {@link HttpContent} validation checks are configured through the {@code validationTime} parameter in the constructor. * If an {@link HttpContent} is found to be invalid it will be removed from the cache. * A value of -1 means that the cached {@link HttpContent} will never be checked if it is still valid, * a value of 0 means it is checked on every request, * a positive value indicates the number of milliseconds of the minimum time between validation checks. *

*

* This also remember a missed entry for the time set by {@code validationTime}ms. After this has * elapsed the entry will be invalid and will be evicted from the cache at the next access. *

*/ public class ValidatingCachingHttpContentFactory extends CachingHttpContentFactory implements Runnable { private final Scheduler _scheduler; private final long _sweepDelay; private final long _validationTime; private final long _maxCacheIdleTime; /** * Construct a {@link ValidatingCachingHttpContentFactory} which validates entries upon use to check if they * are still valid. * * @param authority the wrapped {@link HttpContent.Factory} to use. * @param validationPeriod time between filesystem checks in ms to see if an {@link HttpContent} is still valid (-1 never validate, 0 always validate). * @param bufferPool the {@link org.eclipse.jetty.io.ByteBufferPool} to use. */ public ValidatingCachingHttpContentFactory(@Name("authority") HttpContent.Factory authority, @Name("validationPeriod") long validationPeriod, @Name("bufferPool") ByteBufferPool bufferPool) { this(authority, validationPeriod, bufferPool, null, -1, -1); } /** * Construct a {@link ValidatingCachingHttpContentFactory} which validates entries upon use to check if they * are still valid and an optional period sweeper of the cache to find invalid and old entries to evict. * * @param authority the wrapped {@link HttpContent.Factory} to use. * @param validationPeriod time between filesystem checks in ms to see if an {@link HttpContent} is still valid (-1 never validate, 0 always validate). * @param bufferPool the {@link org.eclipse.jetty.io.ByteBufferPool} to use. * @param scheduler scheduler to use for the sweeper, can be null to not use sweeper. * @param sweepPeriod time between runs of the sweeper in ms (if 0 never sweep for invalid entries). * @param idleTimeout amount of time in ms an entry can be unused before evicted by the sweeper (if 0 never evict unused entries). */ public ValidatingCachingHttpContentFactory(@Name("authority") HttpContent.Factory authority, @Name("validationPeriod") long validationPeriod, @Name("byteBufferPool") ByteBufferPool bufferPool, @Name("scheduler") Scheduler scheduler, @Name("sweepPeriod") long sweepPeriod, @Name("idleTimeout") long idleTimeout) { super(authority, bufferPool); _validationTime = validationPeriod; _scheduler = scheduler; _sweepDelay = sweepPeriod; _maxCacheIdleTime = idleTimeout; if (scheduler != null && sweepPeriod > 0) schedule(); } @Override protected boolean isCacheable(HttpContent httpContent) { if (httpContent == null) return (_validationTime != 0); return super.isCacheable(httpContent); } private void schedule() { _scheduler.schedule(this, _sweepDelay, TimeUnit.MILLISECONDS); } @Override public void run() { try { ConcurrentMap cache = getCache(); for (Map.Entry entry : cache.entrySet()) { CachingHttpContent value = entry.getValue(); if (_maxCacheIdleTime > 0 && NanoTime.since(value.getLastAccessedNanos()) > TimeUnit.MILLISECONDS.toNanos(_maxCacheIdleTime)) removeFromCache(value); else if (!value.isValid()) removeFromCache(value); } } finally { schedule(); } } @Override protected CachingHttpContent newCachedContent(String p, HttpContent httpContent) { return new ValidatingCachedContent(p, httpContent, _validationTime); } @Override protected CachingHttpContent newNotFoundContent(String p) { return new ValidatingNotFoundContent(p, _validationTime); } protected class ValidatingCachedContent extends CachedHttpContent { private final long _validationTime; private final AtomicLong _lastValidated = new AtomicLong(); public ValidatingCachedContent(String key, HttpContent httpContent, long validationTime) { super(key, httpContent); _lastValidated.set(NanoTime.now()); _validationTime = validationTime; } @Override public boolean isValid() { if (_validationTime < 0) { return true; } else if (_validationTime > 0) { long now = NanoTime.now(); if (_lastValidated.updateAndGet(lastChecked -> (NanoTime.elapsed(lastChecked, now) > TimeUnit.MILLISECONDS.toNanos(_validationTime)) ? now : lastChecked) != now) return true; } return Objects.equals(getLastModifiedInstant(), getWrapped().getLastModifiedInstant()); } } protected static class ValidatingNotFoundContent extends NotFoundHttpContent { private final long _validationTime; private final AtomicLong _lastValidated = new AtomicLong(); public ValidatingNotFoundContent(String key, long validationTime) { super(key); _validationTime = validationTime; _lastValidated.set(NanoTime.now()); } @Override public boolean isValid() { if (_validationTime < 0) return true; if (_validationTime > 0) return NanoTime.since(_lastValidated.get()) < TimeUnit.MILLISECONDS.toNanos(_validationTime); return false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy