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.store;
18
19 import net.sf.ehcache.Cache;
20 import net.sf.ehcache.Element;
21 import net.sf.ehcache.CacheException;
22 import org.apache.commons.collections.SequencedHashMap;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 import java.io.Serializable;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
29 import java.util.Set;
30
31 /**
32 * First-In-First-Out (FIFO) implementation of MemoryStore.
33 *
34 * @author <a href="mailto:ssuravarapu@users.sourceforge.net">Surya Suravarapu</a>
35 * @version $Id: FifoMemoryStore.java 52 2006-04-24 14:50:03Z gregluck $
36 */
37 public final class FifoMemoryStore extends MemoryStore {
38 private static final Log LOG = LogFactory.getLog(FifoMemoryStore.class.getName());
39
40 private final static int SEQUENCED_HASH_MAP = 1;
41
42 private final static int LINKED_HASH_MAP = 2;
43
44 /**
45 * One of the above declared static collection types
46 */
47 private int collectionType;
48
49 /**
50 * Constructor for the FifoMemoryStore object.
51 * <p/>
52 * First tries to use {@link java.util.LinkedHashMap}. If not found uses
53 * Jakarta Commons collections.
54 */
55 public FifoMemoryStore(Cache cache, DiskStore diskStore) {
56 super(cache, diskStore);
57
58
59 try {
60 Class.forName("java.util.LinkedHashMap");
61 map = new LinkedHashMap();
62 collectionType = LINKED_HASH_MAP;
63 } catch (ClassNotFoundException e) {
64
65 try {
66 Class.forName("org.apache.commons.collections.SequencedHashMap");
67 map = new SequencedHashMap();
68 collectionType = SEQUENCED_HASH_MAP;
69 } catch (ClassNotFoundException ee) {
70 LOG.error(ee.getMessage());
71 }
72 }
73 }
74
75 /**
76 * Allow specialised actions over adding the element to the map
77 *
78 * @param element
79 */
80 protected final void doPut(Element element) throws CacheException {
81 if (isFull()) {
82 removeFirstElement();
83 }
84 }
85
86
87 /**
88 * Returns the first eligible element that can be taken out of the cache
89 * based on the FIFO policy
90 */
91 Element getFirstElement() {
92 if (map.size() == 0) {
93 return null;
94 }
95
96 Element element = null;
97 Serializable key;
98
99 if (collectionType == LINKED_HASH_MAP) {
100 Set keySet = map.keySet();
101 Iterator itr = keySet.iterator();
102
103 if (itr.hasNext()) {
104 key = (Serializable) itr.next();
105 element = (Element) map.get(key);
106 }
107 } else if (collectionType == SEQUENCED_HASH_MAP) {
108 key = (Serializable) ((SequencedHashMap) map).getFirstKey();
109 element = (Element) map.get(key);
110 }
111
112 return element;
113 }
114
115 /**
116 * Remove the first element that is eligible to removed from the store
117 * based on the FIFO policy
118 */
119 private void removeFirstElement() throws CacheException {
120 Element element = getFirstElement();
121
122 if (cache.isExpired(element)) {
123 remove(element.getObjectKey());
124 notifyExpiry(element);
125 return;
126 }
127 remove(element.getObjectKey());
128 evict(element);
129 }
130 }