@@ -68,6 +68,7 @@ public class CachingHttpContentFactory implements HttpContent.Factory
68
68
private final HttpContent .Factory _authority ;
69
69
private final ConcurrentHashMap <String , CachingHttpContent > _cache = new ConcurrentHashMap <>();
70
70
private final AtomicLong _cachedSize = new AtomicLong ();
71
+ private final AtomicBoolean _shrinking = new AtomicBoolean ();
71
72
private final ByteBufferPool _bufferPool ;
72
73
private int _maxCachedFileSize = DEFAULT_MAX_CACHED_FILE_SIZE ;
73
74
private int _maxCachedFiles = DEFAULT_MAX_CACHED_FILES ;
@@ -148,35 +149,46 @@ public void setUseDirectByteBuffers(boolean useDirectByteBuffers)
148
149
149
150
private void shrinkCache ()
150
151
{
151
- // While we need to shrink
152
- int numCacheEntries = _cache .size ();
153
- while (numCacheEntries > 0 && (numCacheEntries > _maxCachedFiles || _cachedSize .get () > _maxCacheSize ))
152
+ // Only 1 thread shrinking at once
153
+ if (_shrinking .compareAndSet (false , true ))
154
154
{
155
- // Scan the entire cache and generate an ordered list by last accessed time.
156
- SortedSet <CachingHttpContent > sorted = new TreeSet <>((c1 , c2 ) ->
155
+ try
157
156
{
158
- long delta = NanoTime .elapsed (c2 .getLastAccessedNanos (), c1 .getLastAccessedNanos ());
159
- if (delta != 0 )
160
- return delta < 0 ? -1 : 1 ;
161
-
162
- delta = c1 .getContentLengthValue () - c2 .getContentLengthValue ();
163
- if (delta != 0 )
164
- return delta < 0 ? -1 : 1 ;
165
-
166
- return c1 .getKey ().compareTo (c2 .getKey ());
167
- });
168
- sorted .addAll (_cache .values ());
169
-
170
- // TODO: Can we remove the buffers from the content before evicting.
171
- // Invalidate least recently used first
172
- for (CachingHttpContent content : sorted )
157
+ // While we need to shrink
158
+ int numCacheEntries = _cache .size ();
159
+ while (numCacheEntries > 0 && (numCacheEntries > _maxCachedFiles || _cachedSize .get () > _maxCacheSize ))
160
+ {
161
+ // Scan the entire cache and generate an ordered list by last accessed time.
162
+ SortedSet <CachingHttpContent > sorted = new TreeSet <>((c1 , c2 ) ->
163
+ {
164
+ long delta = NanoTime .elapsed (c2 .getLastAccessedNanos (), c1 .getLastAccessedNanos ());
165
+ if (delta != 0 )
166
+ return delta < 0 ? -1 : 1 ;
167
+
168
+ delta = c1 .getContentLengthValue () - c2 .getContentLengthValue ();
169
+ if (delta != 0 )
170
+ return delta < 0 ? -1 : 1 ;
171
+
172
+ return c1 .getKey ().compareTo (c2 .getKey ());
173
+ });
174
+ sorted .addAll (_cache .values ());
175
+
176
+ // TODO: Can we remove the buffers from the content before evicting.
177
+ // Invalidate least recently used first
178
+ for (CachingHttpContent content : sorted )
179
+ {
180
+ if (_cache .size () <= _maxCachedFiles && _cachedSize .get () <= _maxCacheSize )
181
+ break ;
182
+ removeFromCache (content );
183
+ }
184
+
185
+ numCacheEntries = _cache .size ();
186
+ }
187
+ }
188
+ finally
173
189
{
174
- if (_cache .size () <= _maxCachedFiles && _cachedSize .get () <= _maxCacheSize )
175
- break ;
176
- removeFromCache (content );
190
+ _shrinking .set (false );
177
191
}
178
-
179
- numCacheEntries = _cache .size ();
180
192
}
181
193
}
182
194
0 commit comments