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:
Eric J. Bowersox 2002-05-27 08:13:39 +00:00
parent 86d9a90f54
commit dc28dfeb3e
5 changed files with 51 additions and 82 deletions

1
lib/.gitignore vendored
View File

@ -1,4 +1,5 @@
bsf.jar bsf.jar
commons-collections.jar
jacl.jar jacl.jar
jakarta-regexp*.jar jakarta-regexp*.jar
js.jar js.jar

View File

@ -6,6 +6,8 @@ compatible with the versions specified here.
Library Version File Name(s) Install To 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 Jakarta Regexp 1.2 jakarta-regexp-1.2.jar Venice "lib" subdirectory
Apache LOG4J 1.1.3 log4j.jar Venice "lib" subdirectory Apache LOG4J 1.1.3 log4j.jar Venice "lib" subdirectory
Bean Scripting Framework 2.2 bsf.jar Venice "lib" subdirectory Bean Scripting Framework 2.2 bsf.jar Venice "lib" subdirectory

View File

@ -11,14 +11,13 @@
* *
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>, * 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 * 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): * Contributor(s):
*/ */
package com.silverwrist.util.cache; package com.silverwrist.util.cache;
import java.lang.ref.*; import org.apache.commons.collections.*;
import java.util.*;
/** /**
* A chache which stores objects by key value, and is capable of creating them given an instance of * 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 &lt;erbo@silcom.com&gt; * @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X * @version X
* @see ObjectFactory * @see ObjectFactory
* @see java.lang.ref.SoftReference
*/ */
public class ObjectCache public class ObjectCache
{ {
@ -37,10 +35,9 @@ public class ObjectCache
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
private HashMap the_data = new HashMap(); // the actual underlying map 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 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
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Constructor * Constructor
@ -55,57 +52,25 @@ public class ObjectCache
*/ */
public ObjectCache(ObjectFactory factory) public ObjectCache(ObjectFactory factory)
{ {
if (factory==null) this(factory,5);
throw new NullPointerException("object factory cannot be null!");
this.factory = factory;
} // end constructor } // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
/** /**
* "Sweeps" the cache by taking all references that have been cleared and queued by the garbage * Creates a new <CODE>ObjectCache</CODE>.
* collector and removing them from the map. Should be called fairly often, to minimize wasted *
* hashmap slots. * @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 if (factory==null)
Reference r = rq.poll(); // reference that's been cleared throw new NullPointerException("object factory cannot be null!");
Iterator it; this.factory = factory;
this.mru_cache = new LRUMap(lru_size);
while (r!=null) } // end constructor
{ // 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
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* External operations * External operations
@ -120,9 +85,17 @@ public class ObjectCache
*/ */
public synchronized Object get(Object key) public synchronized Object get(Object key)
{ {
doSweep(); the_data.purge();
SoftReference r = (SoftReference)(the_data.get(key)); Object rc = mru_cache.get(key);
return ((r==null) ? null : r.get()); 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 } // end get
@ -137,18 +110,14 @@ public class ObjectCache
*/ */
public synchronized Object getOrCreate(Object key) throws ObjectFactoryException public synchronized Object getOrCreate(Object key) throws ObjectFactoryException
{ {
doSweep(); Object rc = this.get(key);
SoftReference r = (SoftReference)(the_data.get(key));
Object rc = ((r==null) ? null : r.get());
if (rc==null) if (rc==null)
{ // attempt to create a new object { // create a new object
rc = factory.newObject(key); rc = factory.newObject(key);
if (rc!=null) if (rc!=null)
{ // clear the old reference, throw it away, and put in a new one { // stash in both main map and cache
if (r!=null) the_data.put(key,rc);
r.clear(); mru_cache.put(key,rc);
r = new SoftReference(rc,rq);
the_data.put(key,r);
} // end if } // end if
@ -168,13 +137,11 @@ public class ObjectCache
*/ */
public synchronized void register(Object key, Object data) public synchronized void register(Object key, Object data)
{ {
doSweep(); the_data.purge();
SoftReference old = (SoftReference)(the_data.get(key)); if (the_data.get(key)!=null)
if ((old!=null) && (old.get()!=null))
throw new ObjectCacheException("object already in cache",key); throw new ObjectCacheException("object already in cache",key);
the_data.put(key,new SoftReference(data,rq)); the_data.put(key,data);
if (old!=null) mru_cache.put(key,data);
old.clear();
} // end register } // end register
@ -185,11 +152,18 @@ public class ObjectCache
*/ */
public synchronized void detach(Object key) public synchronized void detach(Object key)
{ {
doSweep(); mru_cache.remove(key);
SoftReference old = (SoftReference)(the_data.remove(key)); the_data.remove(key);
if (old!=null) the_data.purge();
old.clear();
} // end detach } // end detach
public synchronized void shutdown()
{
mru_cache.clear();
the_data.clear();
the_data.purge();
} // end shutdown
} // end class ObjectCache } // end class ObjectCache

View File

@ -158,8 +158,6 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend
if (deleted) if (deleted)
throw new DataException("This community has been deleted."); throw new DataException("This community has been deleted.");
data = env.getEngine().getCommunityDataObject(cid); data = env.getEngine().getCommunityDataObject(cid);
if (data!=null)
env.getUser().saveMRU("community",data);
// clear cache when we get the real data // clear cache when we get the real data
cache = null; cache = null;
@ -179,8 +177,6 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend
try try
{ // attempt to load the CommunityDataObject { // attempt to load the CommunityDataObject
data = env.getEngine().getCommunityDataObject(cid); data = env.getEngine().getCommunityDataObject(cid);
if (data!=null)
env.getUser().saveMRU("community",data);
} // end try } // end try
catch (DataException e) catch (DataException e)

View File

@ -219,8 +219,6 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
if (deleted) if (deleted)
throw new DataException("This conference has been deleted."); throw new DataException("This conference has been deleted.");
confdata = env.getCommunity().getConferenceDataObject(confid); confdata = env.getCommunity().getConferenceDataObject(confid);
if (confdata!=null)
env.getUser().saveMRU("conf",confdata);
// clear cache when we get the real confdata // clear cache when we get the real confdata
cache = null; cache = null;
@ -241,8 +239,6 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
try try
{ // attempt to load the ConferenceCommunityContext { // attempt to load the ConferenceCommunityContext
confdata = env.getCommunity().getConferenceDataObject(confid); confdata = env.getCommunity().getConferenceDataObject(confid);
if (confdata!=null)
env.getUser().saveMRU("conf",confdata);
} // end try } // end try
catch (DataException e) catch (DataException e)