1 package org.apache.commons.jcs3.engine.memory.soft;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.lang.ref.SoftReference;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.concurrent.ConcurrentHashMap;
29 import java.util.concurrent.ConcurrentMap;
30 import java.util.concurrent.LinkedBlockingQueue;
31
32 import org.apache.commons.jcs3.engine.behavior.ICacheElement;
33 import org.apache.commons.jcs3.engine.behavior.ICompositeCacheAttributes;
34 import org.apache.commons.jcs3.engine.control.CompositeCache;
35 import org.apache.commons.jcs3.engine.memory.AbstractMemoryCache;
36 import org.apache.commons.jcs3.engine.memory.util.MemoryElementDescriptor;
37 import org.apache.commons.jcs3.engine.memory.util.SoftReferenceElementDescriptor;
38 import org.apache.commons.jcs3.engine.stats.StatElement;
39 import org.apache.commons.jcs3.engine.stats.behavior.IStatElement;
40 import org.apache.commons.jcs3.engine.stats.behavior.IStats;
41 import org.apache.commons.jcs3.log.Log;
42 import org.apache.commons.jcs3.log.LogManager;
43
44
45
46
47
48
49
50
51
52
53 public class SoftReferenceMemoryCache<K, V> extends AbstractMemoryCache<K, V>
54 {
55
56 private static final Log log = LogManager.getLog(SoftReferenceMemoryCache.class);
57
58
59
60
61
62
63
64
65 private LinkedBlockingQueue<ICacheElement<K, V>> strongReferences;
66
67
68
69
70
71
72 @Override
73 public synchronized void initialize( final CompositeCache<K, V> hub )
74 {
75 super.initialize( hub );
76 strongReferences = new LinkedBlockingQueue<>();
77 log.info( "initialized Soft Reference Memory Cache for {0}",
78 this::getCacheName );
79 }
80
81
82
83
84 @Override
85 public ConcurrentMap<K, MemoryElementDescriptor<K, V>> createMap()
86 {
87 return new ConcurrentHashMap<>();
88 }
89
90
91
92
93 @Override
94 public Set<K> getKeySet()
95 {
96 final Set<K> keys = new HashSet<>();
97 for (final Map.Entry<K, MemoryElementDescriptor<K, V>> e : map.entrySet())
98 {
99 final SoftReferenceElementDescriptor<K, V> sred = (SoftReferenceElementDescriptor<K, V>) e.getValue();
100 if (sred.getCacheElement() != null)
101 {
102 keys.add(e.getKey());
103 }
104 }
105
106 return keys;
107 }
108
109
110
111
112
113
114 @Override
115 public int getSize()
116 {
117 int size = 0;
118 for (final MemoryElementDescriptor<K, V> me : map.values())
119 {
120 final SoftReferenceElementDescriptor<K, V> sred = (SoftReferenceElementDescriptor<K, V>) me;
121 if (sred.getCacheElement() != null)
122 {
123 size++;
124 }
125 }
126 return size;
127 }
128
129
130
131
132 @Override
133 public IStats getStatistics()
134 {
135 final IStats stats = super.getStatistics();
136 stats.setTypeName("Soft Reference Memory Cache");
137
138 final List<IStatElement<?>> elems = stats.getStatElements();
139 final int emptyrefs = map.size() - getSize();
140 elems.add(new StatElement<>("Empty References", Integer.valueOf(emptyrefs)));
141 elems.add(new StatElement<>("Strong References", Integer.valueOf(strongReferences.size())));
142
143 return stats;
144 }
145
146
147
148
149
150
151
152 @Override
153 protected void lockedGetElement(final MemoryElementDescriptor<K, V> me)
154 {
155 final ICacheElement<K, V> val = me.getCacheElement();
156 val.getElementAttributes().setLastAccessTimeNow();
157
158
159 strongReferences.add(val);
160 trimStrongReferences();
161 }
162
163
164
165
166
167
168
169 @Override
170 protected void lockedRemoveElement(final MemoryElementDescriptor<K, V> me)
171 {
172 strongReferences.remove(me.getCacheElement());
173 }
174
175
176
177
178
179 @Override
180 protected void lockedRemoveAll()
181 {
182 strongReferences.clear();
183 }
184
185
186
187
188
189
190
191 @Override
192 public void update(final ICacheElement<K, V> ce) throws IOException
193 {
194 putCnt.incrementAndGet();
195 ce.getElementAttributes().setLastAccessTimeNow();
196
197 lock.lock();
198
199 try
200 {
201 map.put(ce.getKey(), new SoftReferenceElementDescriptor<>(ce));
202 strongReferences.add(ce);
203 trimStrongReferences();
204 }
205 finally
206 {
207 lock.unlock();
208 }
209 }
210
211
212
213
214
215 private void trimStrongReferences()
216 {
217 final int max = getCacheAttributes().getMaxObjects();
218 final int startsize = strongReferences.size();
219
220 for (int cursize = startsize; cursize > max; cursize--)
221 {
222 final ICacheElement<K, V> ce = strongReferences.poll();
223 waterfal(ce);
224 }
225 }
226
227
228
229
230
231
232
233
234 @Override
235 public int freeElements(final int numberToFree) throws IOException
236 {
237 return 0;
238 }
239 }