1 package org.apache.commons.jcs.engine.memory.shrinking;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Set;
23
24 import org.apache.commons.jcs.engine.behavior.ICacheElement;
25 import org.apache.commons.jcs.engine.behavior.IElementAttributes;
26 import org.apache.commons.jcs.engine.control.CompositeCache;
27 import org.apache.commons.jcs.engine.control.event.behavior.ElementEventType;
28 import org.apache.commons.jcs.engine.memory.behavior.IMemoryCache;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32
33
34
35
36
37 public class ShrinkerThread<K, V>
38 implements Runnable
39 {
40
41 private static final Log log = LogFactory.getLog( ShrinkerThread.class );
42
43
44 private final CompositeCache<K, V> cache;
45
46
47 private final long maxMemoryIdleTime;
48
49
50 private final int maxSpoolPerRun;
51
52
53 private boolean spoolLimit = false;
54
55
56
57
58
59
60 public ShrinkerThread( CompositeCache<K, V> cache )
61 {
62 super();
63
64 this.cache = cache;
65
66 long maxMemoryIdleTimeSeconds = cache.getCacheAttributes().getMaxMemoryIdleTimeSeconds();
67
68 if ( maxMemoryIdleTimeSeconds < 0 )
69 {
70 this.maxMemoryIdleTime = -1;
71 }
72 else
73 {
74 this.maxMemoryIdleTime = maxMemoryIdleTimeSeconds * 1000;
75 }
76
77 this.maxSpoolPerRun = cache.getCacheAttributes().getMaxSpoolPerRun();
78 if ( this.maxSpoolPerRun != -1 )
79 {
80 this.spoolLimit = true;
81 }
82
83 }
84
85
86
87
88 @Override
89 public void run()
90 {
91 shrink();
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 protected void shrink()
110 {
111 if ( log.isDebugEnabled() )
112 {
113 log.debug( "Shrinking memory cache for: " + this.cache.getCacheName() );
114 }
115
116 IMemoryCache<K, V> memCache = cache.getMemoryCache();
117
118 try
119 {
120 Set<K> keys = memCache.getKeySet();
121 int size = keys.size();
122 if ( log.isDebugEnabled() )
123 {
124 log.debug( "Keys size: " + size );
125 }
126
127 ICacheElement<K, V> cacheElement;
128 IElementAttributes attributes;
129
130 int spoolCount = 0;
131
132 for (K key : keys)
133 {
134 cacheElement = memCache.getQuiet( key );
135
136 if ( cacheElement == null )
137 {
138 continue;
139 }
140
141 attributes = cacheElement.getElementAttributes();
142
143 boolean remove = false;
144
145 long now = System.currentTimeMillis();
146
147
148
149 if ( !cacheElement.getElementAttributes().getIsEternal() )
150 {
151 remove = cache.isExpired( cacheElement, now,
152 ElementEventType.EXCEEDED_MAXLIFE_BACKGROUND,
153 ElementEventType.EXCEEDED_IDLETIME_BACKGROUND );
154
155 if ( remove )
156 {
157 memCache.remove( cacheElement.getKey() );
158 }
159 }
160
161
162
163
164 if ( !remove && maxMemoryIdleTime != -1 )
165 {
166 if ( !spoolLimit || spoolCount < this.maxSpoolPerRun )
167 {
168 final long lastAccessTime = attributes.getLastAccessTime();
169
170 if ( lastAccessTime + maxMemoryIdleTime < now )
171 {
172 if ( log.isDebugEnabled() )
173 {
174 log.debug( "Exceeded memory idle time: " + cacheElement.getKey() );
175 }
176
177
178
179
180
181
182
183 spoolCount++;
184
185 memCache.remove( cacheElement.getKey() );
186
187 memCache.waterfal( cacheElement );
188
189 key = null;
190 cacheElement = null;
191 }
192 }
193 else
194 {
195 if ( log.isDebugEnabled() )
196 {
197 log.debug( "spoolCount = '" + spoolCount + "'; " + "maxSpoolPerRun = '" + maxSpoolPerRun
198 + "'" );
199 }
200
201
202 if ( spoolLimit && spoolCount >= this.maxSpoolPerRun )
203 {
204 return;
205 }
206 }
207 }
208 }
209 }
210 catch ( Throwable t )
211 {
212 log.info( "Unexpected trouble in shrink cycle", t );
213
214
215
216
217
218 return;
219 }
220 }
221 }