1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.fjank.jcache;
21
22 import java.lang.ref.ReferenceQueue;
23 import java.util.Iterator;
24 import javax.util.jcache.Attributes;
25 import javax.util.jcache.CacheAttributes;
26 import javax.util.jcache.CacheException;
27 import javax.util.jcache.CacheNotAvailableException;
28 import javax.util.jcache.NullObjectException;
29
30
31
32
33
34
35
36
37
38
39
40 public class CacheSweeper implements Runnable {
41
42 private static CacheSweeper _singleton;
43
44
45 private boolean active = false;
46
47
48
49
50 private CacheSweeper() {
51 }
52
53
54
55
56
57 public void run() {
58 CacheImpl cache = CacheImpl.getCache(true);
59 CacheAttributes attribs = cache.getAttributes();
60
61 while (active) {
62 try {
63 Thread.sleep(attribs.getCleanInterval() * 1000);
64 } catch (InterruptedException e) {
65
66 }
67 sweepCache();
68 }
69 }
70
71
72
73
74
75
76
77
78
79 private void sweepCache() {
80 CacheImpl cache = null;
81 try {
82 cache = CacheImpl.getCache(true);
83
84 int maxSize = cache.getAttributes().getMemoryCacheSize();
85 long maxBytes = maxSize * 1024 * 1024;
86 if (getMemoryCacheSize() >= maxBytes) {
87 writeToDisk();
88 }
89
90
91
92
93
94
95
96
97 CacheRegion reg = cache.getRegion();
98 sweepGroup(reg);
99 Iterator iter = cache.userRegionNames();
100 while(iter.hasNext()) {
101 Object key = iter.next();
102 CacheRegion userReg = cache.getRegion(key);
103 sweepGroup(userReg);
104 }
105 for(int i=0; i<3; i++) {
106 System.runFinalization();
107 System.gc();
108 try {
109 Thread.sleep(500);
110 } catch (InterruptedException e1) {;}
111 }
112
113
114
115
116 CacheObject cacheObj = null;
117 ReferenceQueue q = cache.getReferenceQueue();
118 while ((cacheObj = (CacheObject) q.poll()) != null) {
119 cacheObj.resetRefCount();
120 tryRemoval(cacheObj);
121 }
122
123 } catch (CacheException e) {
124 e.printStackTrace();
125 stopSweeper();
126 } catch (java.lang.IncompatibleClassChangeError e) {
127
128
129 if (cache != null) {
130 cache.close();
131 try {
132 cache.open();
133 } catch (CacheNotAvailableException ee) {
134 stopSweeper();
135 }
136 }
137 }
138 }
139
140
141
142
143
144
145
146
147 private void sweepGroup(CacheGroup group) throws NullObjectException {
148 Iterator iter = group.weakReferenceObjects.keySet().iterator();
149 while(iter.hasNext()) {
150 Object key = iter.next();
151 Object obj = group.weakReferenceObjects.get(key);
152 if(obj instanceof CacheObject) {
153 if(hasExpired((CacheObject) obj)) {
154 group.removeObjectReference(key);
155 }
156 }else if(obj instanceof CacheGroup) {
157 sweepGroup((CacheGroup) obj);
158 }else {
159 System.out.println("An unknown object ("+obj.getClass().getName()+") was discovered in the cache.");
160 break;
161 }
162 }
163 }
164
165
166
167
168
169
170
171
172
173
174 private boolean tryRemoval(final CacheObject cacheObj) throws NullObjectException {
175 if (hasExpired(cacheObj)) {
176 cacheObj.invalidate();
177 return true;
178 }
179 return false;
180 }
181 private boolean hasExpired(CacheObject obj) throws NullObjectException {
182 Attributes attributes = obj.getAttributes();
183 if(attributes==null) throw new NullObjectException("A null attributes was detected.");
184
185
186
187
188 if(attributes.getTimeToLive()==-1) {
189 return false;
190 }
191 if(attributes.getLoader()!=null) return false;
192 long now = System.currentTimeMillis();
193 long timealive = (now - attributes.getCreateTime()) / 1000;
194
195
196 if (timealive >= attributes.getTimeToLive()) {
197 return true;
198 }
199 return false;
200 }
201
202
203
204
205
206
207
208
209
210
211
212 private void writeToDisk() {
213 }
214
215
216
217
218
219
220
221
222
223
224 private long getMemoryCacheSize() {
225 return 0;
226 }
227
228
229
230
231 synchronized void startSweeper() {
232
233 if (!_singleton.active){
234 active=true;
235 CacheThreadFactory fact = CacheThreadFactory.getInstance();
236 fact.setName("Fjanks FKache - CacheSweeper");
237 fact.setDaemon(true);
238 fact.newThread(this).start();
239
240 }
241 }
242
243
244
245
246
247 synchronized void stopSweeper() {
248 active = false;
249
250 }
251
252
253
254
255 public static synchronized CacheSweeper getInstance() {
256 if (_singleton == null) {
257 _singleton = new CacheSweeper();
258
259
260
261 }
262 return _singleton;
263 }
264
265
266
267
268
269 static synchronized void removeInstance() {
270 if (_singleton != null) {
271 if (_singleton.active){
272 _singleton.stopSweeper();
273 }
274 _singleton = null;
275
276 }
277 }
278 }