Fields Summary |
---|
public static final String | DEFAULT_SERVLET_NAME |
private final ConcurrentHashMap | fileCacheA ByteBuffer cache of static pages. |
private static final ByteBuffer | nullByteBufferA dummy instance of ByteBuffer |
protected static final ByteBuffer | connectionCloseBBA connection: close of ByteBuffer |
protected static final ByteBuffer | connectionKaBBA connection: keep-alive of ByteBuffer |
private static final String | NEWLINEHTTP end line. |
public static final String | OKHTTP OK header |
private int | portThe port associated with this cache. |
private ScheduledThreadPoolExecutor | cacheResourcesThreadScheduled Thread that clean the cache every XX seconds. |
private ConcurrentLinkedQueue | cacheManagerFileCacheEntry cache |
private int | secondsMaxAgeTimeout before remove the static resource from the cache. |
private int | maxCacheEntriesThe maximum entries in the fileCache |
private long | minEntrySizeThe maximum size of a cached resources. |
private long | maxEntrySizeThe maximum size of a cached resources. |
private long | maxLargeFileCacheSizeThe maximum memory mapped bytes |
private long | maxSmallFileCacheSizeThe maximum cached bytes |
private static long | mappedMemorySizeThe current cache size in bytes |
private static long | heapSizeThe current cache size in bytes |
private boolean | isEnabledIs the file cache enabled. |
private boolean | isLargeFileCacheEnabledIs the large FileCache enabled. |
private static boolean | isMonitoringEnabledIs monitoring enabled. |
private int | openCacheEntriesThe number of current open cache entries |
private int | maxOpenCacheEntriesThe number of max current open cache entries |
private long | maxHeapCacheSizeMax heap space used for cache |
private long | maxMappedMemoryMax mapped memory used for cache |
private int | countHitsNumber of cache lookup hits |
private int | countMissesNumber of cache lookup misses |
private int | countCacheHitsNumber of hits on cached file info |
private int | countCacheMissesNumber of misses on cached file info |
private int | countMappedHitsNumber of hits on cached file info |
private int | countMappedMissesNumber of misses on cached file info |
private int | headerBBSizeThe Header ByteBuffer default size. |
Methods Summary |
---|
public synchronized void | add(java.lang.String mappedServlet, java.lang.String baseDir, java.lang.String requestURI, org.apache.tomcat.util.http.MimeHeaders headers, boolean xPoweredBy)Add a resource to the cache. Currently, only static resources served
by the DefaultServlet can be cached.
// ---------------------------------------------------- Methods ----------//
if ( fileCache.get(requestURI) != null) return;
// cache is full.
if ( fileCache.size() > maxCacheEntries) {
return;
}
if ( mappedServlet.equals(DEFAULT_SERVLET_NAME) ){
File file = new File(baseDir + requestURI);
ByteBuffer bb = mapFile(file);
// Always put the answer into the map. If it's null, then
// we know that it doesn't fit into the cache, so there's no
// reason to go through this code again.
if (bb == null)
bb = nullByteBuffer;
FileCacheEntry entry = cacheManager.poll();
if ( entry == null){
entry = new FileCacheEntry();
}
entry.bb = bb;
entry.requestURI = requestURI;
if ( bb != nullByteBuffer){
entry.lastModified = headers.getHeader("Last-Modified");
entry.contentType = headers.getHeader("content-type");
entry.xPoweredBy = xPoweredBy;
entry.isInHeap = (file.length() < minEntrySize);
entry.date = headers.getHeader("Date");
entry.Etag = headers.getHeader("Etag");
configHeaders(entry);
if ( isMonitoringEnabled ) {
openCacheEntries++;
if ( openCacheEntries > maxOpenCacheEntries){
maxOpenCacheEntries = openCacheEntries;
}
if ( heapSize > maxHeapCacheSize){
maxHeapCacheSize = heapSize;
}
if ( mappedMemorySize > maxMappedMemory){
maxMappedMemory = mappedMemorySize;
}
}
if ( secondsMaxAge > 0 ) {
entry.future = cacheResourcesThread.schedule(entry,
secondsMaxAge, TimeUnit.SECONDS);
}
}
fileCache.put(requestURI,entry);
}
|
private void | appendHeaderValue(java.lang.StringBuffer sb, java.lang.String name, java.lang.String value)Utility to add headers to the HTTP response.
sb.append(name);
sb.append(": ");
sb.append(value);
sb.append(NEWLINE);
|
private void | configHeaders(com.sun.enterprise.web.connector.grizzly.FileCache$FileCacheEntry entry)Return a ByteBuffer contains the server header.
if ( entry.headerBuffer == null ) {
entry.headerBuffer =
ByteBuffer.allocate(getHeaderBBSize());
}
StringBuffer sb = new StringBuffer();
sb.append(OK);
if ( entry.xPoweredBy){
appendHeaderValue(sb,"X-Powered-By", "Servlet/2.5");
}
appendHeaderValue(sb, "ETag", entry.Etag);
appendHeaderValue(sb,"Last-Modified", entry.lastModified);
appendHeaderValue(sb,"Content-Type", entry.contentType);
appendHeaderValue(sb,"Content-Length", entry.bb.capacity() + "");
appendHeaderValue(sb,"Date", entry.date);
appendHeaderValue(sb,"Server", SelectorThread.SERVER_NAME);
entry.headerBuffer.put(sb.toString().getBytes());
entry.headerBuffer.flip();
|
public java.util.concurrent.ConcurrentHashMap | getCache()Return the FileCache
return fileCache;
|
public long | getCountContentHits()Return the Number of hits on cached file content
return countMappedHits;
|
public int | getCountContentMisses()Return the Number of misses on cached file content
return countMappedMisses;
|
public long | getCountEntries()Return the number of current cache entries.
return fileCache.size();
|
public long | getCountHits()Return the Number of cache lookup hits
return countHits;
|
public long | getCountInfoHits()The Number of hits on cached file info
return countCacheHits;
|
public long | getCountInfoMisses()Return the number of misses on cached file info
return countCacheMisses;
|
public long | getCountMisses()Return the Number of cache lookup misses
return countMisses;
|
public long | getCountOpenEntries()The number of current open cache entries
return openCacheEntries;
|
public int | getFlagEnabled()Returns flag indicating whether file cache has been enabled
return (isEnabled == true?1:0);
|
public int | getHeaderBBSize()Retunr the header size buffer.
return headerBBSize;
|
public boolean | getLargeFileCacheEnabled()Is the large file cache support enabled.
return isLargeFileCacheEnabled;
|
public int | getMaxCacheEntries()Return the maximum entries this cache can contains.
return maxCacheEntries;
|
public long | getMaxEntries()Return the maximum number of cache entries
return maxCacheEntries;
|
public long | getMaxEntrySize()Get the maximum size a FileCacheEntry can have.
return maxEntrySize;
|
public long | getMaxHeapCacheSize()Return the maximum heap space used for cache
return maxHeapCacheSize;
|
public long | getMaxLargeCacheSize()Get the maximum cache size
return maxLargeFileCacheSize;
|
public long | getMaxMmapCacheSize()Return the Maximum Memory Map size to be used for caching
return maxMappedMemory;
|
public long | getMaxOpenEntries()Return the maximum number of open cache entries
return maxOpenCacheEntries;
|
public long | getMaxSmallCacheSize()Get the maximum cache size
return maxSmallFileCacheSize;
|
public long | getMinEntrySize()Get the maximum size a FileCacheEntry can have.
return minEntrySize;
|
public int | getSecondsMaxAge()Return the maximum age of a valid cache entry
return secondsMaxAge;
|
public long | getSizeHeapCache()Return the heap space used for cache
return heapSize;
|
public static long | getSizeMmapCache()Return the size of Mapped memory used for caching
return mappedMemorySize;
|
public boolean | isEnabled()Is the fileCache enabled.
return isEnabled;
|
private final com.sun.enterprise.web.connector.grizzly.FileCache$FileCacheEntry | map(byte[] requestBytes, int start, int length)Return true if the file is cached.
String uri = "";
FileCacheEntry entry = null;
if ( !fileCache.isEmpty() ){
uri = new String(requestBytes,start,length);
entry = fileCache.get(uri);
if ( isMonitoringEnabled) {
if (entry != null && entry.bb != null
&& entry.bb != nullByteBuffer){
if ( entry.isInHeap )
countCacheHits++;
else
countMappedHits++;
countHits++;
} else {
countMisses++;
}
}
}
return entry;
|
private final java.nio.ByteBuffer | mapFile(java.io.File file)Map the file to a ByteBuffer
FileChannel fileChannel = null;
FileInputStream stream = null;
try {
stream = new FileInputStream(file);
fileChannel = stream.getChannel();
long size = fileChannel.size();
if ( !isLargeFileCacheEnabled ) {
// Large file support are not enabled
if ( size > minEntrySize ) {
return null;
}
} else if ( size > maxEntrySize){
return null;
}
if ( size > minEntrySize )
mappedMemorySize+= size;
else
heapSize+= size;
// Cache full
if ( mappedMemorySize > maxLargeFileCacheSize ) {
mappedMemorySize-= size;
return null;
} else if ( heapSize > maxSmallFileCacheSize ) {
heapSize-= size;
return null;
}
ByteBuffer bb =
fileChannel.map(FileChannel.MapMode.READ_ONLY,0,size);
if ( size < minEntrySize) {
((MappedByteBuffer)bb).load();
}
return bb;
} catch (IOException ioe) {
return null;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ioe) {
}
}
if (fileChannel != null) {
try {
fileChannel.close();
} catch (IOException ioe) {
}
}
}
|
public boolean | sendCache(byte[] req, int start, int length, java.nio.channels.SocketChannel socketChannel, boolean keepAlive)Send the cache.
try{
FileCacheEntry entry = map(req,start,length);
if ( entry != null && entry.bb != nullByteBuffer){
sendCache(socketChannel,entry,keepAlive);
return true;
}
} catch (IOException ex){
SelectorThread.logger()
.fine("File Cache: " + ex.getMessage());
return true;
} catch (Throwable t){
// If an unexpected exception occurs, try to serve the page
// as if it wasn't in a cache.
SelectorThread.logger()
.fine("File Cache thread race: " + t.getMessage());
}
return false;
|
protected void | sendCache(java.nio.channels.SocketChannel socketChannel, com.sun.enterprise.web.connector.grizzly.FileCache$FileCacheEntry entry, boolean keepAlive)Send the cached resource.
OutputWriter.flushChannel(socketChannel, entry.headerBuffer.slice());
ByteBuffer keepAliveBuf = keepAlive ? connectionKaBB.slice():
connectionCloseBB.slice();
OutputWriter.flushChannel(socketChannel, keepAliveBuf);
OutputWriter.flushChannel(socketChannel, entry.bb.slice());
|
public void | setCacheManager(java.util.concurrent.ConcurrentLinkedQueue cacheManager)Set the cache manager used by this instance.
this.cacheManager = cacheManager;
|
public void | setHeaderBBSize(int headerBBSize)Set the size of the header ByteBuffer.
this.headerBBSize = headerBBSize;
|
public void | setIsEnabled(boolean isEnabled)Is the file caching mechanism enabled.
this.isEnabled = isEnabled;
|
public static void | setIsMonitoringEnabled(boolean isMe)Turn monitoring on/off
isMonitoringEnabled = isMe;
|
public void | setLargeFileCacheEnabled(boolean isLargeEnabled)Is the large file cache support enabled.
this.isLargeFileCacheEnabled = isLargeEnabled;
|
public void | setMaxCacheEntries(int mEntries)Set the maximum entries this cache can contains.
maxCacheEntries = mEntries;
|
public void | setMaxEntrySize(long mEntrySize)Set the maximum size a FileCacheEntry can have.
maxEntrySize = mEntrySize;
|
public void | setMaxLargeCacheSize(long mCacheSize)Set the maximum cache size
maxLargeFileCacheSize = mCacheSize;
|
public void | setMaxSmallCacheSize(long mCacheSize)Set the maximum cache size
maxSmallFileCacheSize = mCacheSize;
|
public void | setMinEntrySize(long mSize)Set the maximum size a FileCacheEntry can have.
minEntrySize = mSize;
|
public void | setSecondsMaxAge(int sMaxAges)The timeout in seconds before remove a FileCacheEntry
from the fileCache
secondsMaxAge = sMaxAges;
|