/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.catalina.webresources;
if (cacheEntry == null) { // Local copy to ensure consistency int objectMaxSizeBytes = getObjectMaxSizeBytes();
CachedResource newCacheEntry = new CachedResource(this, root, path, getTtl(), objectMaxSizeBytes,
useClassLoaderResources);
// Concurrent callers will end up with the same CachedResource // instance
cacheEntry = resourceCache.putIfAbsent(path, newCacheEntry);
if (cacheEntry == null) { // newCacheEntry was inserted into the cache - validate it
cacheEntry = newCacheEntry;
cacheEntry.validateResource(useClassLoaderResources);
// Even if the resource content larger than objectMaxSizeBytes // there is still benefit in caching the resource metadata
long delta = cacheEntry.getSize();
size.addAndGet(delta);
if (size.get() > maxSize) { // Process resources unordered for speed. Trades cache // efficiency (younger entries may be evicted before older // ones) for speed since this is on the critical path for // request processing long targetSize = maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100; long newSize = evict(targetSize, resourceCache.values().iterator()); if (newSize > maxSize) { // Unable to create sufficient space for this resource // Remove it from the cache
removeCacheEntry(path);
log.warn(sm.getString("cache.addFail", path, root.getContext().getName()));
}
}
} else { // Another thread added the entry to the cache if (cacheEntry.usesClassLoaderResources() != useClassLoaderResources) { // Race condition adding cache entries with the same path // but differing values for useClassLoaderResources. // Cache only supports one entry per path with one value of // useClassLoaderResources. // Let the other thread "win" and add the resource to the // cache. This thread will receive a cacheEntry instance // that isn't added to the cache. // There are assumptions here. They are: // - refactoring the Cache to use a combined key of // path+useClassLoaderResources adds unnecessary // complexity // - the race condition is rare (over the lifetime of an // application) // - it would be rare for an application to need to cache a // resource for both values of useClassLoaderResources
cacheEntry = newCacheEntry;
} // Make sure it is validated
cacheEntry.validateResource(useClassLoaderResources);
}
} else {
hitCount.increment();
}
if (cacheEntry == null) { // Local copy to ensure consistency int objectMaxSizeBytes = getObjectMaxSizeBytes();
CachedResource newCacheEntry = new CachedResource(this, root, path, getTtl(), objectMaxSizeBytes,
useClassLoaderResources);
// Concurrent callers will end up with the same CachedResource // instance
cacheEntry = resourceCache.putIfAbsent(path, newCacheEntry);
if (cacheEntry == null) { // newCacheEntry was inserted into the cache - validate it
cacheEntry = newCacheEntry;
cacheEntry.validateResources(useClassLoaderResources);
// Content will not be cached but we still need metadata size long delta = cacheEntry.getSize();
size.addAndGet(delta);
if (size.get() > maxSize) { // Process resources unordered for speed. Trades cache // efficiency (younger entries may be evicted before older // ones) for speed since this is on the critical path for // request processing long targetSize = maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100; long newSize = evict(targetSize, resourceCache.values().iterator()); if (newSize > maxSize) { // Unable to create sufficient space for this resource // Remove it from the cache
removeCacheEntry(path);
log.warn(sm.getString("cache.addFail", path));
}
}
} else { // Another thread added the entry to the cache // Make sure it is validated
cacheEntry.validateResources(useClassLoaderResources);
}
} else {
hitCount.increment();
}
return cacheEntry.getWebResources();
}
protectedvoid backgroundProcess() { // Create an ordered set of all cached resources with the least recently // used first. This is a background process so we can afford to take the // time to order the elements first
TreeSet<CachedResource> orderedResources = new TreeSet<>(
Comparator.comparingLong(CachedResource::getNextCheck));
orderedResources.addAll(resourceCache.values());
Iterator<CachedResource> iter = orderedResources.iterator();
long targetSize = maxSize * (100 - TARGET_FREE_PERCENT_BACKGROUND) / 100; long newSize = evict(targetSize, iter);
// Don't expire anything that has been checked within the TTL if (resource.getNextCheck() > now) { continue;
}
// Remove the entry from the cache
removeCacheEntry(resource.getWebappPath());
newSize = size.get();
}
return newSize;
}
void removeCacheEntry(String path) { // With concurrent calls for the same path, the entry is only removed // once and the cache size is only updated (if required) once.
CachedResource cachedResource = resourceCache.remove(path); if (cachedResource != null) { long delta = cachedResource.getSize();
size.addAndGet(-delta);
}
}
public CacheStrategy getCacheStrategy() { return cacheStrategy;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.