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 }