diff --git a/src/main/java/com/jakewharton/disklrucache/DiskLruCache.java b/src/main/java/com/jakewharton/disklrucache/DiskLruCache.java index b29a9d0..5846c30 100644 --- a/src/main/java/com/jakewharton/disklrucache/DiskLruCache.java +++ b/src/main/java/com/jakewharton/disklrucache/DiskLruCache.java @@ -34,6 +34,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.WeakHashMap; import java.util.concurrent.Callable; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -150,6 +151,7 @@ public final class DiskLruCache implements Closeable { private final LinkedHashMap lruEntries = new LinkedHashMap(0, 0.75f, true); private int redundantOpCount; + private final Map activeEditors = new WeakHashMap(); /** * To differentiate between old and current snapshots, each entry is given @@ -471,6 +473,8 @@ private synchronized Editor edit(String key, long expectedSequenceNumber) throws // Flush the journal before creating files to prevent file leaks. journalWriter.write(DIRTY + ' ' + key + '\n'); journalWriter.flush(); + + activeEditors.put(editor, null); return editor; } @@ -510,6 +514,7 @@ private synchronized void completeEdit(Editor editor, boolean success) throws IO if (entry.currentEditor != editor) { throw new IllegalStateException(); } + activeEditors.remove(editor); // If this edit is creating the entry for the first time, every index must have a value. if (success && !entry.readable) { @@ -654,6 +659,23 @@ public void delete() throws IOException { Util.deleteContents(directory); } + /** + * Deletes all of the stored values in the cache. This will delete + * all files in the cache directory including files that weren't created by + * the cache. Any uncommitted {@link Editor editors} will be ignored. + */ + public synchronized void evictAll() throws IOException { + Util.deleteContents(directory); + for (Editor editor : activeEditors.keySet()) { + editor.invalidate(); + } + activeEditors.clear(); + redundantOpCount = 0; + size = 0; + lruEntries.clear(); + rebuildJournal(); + } + private void validateKey(String key) { Matcher matcher = LEGAL_KEY_PATTERN.matcher(key); if (!matcher.matches()) { @@ -723,6 +745,7 @@ public final class Editor { private final boolean[] written; private boolean hasErrors; private boolean committed; + private boolean invalidated; private Editor(Entry entry) { this.entry = entry; @@ -807,6 +830,9 @@ public void set(int index, String value) throws IOException { * edit lock so another edit may be started on the same key. */ public void commit() throws IOException { + if (invalidated) { + return; + } if (hasErrors) { completeEdit(this, false); remove(entry.key); // The previous entry is stale. @@ -821,6 +847,9 @@ public void commit() throws IOException { * started on the same key. */ public void abort() throws IOException { + if (invalidated) { + return; + } completeEdit(this, false); } @@ -833,6 +862,10 @@ public void abortUnlessCommitted() { } } + public void invalidate() { + invalidated = true; + } + private class FaultHidingOutputStream extends FilterOutputStream { private FaultHidingOutputStream(OutputStream out) { super(out); diff --git a/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java b/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java index d9a42fb..94824d6 100644 --- a/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java +++ b/src/test/java/com/jakewharton/disklrucache/DiskLruCacheTest.java @@ -50,17 +50,16 @@ public final class DiskLruCacheTest { @Before public void setUp() throws Exception { javaTmpDir = System.getProperty("java.io.tmpdir"); cacheDir = new File(javaTmpDir, "DiskLruCacheTest"); + FileUtils.deleteQuietly(cacheDir); cacheDir.mkdir(); journalFile = new File(cacheDir, JOURNAL_FILE); journalBkpFile = new File(cacheDir, JOURNAL_FILE_BACKUP); - for (File file : cacheDir.listFiles()) { - file.delete(); - } cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE); } @After public void tearDown() throws Exception { cache.close(); + FileUtils.deleteQuietly(cacheDir); } @Test public void emptyCache() throws Exception { @@ -876,6 +875,36 @@ public final class DiskLruCacheTest { assertThat(cache.get("a")).isNull(); } + @Test public void evictRemovesEverythingFromCache() throws Exception { + set("k1", "A", "B"); + assertValue("k1", "A", "B"); + + cache.evictAll(); + assertAbsent("k1"); + assertThat(cache.size()).isZero(); + assertThat(cache.isClosed()).isFalse(); + + // Make sure we are still in a writable state + set("k1", "C", "D"); + assertValue("k1", "C", "D"); + } + + @Test public void editorCommittedAfterEvictDoesNothing() throws Exception { + DiskLruCache.Editor kOne = cache.edit("k"); + kOne.set(0, "A"); + kOne.set(1, "B"); + + cache.evictAll(); + + DiskLruCache.Editor kTwo = cache.edit("k"); + kTwo.set(0, "C"); + kTwo.set(1, "D"); + + kOne.commit(); + kTwo.commit(); + assertValue("k", "C", "D"); + } + private void assertJournalEquals(String... expectedBodyLines) throws Exception { List expectedLines = new ArrayList(); expectedLines.add(MAGIC);