Update of /var/cvs/src/org/mmbase/cache
In directory james.mmbase.org:/tmp/cvs-serv10057

Modified Files:
        Cache.java CacheImplementationInterface.java 
        QueryResultCache.java 
Log Message:
  MMB-1667, changed locking object, and made it explicit


See also: http://cvs.mmbase.org/viewcvs/src/org/mmbase/cache
See also: http://www.mmbase.org/jira/browse/MMB-1667


Index: Cache.java
===================================================================
RCS file: /var/cvs/src/org/mmbase/cache/Cache.java,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- Cache.java  3 Feb 2008 17:33:56 -0000       1.49
+++ Cache.java  24 Jun 2008 09:54:44 -0000      1.50
@@ -20,7 +20,7 @@
  * A base class for all Caches. Extend this class for other caches.
  *
  * @author Michiel Meeuwissen
- * @version $Id: Cache.java,v 1.49 2008/02/03 17:33:56 nklasens Exp $
+ * @version $Id: Cache.java,v 1.50 2008/06/24 09:54:44 michiel Exp $
  */
 abstract public class Cache<K, V> implements SizeMeasurable, Map<K, V> {
 
@@ -33,6 +33,7 @@
      * @since MMBase-1.8
      */
     private CacheImplementationInterface<K, V> implementation;
+    protected Object lock;
 
     /**
      * The number of times an element was succesfully retrieved from this 
cache.
@@ -52,6 +53,7 @@
     public Cache(int size) {
         // See: http://www.mmbase.org/jira/browse/MMB-1486
         implementation = new LRUCache<K, V>(size);
+        lock =         = implementation.getLock();
         //implementation = new LRUHashtable<K, V>(size);
 
         log.service("Creating cache " + getName() + ": " + getDescription());
@@ -63,6 +65,7 @@
             if (implementation == null || (! 
clas.equals(implementation.getClass()))) {
                 implementation = (CacheImplementationInterface<K,V>) 
clas.newInstance();
                 implementation.config(configValues);
+                lock = implementation.getLock();
             }
         } catch (ClassNotFoundException cnfe) {
             log.error("For cache " + this + " " + cnfe.getClass().getName() + 
": " + cnfe.getMessage());
@@ -118,6 +121,13 @@
     }
 
     /**
+     * @since MMBase-1.8.6
+     */
+    public Class getImplementation() {
+        return implementation.getClass();
+    }
+
+    /**
      * Checks whether the key object should be cached.
      * This method returns <code>false</code> if either the current cache is 
inactive, or the object to cache
      * has a cache policy associated that prohibits caching of the object.


Index: CacheImplementationInterface.java
===================================================================
RCS file: /var/cvs/src/org/mmbase/cache/CacheImplementationInterface.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- CacheImplementationInterface.java   10 Aug 2007 07:53:52 -0000      1.9
+++ CacheImplementationInterface.java   24 Jun 2008 09:54:44 -0000      1.10
@@ -17,7 +17,7 @@
  * An implementation of this interface has to be thread-safe to guarantee 
correctness.
  *
  * @author Michiel Meeuwissen
- * @version $Id: CacheImplementationInterface.java,v 1.9 2007/08/10 07:53:52 
michiel Exp $
+ * @version $Id: CacheImplementationInterface.java,v 1.10 2008/06/24 09:54:44 
michiel Exp $
  * @since MMBase-1.8
  */
 public interface CacheImplementationInterface<K, V> extends Map<K, V> {
@@ -42,4 +42,10 @@
      */
     void config(Map<String, String> configuration);
 
+    /**
+     * The cache implementation must be somehow thread-safe. This method should
+     * return the object on which to synchronize, e.g. when looping over 
entrySet.
+     * @since MMBase-1.8.6
+     */
+    Object getLock();
 }


Index: QueryResultCache.java
===================================================================
RCS file: /var/cvs/src/org/mmbase/cache/QueryResultCache.java,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -b -r1.45 -r1.46
--- QueryResultCache.java       17 Sep 2007 16:53:01 -0000      1.45
+++ QueryResultCache.java       24 Jun 2008 09:54:44 -0000      1.46
@@ -27,14 +27,15 @@
  * one of the types present in the SearchQuery is changed (,created or 
deleted).
  * This mechanism is not very subtle but it is garanteed to be correct. It 
means
  * though that your cache can be considerably less effective for queries
- * containing node types from which often node are edited.
+ * containing node types from which often nodes are edited.
  *
  * @author Daniel Ockeloen
  * @author Michiel Meeuwissen
  * @author Bunst Eunders
- * @version $Id: QueryResultCache.java,v 1.45 2007/09/17 16:53:01 pierre Exp $
+ * @version $Id: QueryResultCache.java,v 1.46 2008/06/24 09:54:44 michiel Exp $
  * @since MMBase-1.7
  * @see org.mmbase.storage.search.SearchQuery
+ * @todo Perhaps we could put the 'typeCounter' stuff in a sub-class.
  */
 
 abstract public class QueryResultCache extends Cache<SearchQuery, 
List<MMObjectNode>> implements NodeEventListener, RelationEventListener {
@@ -47,6 +48,8 @@
      * A relation role name is considered a type
      * This cache will not invalidate when an event does not mention one of 
these types
      * The cache will be evaluated when a parent type is in this map.
+     * @todo I think that nearly all query result caches contain queries with 
quite generic or
+     * oftenly changed types. I doubt that the gain is worth the hassle.
      */
     private Map<String, Integer> typeCounters = new HashMap<String, Integer>();
     
@@ -100,14 +103,16 @@
     /**
      * Puts a search result in this cache.
      */
-    public synchronized List<MMObjectNode> put(SearchQuery query, 
List<MMObjectNode> queryResult) {
+    public List<MMObjectNode> put(SearchQuery query, List<MMObjectNode> 
queryResult) {
         if (!checkCachePolicy(query)) return null;
         if (query instanceof BasicQuery) {
             query = ((BasicQuery) query).getQuery();
         }
+        synchronized(lock) {
         increaseCounters(query, typeCounters);
         return super.put(query, queryResult);
     }
+    }
 
     /**
      * Removes an object from the cache. It alsos remove the watch from the
@@ -115,14 +120,16 @@
      *
      * @param key A SearchQuery object.
      */
-    public synchronized List<MMObjectNode> remove(SearchQuery key) {
+    public List<MMObjectNode> remove(SearchQuery key) {
         if (key instanceof BasicQuery) {
             key = ((BasicQuery) key).getQuery();
         }
+        synchronized(lock) {
         List<MMObjectNode> result = super.remove(key);
-        decreaseCounters(key, typeCounters);
+            if (result != null) decreaseCounters(key, typeCounters);
         return result;
     }
+    }
 
     private void increaseCounters(SearchQuery query, Map<String, Integer> 
counters) {
         for (Step step : query.getSteps()) {
@@ -130,8 +137,7 @@
             if (counters.containsKey(stepName)) {
                 int count = counters.get(stepName);
                 counters.put(stepName, count + 1);
-            }
-            else {
+            } else {
                 counters.put(stepName, 1);
             }
         }
@@ -144,8 +150,7 @@
                 int count = counters.get(stepName);
                 if (count > 1) {
                     counters.put(stepName, count - 1);
-                }
-                else {
+                } else {
                     counters.remove(stepName);
                 }
             }
@@ -165,7 +170,12 @@
         }
     }
 
+    /**
+     *
+     * @todo Is the lock necessary?
+     */
     private boolean containsType(RelationEvent event) {
+        synchronized(lock) {
         if (typeCounters.containsKey("object")) {
             return true;
         }
@@ -198,6 +208,8 @@
         }
         return false;
     }
+    }
+
 
     /**
      * @see 
org.mmbase.core.event.NodeEventListener#notify(org.mmbase.core.event.NodeEvent)
@@ -209,6 +221,7 @@
     }
 
     private boolean containsType(NodeEvent event) {
+        synchronized(lock) {
         if (typeCounters.containsKey("object")) {
             return true;
         }
@@ -227,6 +240,7 @@
         }
         return false;
     }
+    }
 
     protected int nodeChanged(Event event) throws IllegalArgumentException{
         if (log.isDebugEnabled()) {
@@ -234,7 +248,7 @@
         }
         Set<SearchQuery> cacheKeys;
         Map<String, Integer> oldTypeCounters;
-        synchronized(this) {
+        synchronized(lock) {
             cacheKeys = new HashSet<SearchQuery>(keySet());
             oldTypeCounters = new HashMap<String, Integer>(typeCounters);
         }
@@ -244,7 +258,7 @@
 
         evaluate(event, cacheKeys, removeKeys, foundTypeCounters);
 
-        synchronized(this) {
+        synchronized(lock) {
             for (SearchQuery q : removeKeys) {
                 remove(q);
             }
@@ -275,7 +289,9 @@
         }
         return removeKeys.size();
     }
-
+    /**
+     * @javadoc
+     */
     private void evaluate(Event event, Set<SearchQuery> cacheKeys, 
Set<SearchQuery> removeKeys, Map<String, Integer> foundTypeCounters) {
         int evaluatedResults = cacheKeys.size();
         long startTime = System.currentTimeMillis();
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to