From dc28dfeb3ecdf5d29675323e9272030825c42c49 Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Mon, 27 May 2002 08:13:39 +0000 Subject: [PATCH] introduced the use of the Jakarta Commons Collections - revamped ObjectCache to include an LRU hard reference map and simplified it greatly in the process --- lib/.gitignore | 1 + lib/README.lib | 2 + .../silverwrist/util/cache/ObjectCache.java | 122 +++++++----------- .../core/impl/CommunityUserContextImpl.java | 4 - .../core/impl/ConferenceUserContextImpl.java | 4 - 5 files changed, 51 insertions(+), 82 deletions(-) diff --git a/lib/.gitignore b/lib/.gitignore index a93d63b..780e3d3 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,4 +1,5 @@ bsf.jar +commons-collections.jar jacl.jar jakarta-regexp*.jar js.jar diff --git a/lib/README.lib b/lib/README.lib index 1382f87..6fda8ef 100644 --- a/lib/README.lib +++ b/lib/README.lib @@ -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 diff --git a/src/com/silverwrist/util/cache/ObjectCache.java b/src/com/silverwrist/util/cache/ObjectCache.java index 27d1b36..0e63a4a 100644 --- a/src/com/silverwrist/util/cache/ObjectCache.java +++ b/src/com/silverwrist/util/cache/ObjectCache.java @@ -11,14 +11,13 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * 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 ObjectCache. + * + * @param factory The factory object used to create new objects when getOrCreate is called. + * @param lru_size How many objects to maintain hard references to. + * @exception java.lang.NullPointerException The object factory passed in is null. */ - 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 diff --git a/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java b/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java index e5781a3..76fc760 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java @@ -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) diff --git a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java index 5c7e482..9529036 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java @@ -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)