Author: tv Date: Tue Feb 2 15:27:42 2016 New Revision: 1728149 URL: http://svn.apache.org/viewvc?rev=1728149&view=rev Log: Simplify managers
Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java?rev=1728149&r1=1728148&r2=1728149&view=diff ============================================================================== --- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java (original) +++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java Tue Feb 2 15:27:42 2016 @@ -22,15 +22,16 @@ package org.apache.torque.manager; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; -import org.apache.commons.collections.FastArrayList; import org.apache.commons.jcs.JCS; import org.apache.commons.jcs.access.CacheAccess; import org.apache.commons.jcs.access.GroupCacheAccess; @@ -82,11 +83,11 @@ public abstract class AbstractBaseManage private boolean isNew = true; /** The fields which are valid fields of interest for a listener. */ - protected Map<Column, ?> validFields; + private CopyOnWriteArraySet<Column> validFields = new CopyOnWriteArraySet<Column>(); /** The listeners for this manager. */ - protected Map<Column, FastArrayList> listenersMap - = new HashMap<Column, FastArrayList>(); + protected ConcurrentMap<Column, CopyOnWriteArrayList<CacheListener<?>>> listenersMap = + new ConcurrentHashMap<Column, CopyOnWriteArrayList<CacheListener<?>>>(); /** * Get the Class instance @@ -109,6 +110,16 @@ public abstract class AbstractBaseManage } /** + * Add variable number of fields to the list potentially monitored by a listener + * + * @param columns array of columns + */ + protected void addValidField(Column ...columns) + { + this.validFields.addAll(Arrays.asList(columns)); + } + + /** * Get a fresh instance of an om * * @return an instance of the om class @@ -259,7 +270,7 @@ public abstract class AbstractBaseManage } /** - * Disposes of the cache. This triggers a shutdown of the connected cache + * Disposes of the manager. This triggers a shutdown of the connected cache * instances. This method should only be used during shutdown of Torque. The * manager instance will not cache anymore after this call. */ @@ -276,6 +287,9 @@ public abstract class AbstractBaseManage groupCache.dispose(); groupCache = null; } + + validFields.clear(); + listenersMap.clear(); } /** @@ -357,12 +371,12 @@ public abstract class AbstractBaseManage /** * Gets a list of om's based on id's. * - * @param ids a <code>ObjectKey[]</code> value - * @return a <code>List</code> value + * @param ids a number of object ids + * @return a <code>List</code> of objects * @throws TorqueException Any exceptions caught during processing will be * rethrown wrapped into a TorqueException. */ - protected List<T> getOMs(final ObjectKey[] ids) + protected List<T> getOMs(final ObjectKey ...ids) throws TorqueException { return getOMs(Arrays.asList(ids)); @@ -508,6 +522,8 @@ public abstract class AbstractBaseManage } /** + * Get the object usable for result caching + * * @return The cache instance. */ public synchronized MethodResultCache getMethodResultCache() @@ -530,110 +546,63 @@ public abstract class AbstractBaseManage } /** + * Add a new listener * * @param listener A new listener for cache events. */ - public void addCacheListenerImpl( - final CacheListener<? extends Persistent> listener) + public void addCacheListenerImpl(final CacheListener<?> listener) { - List<Column> keys = listener.getInterestedFields(); - for (Column key : keys) + for (Column key : listener.getInterestedFields()) { // Peer.column names are the fields - if (validFields != null && validFields.containsKey(key)) + if (validFields.contains(key)) { - FastArrayList listeners = listenersMap.get(key); + CopyOnWriteArrayList<CacheListener<?>> newList = new CopyOnWriteArrayList<CacheListener<?>>(); + CopyOnWriteArrayList<CacheListener<?>> listeners = listenersMap.putIfAbsent(key, newList); + if (listeners == null) { - listeners = createSubsetList(key); + listeners = newList; } - boolean isListenerNew = true; - Iterator<?> j = listeners.iterator(); - while (j.hasNext()) - { - Object listener2 = - ((WeakReference<?>) j.next()).get(); -// if (listener2 == null) -// { -// // do a little cleanup while checking for dupes -// // not thread-safe, not likely to be many nulls -// // but should revisit -// //j.remove(); -// } -// else - if (listener2 == listener) - { - isListenerNew = false; - break; - } - } - if (isListenerNew) - { - listeners.add(new WeakReference<CacheListener<? extends Persistent>>(listener)); - } + listeners.addIfAbsent(listener); } } } /** + * Notify all listeners in the list that an object has changed * - * @param key - * @return A subset of the list identified by <code>key</code>. - */ - private synchronized FastArrayList createSubsetList(final Column key) - { - FastArrayList list = null; - if (listenersMap.containsKey(key)) - { - list = listenersMap.get(key); - } - else - { - list = new FastArrayList(); - list.setFast(true); - listenersMap.put(key, list); - } - return list; - } - - /** - * - * @param listeners - * @param oldOm - * @param om + * @param listeners the list of listeners + * @param oldOm the previous object, null if the object has been added + * @param om the new object, null if the object has been removed */ protected <TT extends Persistent> void notifyListeners( - final List<WeakReference<CacheListener<TT>>> listeners, + final List<CacheListener<?>> listeners, final TT oldOm, final TT om) { if (listeners != null) { - synchronized (listeners) + for (CacheListener<?> cl : listeners) { - Iterator<WeakReference<CacheListener<TT>>> i = listeners.iterator(); - while (i.hasNext()) + @SuppressWarnings("unchecked") + CacheListener<TT> listener = (CacheListener<TT>) cl; + + if (oldOm == null) { - CacheListener<TT> listener = i.next().get(); - if (listener == null) - { - // remove reference as its object was cleared - i.remove(); - } - else - { - if (oldOm == null) - { - // object was added - listener.addedObject(om); - } - else - { - // object was refreshed - listener.refreshedObject(om); - } - } + // object was added + listener.addedObject(om); + } + else if (om == null) + { + // object was removed + listener.removedObject(om); + } + else + { + // object was refreshed + listener.refreshedObject(om); } } } Modified: db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java?rev=1728149&r1=1728148&r2=1728149&view=diff ============================================================================== --- db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java (original) +++ db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java Tue Feb 2 15:27:42 2016 @@ -34,21 +34,30 @@ import org.apache.torque.om.Persistent; public interface CacheListener<T extends Persistent> { /** + * Notify listener that an object has been added to the database * - * @param om + * @param om the object */ void addedObject(T om); /** + * Notify listener that an object has been modified * - * @param om + * @param om the object */ void refreshedObject(T om); - //public void removedObject(T om); + /** + * Notify listener that an object has been removed from the database + * + * @param om the object + */ + void removedObject(T om); /** + * Get the list of fields we are listening for * + * @return a list of fields, not null */ List<Column> getInterestedFields(); } Modified: db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java URL: http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java?rev=1728149&r1=1728148&r2=1728149&view=diff ============================================================================== --- db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java (original) +++ db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java Tue Feb 2 15:27:42 2016 @@ -20,7 +20,6 @@ package org.apache.torque.manager; */ import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import junit.framework.TestCase; @@ -42,6 +41,7 @@ public class AbstractBaseManagerTest ext private boolean addedObjectCalled; private boolean refreshedObjectCalled; + private boolean removedObjectCalled; static { @@ -69,7 +69,13 @@ public class AbstractBaseManagerTest ext this.refreshedObjectCalled = true; } - @Override + @Override + public void removedObject(TestPersistent om) + { + this.removedObjectCalled = true; + } + + @Override public List<Column> getInterestedFields() { List<Column> columnList = new ArrayList<Column>(2); @@ -172,24 +178,34 @@ public class AbstractBaseManagerTest ext assertNotNull("Should have MethodResultCache", mrc); } - @SuppressWarnings("unchecked") public void testListeners() { - manager.validFields = new HashMap<Column, Object>(); - manager.validFields.put(new ColumnImpl("test1"), null); - manager.validFields.put(new ColumnImpl("test2"), null); + manager.addValidField(new ColumnImpl("test1"), new ColumnImpl("test2")); manager.addCacheListenerImpl(this); this.addedObjectCalled = false; this.refreshedObjectCalled = false; + this.removedObjectCalled = false; TestPersistent test1 = new TestPersistent(); TestPersistent test2 = new TestPersistent(); manager.notifyListeners(manager.listenersMap.get(new ColumnImpl("test1")), (TestPersistent)null, test1); assertTrue("Should call addedObject", addedObjectCalled); assertFalse("Should not call refreshedObject", refreshedObjectCalled); + assertFalse("Should not call removedObject", removedObjectCalled); + this.addedObjectCalled = false; this.refreshedObjectCalled = false; + this.removedObjectCalled = false; manager.notifyListeners(manager.listenersMap.get(new ColumnImpl("test2")), test2, test1); assertFalse("Should not call addedObject", addedObjectCalled); assertTrue("Should call refreshedObject", refreshedObjectCalled); + assertFalse("Should not call removedObject", removedObjectCalled); + + this.addedObjectCalled = false; + this.refreshedObjectCalled = false; + this.removedObjectCalled = false; + manager.notifyListeners(manager.listenersMap.get(new ColumnImpl("test2")), test2, null); + assertFalse("Should not call addedObject", addedObjectCalled); + assertFalse("Should not call refreshedObject", refreshedObjectCalled); + assertTrue("Should call removedObject", removedObjectCalled); } } --------------------------------------------------------------------- To unsubscribe, e-mail: torque-dev-unsubscr...@db.apache.org For additional commands, e-mail: torque-dev-h...@db.apache.org