001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tcclient.ehcache;
006:
007: import com.tc.object.bytecode.Manager;
008: import com.tc.object.bytecode.ManagerUtil;
009: import com.tc.util.Assert;
010: import com.tcclient.cache.CacheConfig;
011: import com.tcclient.cache.CacheData;
012: import com.tcclient.cache.CacheDataStore;
013: import com.tcclient.cache.Expirable;
014:
015: import java.io.Serializable;
016: import java.util.AbstractCollection;
017: import java.util.AbstractSet;
018: import java.util.Collection;
019: import java.util.Iterator;
020: import java.util.Map;
021: import java.util.Set;
022:
023: /**
024: * Up to now, TimeExpiryMap is only used in the context of Ehcache which is synchronized and auto-locked in the
025: * MemoryStore class; therefore, no synchronization is needed here. TimeExpiryMap will be shared when a Ehcache is
026: * clustered. That is why we do not need to make store and dtmStore as root like what Session does.
027: */
028: public class TimeExpiryMap implements Map, Expirable, Cloneable,
029: Serializable {
030: protected final CacheDataStore timeExpiryDataStore;
031:
032: public TimeExpiryMap(long invalidatorSleepSeconds,
033: long maxIdleTimeoutSeconds, long maxTTLSeconds,
034: String cacheName) {
035: Manager manager = ManagerUtil.getManager();
036: CacheConfig config = new CacheConfig("CacheInvalidator - "
037: + cacheName, maxIdleTimeoutSeconds, maxTTLSeconds,
038: invalidatorSleepSeconds, this , manager);
039: timeExpiryDataStore = new CacheDataStore(config);
040: }
041:
042: // For test only
043: public TimeExpiryMap(long invalidatorSleepSeconds,
044: long maxIdleTimeoutSeconds, long maxTTLSeconds,
045: String cacheName, boolean globalEvictionEnabled,
046: int globalEvictionDuration, int concurrency,
047: int evictorPoolSize, boolean isLoggingEnabled,
048: boolean isEvictorLoggingEnabled, int numOfChunks,
049: long restMillis) {
050:
051: CacheConfig config = new CacheConfig("CacheInvalidator - "
052: + cacheName, maxIdleTimeoutSeconds, maxTTLSeconds,
053: invalidatorSleepSeconds, this , concurrency,
054: evictorPoolSize, globalEvictionEnabled,
055: globalEvictionDuration, isLoggingEnabled,
056: isEvictorLoggingEnabled, numOfChunks, restMillis);
057: timeExpiryDataStore = new CacheDataStore(config);
058: }
059:
060: public void initialize() {
061: timeExpiryDataStore.initialize();
062: }
063:
064: public Object put(Object key, Object value) {
065: return timeExpiryDataStore.put(key, value);
066: }
067:
068: public void putData(Object key, Object value) {
069: timeExpiryDataStore.putData(key, value);
070: }
071:
072: public void expire(Object key) {
073: processExpired(key);
074: }
075:
076: protected void processExpired(Object key) {
077: //
078: }
079:
080: public void clear() {
081: timeExpiryDataStore.clear();
082: }
083:
084: public boolean containsKey(Object key) {
085: return timeExpiryDataStore.getStore(key).containsKey(key);
086: }
087:
088: public boolean containsValue(Object value) {
089: return timeExpiryDataStore.containsValue(value);
090: }
091:
092: public Set entrySet() {
093: return new EntrySetWrapper(timeExpiryDataStore.entrySet());
094: }
095:
096: Set nativeEntrySet() {
097: return timeExpiryDataStore.entrySet();
098: }
099:
100: public Object get(Object key) {
101: return timeExpiryDataStore.get(key);
102: }
103:
104: public boolean isEmpty() {
105: return timeExpiryDataStore.isEmpty();
106: }
107:
108: public Set keySet() {
109: return new KeySetWrapper(timeExpiryDataStore.keySet());
110: }
111:
112: public void putAll(Map map) {
113: for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
114: Map.Entry entry = (Map.Entry) i.next();
115: timeExpiryDataStore.put(entry.getKey(), entry.getValue());
116: }
117: }
118:
119: public Object remove(Object key) {
120: return timeExpiryDataStore.remove(key);
121: }
122:
123: public int size() {
124: return timeExpiryDataStore.size();
125: }
126:
127: public Collection values() {
128: return new ValuesCollectionWrapper(timeExpiryDataStore.values());
129: }
130:
131: public int getHitCount() {
132: return timeExpiryDataStore.getHitCount();
133: }
134:
135: public int getMissCountExpired() {
136: return timeExpiryDataStore.getMissCountExpired();
137: }
138:
139: public int getMissCountNotFound() {
140: return timeExpiryDataStore.getMissCountNotFound();
141: }
142:
143: public boolean isExpired(final Object key) {
144: return timeExpiryDataStore.isExpired(key);
145: }
146:
147: public final void stopTimeMonitoring() {
148: timeExpiryDataStore.stopInvalidatorThread();
149: }
150:
151: public void clearStatistics() {
152: timeExpiryDataStore.clearStatistics();
153: }
154:
155: private class EntrySetWrapper extends AbstractSet {
156:
157: private final Set entries;
158:
159: public EntrySetWrapper(Set entries) {
160: this .entries = entries;
161: }
162:
163: public void clear() {
164: TimeExpiryMap.this .clear();
165: entries.clear();
166: }
167:
168: public boolean contains(Object o) {
169: return entries.contains(o);
170: }
171:
172: public Iterator iterator() {
173: return new EntriesIterator(entries.iterator());
174: }
175:
176: public boolean remove(Object o) {
177: Object key = ((Map.Entry) o).getKey();
178: TimeExpiryMap.this .remove(key);
179: return entries.remove(key);
180: }
181:
182: public int size() {
183: return entries.size();
184: }
185: }
186:
187: private class ValuesCollectionWrapper extends AbstractCollection {
188:
189: private final Collection values;
190:
191: public ValuesCollectionWrapper(Collection values) {
192: this .values = values;
193: }
194:
195: public void clear() {
196: TimeExpiryMap.this .clear();
197: values.clear();
198: }
199:
200: public boolean contains(Object o) {
201: if (!(o instanceof CacheData)) {
202: o = new CacheData(o, timeExpiryDataStore.getConfig());
203: }
204: return values.contains(o);
205: }
206:
207: public Iterator iterator() {
208: return new ValuesIterator(nativeEntrySet().iterator());
209: }
210:
211: public int size() {
212: return values.size();
213: }
214: }
215:
216: private class ValuesIterator extends EntriesIterator {
217:
218: public ValuesIterator(Iterator iterator) {
219: super (iterator);
220: }
221:
222: public Object next() {
223: Map.Entry e = (Map.Entry) super .next();
224: return e.getValue();
225: }
226: }
227:
228: private class EntryWrapper implements Map.Entry {
229:
230: private final Map.Entry entry;
231:
232: public EntryWrapper(Map.Entry entry) {
233: this .entry = entry;
234: }
235:
236: public Object getKey() {
237: return entry.getKey();
238: }
239:
240: public Object getValue() {
241: Object rv = entry.getValue();
242: Assert.pre(rv instanceof CacheData);
243: return ((CacheData) rv).getValue();
244: }
245:
246: public Object setValue(Object value) {
247: if (!(value instanceof CacheData)) {
248: value = new CacheData(value, timeExpiryDataStore
249: .getConfig());
250: }
251: CacheData cd = (CacheData) entry.setValue(value);
252: return cd.getValue();
253: }
254:
255: public boolean equals(Object o) {
256: if (!(o instanceof Map.Entry)) {
257: return false;
258: }
259:
260: Map.Entry e = (Map.Entry) o;
261: return getKey().equals(e.getKey())
262: && getValue().equals(e.getValue());
263: }
264:
265: public int hashCode() {
266: return entry.hashCode();
267: }
268: }
269:
270: private class EntriesIterator implements Iterator {
271:
272: private final Iterator iterator;
273: private Map.Entry currentEntry;
274:
275: public EntriesIterator(Iterator iterator) {
276: this .iterator = iterator;
277: }
278:
279: public boolean hasNext() {
280: return iterator.hasNext();
281: }
282:
283: public Object next() {
284: currentEntry = nextEntry();
285: return new EntryWrapper(currentEntry);
286: }
287:
288: protected Map.Entry nextEntry() {
289: return (Map.Entry) iterator.next();
290: }
291:
292: public void remove() {
293: TimeExpiryMap.this .remove(currentEntry.getKey());
294: iterator.remove();
295: }
296: }
297:
298: private class KeySetWrapper extends AbstractSet {
299:
300: private final Set keySet;
301:
302: public KeySetWrapper(Set keySet) {
303: this .keySet = keySet;
304: }
305:
306: public void clear() {
307: TimeExpiryMap.this .clear();
308: keySet.clear();
309: }
310:
311: public boolean contains(Object o) {
312: return keySet.contains(o);
313: }
314:
315: public Iterator iterator() {
316: return new KeysIterator(nativeEntrySet().iterator());
317: }
318:
319: public boolean remove(Object o) {
320: TimeExpiryMap.this .remove(o);
321: return keySet.remove(o);
322: }
323:
324: public int size() {
325: return keySet.size();
326: }
327: }
328:
329: private class KeysIterator extends EntriesIterator {
330:
331: public KeysIterator(Iterator iterator) {
332: super (iterator);
333: }
334:
335: public Object next() {
336: Map.Entry e = (Map.Entry) super.next();
337: return e.getKey();
338: }
339: }
340:
341: }
|