View Javadoc

1   /**
2    *  Copyright 2003-2006 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.event;
18  
19  import net.sf.ehcache.Cache;
20  import net.sf.ehcache.CacheException;
21  import net.sf.ehcache.Element;
22  
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.Collections;
27  
28  /**
29   * Counts listener notifications.
30   * <p/>
31   * The methods also check that we hold the Cache lock.
32   *
33   * @author Greg Luck
34   * @version $Id: CountingCacheEventListener.java 49 2006-04-23 12:59:55Z gregluck $
35   */
36  public class CountingCacheEventListener implements CacheEventListener {
37  
38      private static final List CACHE_ELEMENTS_PUT = Collections.synchronizedList(new ArrayList());
39      private static final List CACHE_ELEMENTS_UPDATED = Collections.synchronizedList(new ArrayList());
40      private static final List CACHE_ELEMENTS_REMOVED = Collections.synchronizedList(new ArrayList());
41      private static final List CACHE_ELEMENTS_EXPIRED = Collections.synchronizedList(new ArrayList());
42  
43  
44      /**
45       * Accessor
46       */
47      public static List getCacheElementsRemoved(Cache cache) {
48          return extractListForGivenCache(CACHE_ELEMENTS_REMOVED, cache);
49      }
50  
51  
52      /**
53       * Accessor
54       */
55      public static List getCacheElementsPut(Cache cache) {
56          return extractListForGivenCache(CACHE_ELEMENTS_PUT, cache);
57      }
58  
59      /**
60       * Accessor
61       */
62      public static List getCacheElementsUpdated(Cache cache) {
63          return extractListForGivenCache(CACHE_ELEMENTS_UPDATED, cache);
64      }
65  
66      /**
67       * Accessor
68       */
69      public static List getCacheElementsExpired(Cache cache) {
70          return extractListForGivenCache(CACHE_ELEMENTS_EXPIRED, cache);
71      }
72  
73      /**
74       * Resets the counters to 0
75       */
76      public static void resetCounters() {
77          synchronized (CACHE_ELEMENTS_REMOVED) {
78              CACHE_ELEMENTS_REMOVED.clear();
79          }
80          synchronized (CACHE_ELEMENTS_PUT) {
81              CACHE_ELEMENTS_PUT.clear();
82          }
83          synchronized (CACHE_ELEMENTS_UPDATED) {
84              CACHE_ELEMENTS_UPDATED.clear();
85          }
86          synchronized (CACHE_ELEMENTS_EXPIRED) {
87              CACHE_ELEMENTS_EXPIRED.clear();
88          }
89      }
90  
91  
92      /**
93       * @param notificationList
94       * @param cache            the cache to filter on. If null, there is not filtering and all entries are returned.
95       * @return a list of notifications for the cache
96       */
97      private static List extractListForGivenCache(List notificationList, Cache cache) {
98          ArrayList list = new ArrayList();
99          synchronized (notificationList) {
100             for (int i = 0; i < notificationList.size(); i++) {
101                 CounterEntry counterEntry = (CounterEntry) notificationList.get(i);
102                 if (counterEntry.cache.equals(cache)) {
103                     list.add(counterEntry.getElement());
104                 } else if (cache == null) {
105                     list.add(counterEntry.getElement());
106                 }
107             }
108         }
109         return list;
110     }
111 
112 
113     /**
114      * {@inheritDoc}
115      */
116     public void notifyElementRemoved(final Cache cache, final Element element) {
117         checkSynchronizedAccessToCacheOk(cache);
118         CACHE_ELEMENTS_REMOVED.add(new CounterEntry(cache, element));
119     }
120 
121     /**
122      * Called immediately after an element has been put into the cache. The {@link net.sf.ehcache.Cache#put(net.sf.ehcache.Element)} method
123      * will block until this method returns.
124      * <p/>
125      * Implementers may wish to have access to the Element's fields, including value, so the element is provided.
126      * Implementers should be careful not to modify the element. The effect of any modifications is undefined.
127      *
128      * @param cache
129      * @param element the element which was just put into the cache.
130      */
131     public void notifyElementPut(final Cache cache, final Element element) {
132         checkSynchronizedAccessToCacheOk(cache);
133         CACHE_ELEMENTS_PUT.add(new CounterEntry(cache, element));
134     }
135 
136 
137     /**
138      * Called immediately after an element has been put into the cache and the element already
139      * existed in the cache. This is thus an update.
140      * <p/>
141      * The {@link net.sf.ehcache.Cache#put(net.sf.ehcache.Element)} method
142      * will block until this method returns.
143      * <p/>
144      * Implementers may wish to have access to the Element's fields, including value, so the element is provided.
145      * Implementers should be careful not to modify the element. The effect of any modifications is undefined.
146      *
147      * @param cache   the cache emitting the notification
148      * @param element the element which was just put into the cache.
149      */
150     public void notifyElementUpdated(final Cache cache, final Element element) throws CacheException {
151         CACHE_ELEMENTS_UPDATED.add(new CounterEntry(cache, element));
152     }
153 
154     /**
155      * {@inheritDoc}
156      */
157     public void notifyElementExpired(final Cache cache, final Element element) {
158         CACHE_ELEMENTS_EXPIRED.add(new CounterEntry(cache, element));
159     }
160 
161     /**
162      * Give the replicator a chance to cleanup and free resources when no longer needed
163      * <p/>
164      * Clean up static counters
165      */
166     public void dispose() {
167         resetCounters();
168     }
169 
170     /**
171      * This counter should be called from calls synchonized on Cache. These methods should hold the lock
172      * therefore this is ok.
173      *
174      * @param cache
175      */
176     private void checkSynchronizedAccessToCacheOk(Cache cache) {
177         try {
178             cache.get("justasyncrhonizationtest");
179         } catch (CacheException e) {
180             throw new RuntimeException(e);
181         }
182     }
183 
184     /**
185      * A Counter entry
186      */
187     public static class CounterEntry {
188 
189         private Cache cache;
190         private Element element;
191 
192         /**
193          * Construct a new event
194          *
195          * @param cache
196          * @param element
197          */
198         public CounterEntry(Cache cache, Element element) {
199             this.cache = cache;
200             this.element = element;
201         }
202 
203         /**
204          * @return the cache the event relates to
205          */
206         public Cache getCache() {
207             return cache;
208         }
209 
210         /**
211          * @return the payload
212          */
213         public Serializable getElement() {
214             return element;
215         }
216 
217 
218     }
219 
220 
221 }