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
|
bsf.jar
|
||||||
|
commons-collections.jar
|
||||||
jacl.jar
|
jacl.jar
|
||||||
jakarta-regexp*.jar
|
jakarta-regexp*.jar
|
||||||
js.jar
|
js.jar
|
||||||
|
|
|
@ -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
|
||||||
|
|
120
src/com/silverwrist/util/cache/ObjectCache.java
vendored
120
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>,
|
* 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 <erbo@silcom.com>
|
* @author Eric J. Bowersox <erbo@silcom.com>
|
||||||
* @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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user