/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.imagepipeline.cache;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import android.graphics.Bitmap;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.references.CloseableReference;
/**
* Inspects values cached in bitmap memory cache.
*/
public class CountingMemoryCacheInspector<K, V> {
/**
* Cache entry info for use by dumpers.
*/
public static class DumpInfoEntry<K, V> {
// The key is immutable, so it's safe to store that directly
public final K key;
// The value
public final CloseableReference<V> value;
public DumpInfoEntry(
final K key,
final CloseableReference<V> valueRef) {
this.key = Preconditions.checkNotNull(key);
this.value = CloseableReference.cloneOrNull(valueRef);
}
public void release() {
CloseableReference.closeSafely(value);
}
}
/**
* Info about the status of the cache for use by dumpers.
*/
public static class DumpInfo<K, V> {
public final int maxSize;
public final int maxEntriesCount;
public final int maxEntrySize;
public final int size;
public final int lruSize;
public final List<DumpInfoEntry<K, V>> lruEntries;
public final List<DumpInfoEntry<K, V>> sharedEntries;
public final Map<Bitmap, Object> otherEntries;
public DumpInfo(int size, int lruSize, MemoryCacheParams params) {
maxSize = params.maxCacheSize;
maxEntriesCount = params.maxCacheEntries;
maxEntrySize = params.maxCacheEntrySize;
this.size = size;
this.lruSize = lruSize;
lruEntries = new ArrayList<>();
sharedEntries = new ArrayList<>();
otherEntries = new HashMap<>();
}
public void release() {
for (DumpInfoEntry entry : lruEntries) {
entry.release();
}
for (DumpInfoEntry entry : sharedEntries) {
entry.release();
}
}
}
private final CountingMemoryCache<K, V> mCountingBitmapCache;
public CountingMemoryCacheInspector(CountingMemoryCache<K, V> countingBitmapCache) {
mCountingBitmapCache = countingBitmapCache;
}
/**
* Iterates through all entries cached in counting cache and builds snapshot of its content.
* This should be used by tools that need to know current content of given cache.
* <p> Caller should call release method on returned DumpInfo after it is done with
* examining cache contents
*/
public DumpInfo dumpCacheContent() {
synchronized (mCountingBitmapCache) {
DumpInfo<K, V> dumpInfo = new DumpInfo<>(
mCountingBitmapCache.getSizeInBytes(),
mCountingBitmapCache.getEvictionQueueSizeInBytes(),
mCountingBitmapCache.mMemoryCacheParams);
final List<LinkedHashMap.Entry<K, CountingMemoryCache.Entry<K, V>>> cachedEntries =
mCountingBitmapCache.mCachedEntries.getMatchingEntries(null);
for (LinkedHashMap.Entry<K, CountingMemoryCache.Entry<K, V>> cachedEntry : cachedEntries) {
CountingMemoryCache.Entry<K, V> entry = cachedEntry.getValue();
DumpInfoEntry<K, V> dumpEntry = new DumpInfoEntry<>(entry.key, entry.valueRef);
if (entry.clientCount > 0) {
dumpInfo.sharedEntries.add(dumpEntry);
} else {
dumpInfo.lruEntries.add(dumpEntry);
}
}
for (Map.Entry<Bitmap, Object> entry
: mCountingBitmapCache.mOtherEntries.entrySet()) {
if (entry != null && !entry.getKey().isRecycled()) {
dumpInfo.otherEntries.put(entry.getKey(), entry.getValue());
}
}
return dumpInfo;
}
}
}