diff --git a/source/java/org/alfresco/repo/content/caching/cleanup/CachedContentCleaner.java b/source/java/org/alfresco/repo/content/caching/cleanup/CachedContentCleaner.java index f1bd735161..44278bc88e 100644 --- a/source/java/org/alfresco/repo/content/caching/cleanup/CachedContentCleaner.java +++ b/source/java/org/alfresco/repo/content/caching/cleanup/CachedContentCleaner.java @@ -20,7 +20,6 @@ package org.alfresco.repo.content.caching.cleanup; import java.io.File; import java.util.Date; -import java.util.concurrent.locks.ReentrantReadWriteLock; import org.alfresco.repo.content.caching.CacheFileProps; import org.alfresco.repo.content.caching.ContentCacheImpl; @@ -46,7 +45,6 @@ public class CachedContentCleaner extends Thread implements FileHandler, Applica private ContentCacheImpl cache; // impl specific functionality required private long minFileAgeMillis = 0; private Integer maxDeleteWatchCount = 1; - private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private boolean running; private UsageTracker usageTracker; private long newDiskUsage; @@ -58,7 +56,6 @@ public class CachedContentCleaner extends Thread implements FileHandler, Applica private Date timeFinished; private ApplicationEventPublisher eventPublisher; private long targetReductionBytes; - private boolean cleanRequested; private String reasonMessage; @@ -99,9 +96,9 @@ public class CachedContentCleaner extends Thread implements FileHandler, Applica execute(reason); } - private synchronized void doClean() - { - while (running || (!cleanRequested)) + private void doClean() + { + synchronized(this) { try { @@ -112,7 +109,6 @@ public class CachedContentCleaner extends Thread implements FileHandler, Applica // Nothing to do. } } - running = true; if (log.isInfoEnabled()) { @@ -138,18 +134,19 @@ public class CachedContentCleaner extends Thread implements FileHandler, Applica ", target: " + targetReductionBytes + " bytes"); } - cleanRequested = false; this.targetReductionBytes = 0; running = false; - notifyAll(); + synchronized(this) + { + notifyAll(); + } } public synchronized void execute(String reasonMessage) { this.reasonMessage = reasonMessage; - cleanRequested = true; notifyAll(); } @@ -386,15 +383,7 @@ public class CachedContentCleaner extends Thread implements FileHandler, Applica public boolean isRunning() { - lock.readLock().lock(); - try - { - return running; - } - finally - { - lock.readLock().unlock(); - } + return running; } public long getNumFilesSeen() diff --git a/source/java/org/alfresco/repo/content/caching/quota/StandardQuotaStrategyTest.java b/source/java/org/alfresco/repo/content/caching/quota/StandardQuotaStrategyTest.java index ab1df2a376..78e0384777 100644 --- a/source/java/org/alfresco/repo/content/caching/quota/StandardQuotaStrategyTest.java +++ b/source/java/org/alfresco/repo/content/caching/quota/StandardQuotaStrategyTest.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.List; import org.alfresco.repo.content.ContentContext; @@ -48,7 +47,6 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.mozilla.javascript.ObjToIntMap.Iterator; import org.springframework.context.ApplicationContext; /** @@ -191,4 +189,82 @@ public class StandardQuotaStrategyTest { return FileUtils.listFiles(cacheRoot, new SuffixFileFilter(".bin"), TrueFileFilter.INSTANCE); } + + + /** + * Not a unit test, but useful to fire up a lot of writers that will push the + * CachingContentStore's StandardQuotaStrategy beyond the panic threshold. The + * behaviour can then be monitored with, for example, a profiler. + * + * @throws Exception + */ + private void concurrencySmokeTest() throws Exception + { + StandardQuotaStrategyTest.beforeClass(); + setUp(); + // Need to set maxDeleteWatch count to > 0 + // (0 is useful in unit tests, but for real usage must not be used) + cleaner.setMaxDeleteWatchCount(1); + + final int numThreads = 100; + Thread[] writers = new Thread[numThreads]; + for (int i = 0; i < numThreads; i++) + { + final String threadName = "WriterThread[" + i + "]"; + Runnable runnable = new Runnable() + { + @Override + public void run() + { + while (true) + { + writeFile(); + pause(); + } + } + + private void writeFile() + { + try + { + writeSingleFileInMB(1); + } + catch (IOException error) + { + throw new RuntimeException(threadName + " couldn't write file.", error); + } + } + + private void pause() + { + long pauseTimeMillis = Math.round(Math.random() * 2000); + try + { + Thread.sleep(pauseTimeMillis); + } + catch (InterruptedException error) + { + // Swallow the exception and carry on. + System.out.println(threadName + " InterruptedException."); + } + } + }; + Thread writerThread = new Thread(runnable); + writerThread.setName(threadName); + writers[i] = writerThread; + + writerThread.start(); + } + +// StandardQuotaStrategyTest.afterClass(); + } + + + + public static void main(String[] args) throws Exception + { + StandardQuotaStrategyTest test = new StandardQuotaStrategyTest(); + test.concurrencySmokeTest(); + } + } diff --git a/source/test-resources/cachingstore/test-std-quota-context.xml b/source/test-resources/cachingstore/test-std-quota-context.xml index da9ee10404..07580f16fd 100644 --- a/source/test-resources/cachingstore/test-std-quota-context.xml +++ b/source/test-resources/cachingstore/test-std-quota-context.xml @@ -16,7 +16,7 @@ class="org.alfresco.repo.content.caching.quota.StandardQuotaStrategy" init-method="init" destroy-method="shutdown"> - +