Index: CachingDataStore.java =================================================================== --- CachingDataStore.java (revision 1669518) +++ CachingDataStore.java (working copy) @@ -31,6 +31,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -127,6 +128,12 @@ */ protected final Map asyncDownloadCache = new ConcurrentHashMap(5); + /** + * In memory cache to hold {@link DataRecord#getLength()} against + * {@link DataIdentifier} + */ + protected Map recLengthCache = null; + protected Backend backend; /** @@ -236,6 +243,12 @@ * repository.xml. By default it is 100 */ private int asyncUploadLimit = 100; + + /** + * Size of {@link #recLengthCache}. Each entry consumes of approx 140 bytes. + * Default total memory consumption of {@link #recLengthCache} 28KB. + */ + private int recLengthCacheSize = 200; /** * Initialized the data store. If the path is not set, <repository @@ -333,6 +346,23 @@ new NamedThreadFactory("backend-file-download-worker")); cache = new LocalCache(path, tmpDir.getAbsolutePath(), cacheSize, cachePurgeTrigFactor, cachePurgeResizeFactor, asyncWriteCache); + /* + * Initialize LRU cache of size {@link #recLengthCacheSize} + */ + recLengthCache = Collections.synchronizedMap(new LinkedHashMap() { + + private static final long serialVersionUID = -8752749075395630485L; + + @Override + protected boolean removeEldestEntry( + Map.Entry eldest) { + if(size() > recLengthCacheSize) { + LOG.trace("evicted from recLengthCache [{}]", eldest.getKey()); + return true; + } + return false; + } + }); } catch (Exception e) { throw new RepositoryException(e); } @@ -424,6 +454,8 @@ identifier); usesIdentifier(identifier); return new CachingDataRecord(this, identifier); + } else if(recLengthCache.get(identifier) != null) { + return new CachingDataRecord(this, identifier); } else if (cache.getFileIfStored(fileName) != null || (existsAtBackend = backend.exists(identifier))) { if (existsAtBackend) { @@ -595,11 +627,18 @@ public long getLength(final DataIdentifier identifier) throws DataStoreException { String fileName = getFileName(identifier); - Long length = cache.getFileLength(fileName); + + Long length = recLengthCache.get(identifier); if (length != null) { - return length.longValue(); + LOG.debug(" identifier [{}] length fetched from recLengthCache", + identifier); + return length; + } else if ((length = cache.getFileLength(fileName)) != null) { + recLengthCache.put(identifier, length); + return length; } else { length = backend.getLength(identifier); + recLengthCache.put(identifier, length); asyncDownload(identifier); return length; } @@ -1128,6 +1167,10 @@ public void setProactiveCaching(boolean proactiveCaching) { this.proactiveCaching = proactiveCaching; } + + public void setRecLengthCacheSize(int recLengthCacheSize) { + this.recLengthCacheSize = recLengthCacheSize; + } public Backend getBackend() { return backend;