introduced the use of the Jakarta Commons Collections - revamped ObjectCache
to include an LRU hard reference map and simplified it greatly in the process
This commit is contained in:
parent
86d9a90f54
commit
dc28dfeb3e
1
lib/.gitignore
vendored
1
lib/.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
bsf.jar
|
||||
commons-collections.jar
|
||||
jacl.jar
|
||||
jakarta-regexp*.jar
|
||||
js.jar
|
||||
|
|
|
@ -6,6 +6,8 @@ compatible with the versions specified here.
|
|||
|
||||
Library Version File Name(s) Install To
|
||||
-------------------------------------------------------------------------------------------------
|
||||
Apache Jakarta Commons 2.0 commons-collections.jar Venice "lib" subdirectory
|
||||
Collections
|
||||
Apache Jakarta Regexp 1.2 jakarta-regexp-1.2.jar Venice "lib" subdirectory
|
||||
Apache LOG4J 1.1.3 log4j.jar Venice "lib" subdirectory
|
||||
Bean Scripting Framework 2.2 bsf.jar Venice "lib" subdirectory
|
||||
|
|
122
src/com/silverwrist/util/cache/ObjectCache.java
vendored
122
src/com/silverwrist/util/cache/ObjectCache.java
vendored
|
@ -11,14 +11,13 @@
|
|||
*
|
||||
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
|
||||
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
|
||||
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
* Copyright (C) 2001-02 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
package com.silverwrist.util.cache;
|
||||
|
||||
import java.lang.ref.*;
|
||||
import java.util.*;
|
||||
import org.apache.commons.collections.*;
|
||||
|
||||
/**
|
||||
* A chache which stores objects by key value, and is capable of creating them given an instance of
|
||||
|
@ -28,7 +27,6 @@ import java.util.*;
|
|||
* @author Eric J. Bowersox <erbo@silcom.com>
|
||||
* @version X
|
||||
* @see ObjectFactory
|
||||
* @see java.lang.ref.SoftReference
|
||||
*/
|
||||
public class ObjectCache
|
||||
{
|
||||
|
@ -37,10 +35,9 @@ public class ObjectCache
|
|||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
private HashMap the_data = new HashMap(); // the actual underlying map
|
||||
private ObjectFactory factory; // used to create new objects
|
||||
private ReferenceQueue rq = new ReferenceQueue(); // where our references go when they die
|
||||
private ArrayList sweeper = new ArrayList(); // temporary used in doing sweeps
|
||||
private SoftRefHashMap the_data = new SoftRefHashMap(); // actual main data store
|
||||
private LRUMap mru_cache; // most-recently-used map
|
||||
private ObjectFactory factory; // used to create new objects
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Constructor
|
||||
|
@ -55,57 +52,25 @@ public class ObjectCache
|
|||
*/
|
||||
public ObjectCache(ObjectFactory factory)
|
||||
{
|
||||
if (factory==null)
|
||||
throw new NullPointerException("object factory cannot be null!");
|
||||
this.factory = factory;
|
||||
this(factory,5);
|
||||
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Internal operations
|
||||
*--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* "Sweeps" the cache by taking all references that have been cleared and queued by the garbage
|
||||
* collector and removing them from the map. Should be called fairly often, to minimize wasted
|
||||
* hashmap slots.
|
||||
* Creates a new <CODE>ObjectCache</CODE>.
|
||||
*
|
||||
* @param factory The factory object used to create new objects when <CODE>getOrCreate</CODE> is called.
|
||||
* @param lru_size How many objects to maintain hard references to.
|
||||
* @exception java.lang.NullPointerException The object factory passed in is <CODE>null</CODE>.
|
||||
*/
|
||||
private synchronized void doSweep()
|
||||
public ObjectCache(ObjectFactory factory, int lru_size)
|
||||
{
|
||||
Set entries = the_data.entrySet(); // used to find entries with the specified value
|
||||
Reference r = rq.poll(); // reference that's been cleared
|
||||
Iterator it;
|
||||
if (factory==null)
|
||||
throw new NullPointerException("object factory cannot be null!");
|
||||
this.factory = factory;
|
||||
this.mru_cache = new LRUMap(lru_size);
|
||||
|
||||
while (r!=null)
|
||||
{ // look for this reference in our hash map
|
||||
it = entries.iterator();
|
||||
while (it.hasNext())
|
||||
{ // look for the map entry containing the reference
|
||||
Map.Entry ntry = (Map.Entry)(it.next());
|
||||
if (r==(Reference)(ntry.getValue()))
|
||||
{ // found the entry with this reference - nuke it
|
||||
sweeper.add(ntry.getKey());
|
||||
break; // don't need to take this loop any farther
|
||||
|
||||
} // end if
|
||||
|
||||
} // end while
|
||||
|
||||
r = rq.poll(); // get the next cleared reference
|
||||
|
||||
} // end while
|
||||
|
||||
if (sweeper.isEmpty())
|
||||
return; // no entries to remove
|
||||
|
||||
// Remove all the corresponding keys from the hashmap.
|
||||
it = sweeper.iterator();
|
||||
while (it.hasNext())
|
||||
the_data.remove(it.next());
|
||||
sweeper.clear(); // reset for next time
|
||||
|
||||
} // end doSweep
|
||||
} // end constructor
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* External operations
|
||||
|
@ -120,9 +85,17 @@ public class ObjectCache
|
|||
*/
|
||||
public synchronized Object get(Object key)
|
||||
{
|
||||
doSweep();
|
||||
SoftReference r = (SoftReference)(the_data.get(key));
|
||||
return ((r==null) ? null : r.get());
|
||||
the_data.purge();
|
||||
Object rc = mru_cache.get(key);
|
||||
if (rc==null)
|
||||
{ // retrieve from main map, poke back into cache
|
||||
rc = the_data.get(key);
|
||||
if (rc!=null)
|
||||
mru_cache.put(key,rc);
|
||||
|
||||
} // end if
|
||||
|
||||
return rc;
|
||||
|
||||
} // end get
|
||||
|
||||
|
@ -137,18 +110,14 @@ public class ObjectCache
|
|||
*/
|
||||
public synchronized Object getOrCreate(Object key) throws ObjectFactoryException
|
||||
{
|
||||
doSweep();
|
||||
SoftReference r = (SoftReference)(the_data.get(key));
|
||||
Object rc = ((r==null) ? null : r.get());
|
||||
Object rc = this.get(key);
|
||||
if (rc==null)
|
||||
{ // attempt to create a new object
|
||||
{ // create a new object
|
||||
rc = factory.newObject(key);
|
||||
if (rc!=null)
|
||||
{ // clear the old reference, throw it away, and put in a new one
|
||||
if (r!=null)
|
||||
r.clear();
|
||||
r = new SoftReference(rc,rq);
|
||||
the_data.put(key,r);
|
||||
{ // stash in both main map and cache
|
||||
the_data.put(key,rc);
|
||||
mru_cache.put(key,rc);
|
||||
|
||||
} // end if
|
||||
|
||||
|
@ -168,13 +137,11 @@ public class ObjectCache
|
|||
*/
|
||||
public synchronized void register(Object key, Object data)
|
||||
{
|
||||
doSweep();
|
||||
SoftReference old = (SoftReference)(the_data.get(key));
|
||||
if ((old!=null) && (old.get()!=null))
|
||||
the_data.purge();
|
||||
if (the_data.get(key)!=null)
|
||||
throw new ObjectCacheException("object already in cache",key);
|
||||
the_data.put(key,new SoftReference(data,rq));
|
||||
if (old!=null)
|
||||
old.clear();
|
||||
the_data.put(key,data);
|
||||
mru_cache.put(key,data);
|
||||
|
||||
} // end register
|
||||
|
||||
|
@ -185,11 +152,18 @@ public class ObjectCache
|
|||
*/
|
||||
public synchronized void detach(Object key)
|
||||
{
|
||||
doSweep();
|
||||
SoftReference old = (SoftReference)(the_data.remove(key));
|
||||
if (old!=null)
|
||||
old.clear();
|
||||
mru_cache.remove(key);
|
||||
the_data.remove(key);
|
||||
the_data.purge();
|
||||
|
||||
} // end detach
|
||||
|
||||
public synchronized void shutdown()
|
||||
{
|
||||
mru_cache.clear();
|
||||
the_data.clear();
|
||||
the_data.purge();
|
||||
|
||||
} // end shutdown
|
||||
|
||||
} // end class ObjectCache
|
||||
|
|
|
@ -158,8 +158,6 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend
|
|||
if (deleted)
|
||||
throw new DataException("This community has been deleted.");
|
||||
data = env.getEngine().getCommunityDataObject(cid);
|
||||
if (data!=null)
|
||||
env.getUser().saveMRU("community",data);
|
||||
|
||||
// clear cache when we get the real data
|
||||
cache = null;
|
||||
|
@ -179,8 +177,6 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend
|
|||
try
|
||||
{ // attempt to load the CommunityDataObject
|
||||
data = env.getEngine().getCommunityDataObject(cid);
|
||||
if (data!=null)
|
||||
env.getUser().saveMRU("community",data);
|
||||
|
||||
} // end try
|
||||
catch (DataException e)
|
||||
|
|
|
@ -219,8 +219,6 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
|
|||
if (deleted)
|
||||
throw new DataException("This conference has been deleted.");
|
||||
confdata = env.getCommunity().getConferenceDataObject(confid);
|
||||
if (confdata!=null)
|
||||
env.getUser().saveMRU("conf",confdata);
|
||||
|
||||
// clear cache when we get the real confdata
|
||||
cache = null;
|
||||
|
@ -241,8 +239,6 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
|
|||
try
|
||||
{ // attempt to load the ConferenceCommunityContext
|
||||
confdata = env.getCommunity().getConferenceDataObject(confid);
|
||||
if (confdata!=null)
|
||||
env.getUser().saveMRU("conf",confdata);
|
||||
|
||||
} // end try
|
||||
catch (DataException e)
|
||||
|
|
Loading…
Reference in New Issue
Block a user