📄 filecache.java
字号:
/*
* Copyright 2000-2001,2004 The Apache Software Foundation.
*
* Licensed 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.jetspeed.cache;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.io.File;
// Jetspeed logging classes
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
/**
* FileCache keeps a cache of files up-to-date with a most simple eviction policy.
* The eviction policy will keep n items in the cache, and then start evicting
* the items ordered-by least used first. The cache runs a thread to check for
* both evictions and refreshes.
*
* @author David S. Taylor <a href="mailto:taylor@apache.org">David Sean Taylor</a>
* @version $Id: FileCache.java,v 1.5 2004/03/25 16:27:41 jford Exp $
*/
public class FileCache implements java.util.Comparator
{
protected long scanRate = 300; // every 5 minutes
protected int maxSize = 100; // maximum of 100 items
protected List listeners = new LinkedList();
private FileCacheScanner scanner = null;
private Map cache = null;
/**
* Static initialization of the logger for this class
*/
private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(FileCache.class.getName());
/**
* Default constructor. Use default values for scanReate and maxSize
*
*/
public FileCache()
{
cache = new HashMap();
this.scanner = new FileCacheScanner();
this.scanner.setDaemon(true);
}
/**
* Set scanRate and maxSize
*
* @param scanRate how often in seconds to refresh and evict from the cache
* @param maxSize the maximum allowed size of the cache before eviction starts
*/
public FileCache(long scanRate,
int maxSize)
{
cache = new HashMap();
this.scanRate = scanRate;
this.maxSize = maxSize;
this.scanner = new FileCacheScanner();
this.scanner.setDaemon(true);
}
/**
* Set all parameters on the cache
*
* @param initialCapacity the initial size of the cache as passed to HashMap
* @param loadFactor how full the hash table is allowed to get before increasing
* @param scanRate how often in seconds to refresh and evict from the cache
* @param maxSize the maximum allowed size of the cache before eviction starts
*/
public FileCache(int initialCapacity,
int loadFactor,
long scanRate,
int maxSize)
{
cache = new HashMap(initialCapacity, loadFactor);
this.scanRate = scanRate;
this.maxSize = maxSize;
this.scanner = new FileCacheScanner();
this.scanner.setDaemon(true);
}
/**
* Set the new refresh scan rate on managed files.
*
* @param scanRate the new scan rate in seconds
*/
public void setScanRate(long scanRate)
{
this.scanRate= scanRate;
}
/**
* Get the refresh scan rate
*
* @return the current refresh scan rate in seconds
*/
public long getScanRate()
{
return scanRate;
}
/**
* Set the new maximum size of the cache
*
* @param maxSize the maximum size of the cache
*/
public void setMaxSize(int maxSize)
{
this.maxSize = maxSize;
}
/**
* Get the maximum size of the cache
*
* @return the current maximum size of the cache
*/
public int getMaxSize()
{
return maxSize;
}
/**
* Gets an entry from the cache given a key
*
* @param key the key to look up the entry by
* @return the entry
*/
public FileCacheEntry get(String key)
{
return (FileCacheEntry) cache.get(key);
}
/**
* Gets an entry from the cache given a key
*
* @param key the key to look up the entry by
* @return the entry
*/
public Object getDocument(String key)
{
FileCacheEntry entry = (FileCacheEntry) cache.get(key);
if (entry != null)
{
return entry.getDocument();
}
return null;
}
/**
* Puts a file entry in the file cache
*
* @param file The file to be put in the cache
* @param document the cached document
*/
public void put(File file, Object document)
throws java.io.IOException
{
FileCacheEntry entry = new FileCacheEntry(file, document);
cache.put(file.getCanonicalPath(), entry);
}
/**
* Puts a file entry in the file cache
*
* @param path the full path name of the file
* @param document the cached document
*/
public void put(String key, Object document)
throws java.io.IOException
{
File file = new File(key);
FileCacheEntry entry = new FileCacheEntry(file, document);
cache.put(file.getCanonicalPath(), entry);
}
/**
* Removes a file entry from the file cache
*
* @param key the full path name of the file
* @return the entry removed
*/
public Object remove(String key)
{
return cache.remove(key);
}
/**
* Add a File Cache Event Listener
*
* @param listener the event listener
*/
public void addListener(FileCacheEventListener listener)
{
listeners.add(listener);
}
/**
* Start the file Scanner running at the current scan rate.
*
*/
public void startFileScanner()
{
try
{
this.scanner.start();
}
catch (java.lang.IllegalThreadStateException e)
{
logger.error("Exception starting scanner", e);
}
}
/**
* Stop the file Scanner
*
*/
public void stopFileScanner()
{
this.scanner.setStopping(true);
}
/**
* Evicts entries based on last accessed time stamp
*
*/
protected void evict()
{
synchronized (cache)
{
if (this.getMaxSize() >= cache.size())
{
return;
}
List list = new LinkedList(cache.values());
Collections.sort(list, this);
int count = 0;
int limit = cache.size() - this.getMaxSize();
for (Iterator it = list.iterator(); it.hasNext(); )
{
if (count >= limit)
{
break;
}
FileCacheEntry entry = (FileCacheEntry) it.next();
String key = null;
try
{
key = entry.getFile().getCanonicalPath();
}
catch (java.io.IOException e)
{
logger.error("Exception getting file path: ", e);
}
// notify that eviction will soon take place
for (Iterator lit = this.listeners.iterator(); lit.hasNext(); )
{
FileCacheEventListener listener =
(FileCacheEventListener) lit.next();
listener.evict(entry);
}
cache.remove(key);
count++;
}
}
}
/**
* Comparator function for sorting by last accessed during eviction
*
*/
public int compare(Object o1, Object o2)
{
FileCacheEntry e1 = (FileCacheEntry)o1;
FileCacheEntry e2 = (FileCacheEntry)o2;
if (e1.getLastAccessed() < e2.getLastAccessed())
{
return -1;
}
else if (e1.getLastAccessed() == e2.getLastAccessed())
{
return 0;
}
return 1;
}
/**
* inner class that runs as a thread to scan the cache for updates or evictions
*
*/
protected class FileCacheScanner extends Thread
{
private boolean stopping = false;
public void setStopping(boolean flag)
{
this.stopping = flag;
}
/**
* Run the file scanner thread
*
*/
public void run()
{
boolean done = false;
try
{
while(!done)
{
try
{
int count = 0;
synchronized(FileCache.this)
{
for (Iterator it = FileCache.this.cache.values().iterator(); it.hasNext(); )
{
FileCacheEntry entry = (FileCacheEntry) it.next();
Date modified = new Date(entry.getFile().lastModified());
if (modified.after(entry.getLastModified()))
{
for (Iterator lit = FileCache.this.listeners.iterator(); lit.hasNext(); )
{
FileCacheEventListener listener =
(FileCacheEventListener) lit.next();
listener.refresh(entry);
entry.setLastModified(modified);
}
}
count++;
}
}
if (count > FileCache.this.getMaxSize())
{
FileCache.this.evict();
}
}
catch (Exception e)
{
logger.error("FileCache Scanner: Error in iteration...", e);
}
sleep(FileCache.this.getScanRate() * 1000);
if (this.stopping)
{
this.stopping = false;
done = true;
}
}
}
catch (InterruptedException e)
{
logger.error("FileCacheScanner: recieved interruption, exiting.", e);
}
}
} // end inner class: FileCacheScanner
/**
* get an iterator over the cache values
*
* @return iterator over the cache values
*/
public Iterator getIterator()
{
return cache.values().iterator();
}
/**
* get the size of the cache
*
* @return the size of the cache
*/
public int getSize()
{
return cache.size();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -