KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > core > storage > FixedSizeCache


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Core License version 1 published by ozone-db.org.
3
//
4
// Copyright (C) 2003-@year@, Leo Mekenkamp. All rights reserved.
5
//
6
// $Id: FixedSizeCache.java,v 1.4 2004/03/23 10:14:14 leomekenkamp Exp $
7

8 package org.ozoneDB.core.storage;
9
10 import java.util.Collection JavaDoc;
11 import java.util.Comparator JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.LinkedHashMap JavaDoc;
15 import java.util.LinkedHashSet JavaDoc;
16 import java.util.LinkedList JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19 import java.util.Properties JavaDoc;
20 import java.util.Set JavaDoc;
21 import java.util.Map.Entry;
22 import java.util.SortedSet JavaDoc;
23 import java.util.TreeMap JavaDoc;
24 import java.util.TreeSet JavaDoc;
25 import java.util.logging.Level JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27 import org.ozoneDB.OzoneInternalException;
28 import org.ozoneDB.core.ConfigurationException;
29
30
31 /**
32  * <p>A cache with a fixed maximum number of objects in it. This cache grows
33  * until it has reached its maximum, which can be set by maxCapacity. Once that
34  * maximum has been reached, the least recently used object is thrown away when
35  * a new object is put in the cache. This cache has, next to that maximum number
36  * of elements, also a maximum time an element will remain in this cache. If
37  * that time has expired the element will be removed from this cache also.
38  * Reinserting an element (using the same key) causes the time for that element
39  * to be reset.</p>
40  *
41  * <p>Note: every instance creates its own thread for asynchronous removal of
42  * items past their 'best before' time. The trimmed() method on the TrimHandler
43  * is often but not always called asynchronously from that thread.</p>
44  *
45  * @author <a HREF="mailto:leoATmekenkampD0Tcom">Leo Mekenkamp (mind the anti sp@m)</a>
46  * @version $Id: FixedSizeCache.java,v 1.4 2004/03/23 10:14:14 leomekenkamp Exp $
47  */

48 public class FixedSizeCache extends AbstractTrimmingCache implements PropertyConfigurable {
49     
50     private static final Logger JavaDoc log = Logger.getLogger(FixedSizeDelayCache.class.getName());
51
52     public static final PropertyInfo MAXCAPACITY = new PropertyInfo(
53         ".maxCapacity",
54         "int",
55         "1",
56         "number of objects that this cache should hold as a maximum",
57         new String JavaDoc[] {"100", "100000"}
58     );
59
60     public static final PropertyInfo INITIALCAPACITY = new PropertyInfo(
61         ".initialCapacity",
62         "int",
63         "1",
64         "number of objects that this cache reserves space for initially",
65         new String JavaDoc[] {"100", "100000"}
66     );
67
68     public static final PropertyInfo LOADFACTOR = new PropertyInfo(
69         ".loadFactor",
70         "float",
71         "0.75",
72         "load factor for this cache; see java.util.LinkedHashMap(int initialCapacity, float loadFactor)",
73         new String JavaDoc[] {"0.5", "0.95"}
74     );
75
76     private int maxCapacity;
77     
78     private Map JavaDoc map;
79     
80     /**
81      * @throws ConfigurationException
82      */

83     public FixedSizeCache(Properties JavaDoc properties, String JavaDoc prefix) {
84         super(properties, prefix);
85         try {
86             float loadFactor = Float.parseFloat(properties.getProperty(prefix + LOADFACTOR.getKey(), LOADFACTOR.getDefaultValue()));
87             log.config(getPrefix() + " using a load factor of " + loadFactor);
88             int initialCapacity = Integer.parseInt(properties.getProperty(prefix + INITIALCAPACITY.getKey(), INITIALCAPACITY.getDefaultValue()));
89             log.config(getPrefix() + " using an initial capacity of " + loadFactor);
90             map = new LinkedHashMap JavaDoc(initialCapacity, loadFactor, true);
91             setMaxCapacity(Integer.parseInt(properties.getProperty(prefix + MAXCAPACITY.getKey(), MAXCAPACITY.getDefaultValue())));
92             log.config(getPrefix() + " using a max capacity of " + getMaxCapacity());
93         } catch (NumberFormatException JavaDoc e) {
94             throw new ConfigurationException(e);
95         }
96     }
97
98     private Map JavaDoc getMap() {
99         return map;
100     }
101
102     public final void setMaxCapacity(int maxCapacity) {
103         synchronized(getSynchronizer()) {
104             this.maxCapacity = maxCapacity;
105             trim();
106         }
107     }
108     
109     public final int getMaxCapacity() {
110         // maxCapacity is an int so synchronization is not needed
111
return maxCapacity;
112     }
113     
114     public Collection JavaDoc getPropertyInfos() {
115         Collection JavaDoc result = new LinkedList JavaDoc();
116         result.add(MAXCAPACITY);
117         return result;
118     }
119     
120     public void put(Object JavaDoc key, Object JavaDoc value) {
121         synchronized(getSynchronizer()) {
122             getMap().put(key, value);
123             trim();
124         }
125     }
126
127     private void trim() {
128         int size = getMap().size() - getMaxCapacity();
129         int countDown = getMaxCapacity();
130         if (size > countDown) {
131             for (Iterator JavaDoc i = getMap().entrySet().iterator(); i.hasNext(); ) {
132                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
133                 if (--countDown < 0) {
134                     if (getTrimHandler() != null) {
135                         getTrimHandler().trimming(entry.getKey(), entry.getValue());
136                     }
137                     i.remove();
138                 }
139             }
140         }
141     }
142     
143     public Map JavaDoc copyToMap() {
144         synchronized(getSynchronizer()) {
145             return new HashMap JavaDoc(getMap());
146         }
147     }
148     
149     public Object JavaDoc get(Object JavaDoc key) {
150         synchronized(getSynchronizer()) {
151             return getMap().get(key);
152         }
153     }
154     
155     public Object JavaDoc remove(Object JavaDoc key) {
156         synchronized(getSynchronizer()) {
157             return getMap().remove(key);
158         }
159     }
160     
161     public int size() {
162         synchronized(getSynchronizer()) {
163             return getMap().size();
164         }
165     }
166     
167     private class OurMap extends LinkedHashMap JavaDoc {
168
169         public OurMap(int initialCapacity, float loadFactor) {
170             super(initialCapacity, loadFactor, true);
171         }
172         
173         protected boolean removeEldestEntry(Map.Entry JavaDoc entry) {
174             if (size() > getMaxCapacity()) {
175                 if (getTrimHandler() != null) {
176                     getTrimHandler().trimming(entry.getKey(), entry.getValue());
177                 }
178                 remove(entry.getKey());
179             }
180             return false;
181         }
182
183     }
184
185 }
186
Popular Tags