package ch.qos.logback.classic;
import java.util.concurrent.CyclicBarrier;
import org.junit.Test;
import ch.qos.logback.core.contention.AbstractMultiThreadedHarness;
import ch.qos.logback.core.contention.RunnableWithCounterAndDone;
import ch.qos.logback.core.status.StatusChecker;
public class LoggerContextConcurrentResetTest {
static int CONCURRENT_RESET_THREAD_COUNT = 10;
// see http://jira.qos.ch/browse/LOGBACK-397
@Test(timeout = 1000)
public void concurrentReset() throws InterruptedException {
LoggerContext loggerContext = new LoggerContext();
CyclicBarrier cyclicBarrier = new CyclicBarrier(CONCURRENT_RESET_THREAD_COUNT);
StatusChecker statusChecker = new StatusChecker(loggerContext);
int desiredResetCount = 100;
RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(loggerContext, cyclicBarrier);
Harness harness = new Harness((Resetter) runnableArray[0], desiredResetCount);
harness.execute(runnableArray);
statusChecker.assertIsErrorFree();
}
class Harness extends AbstractMultiThreadedHarness {
int desiredResetCount;
Resetter resetter;
Harness(Resetter resetter, int desiredResetCount) {
this.resetter = resetter;
this.desiredResetCount = desiredResetCount;
}
public void waitUntilEndCondition() throws InterruptedException {
while (resetter.getCounter() < desiredResetCount) {
Thread.yield();
}
}
}
static class GetLoggerRunnable extends RunnableWithCounterAndDone {
final int burstLength = 30;
LoggerContext loggerContext;
CyclicBarrier cyclicBarrier;
String nameSuffix;
GetLoggerRunnable(LoggerContext loggerContext, CyclicBarrier cyclicBarrier, String nameSuffix) {
this.loggerContext = loggerContext;
this.cyclicBarrier = cyclicBarrier;
this.nameSuffix = nameSuffix;
}
public void run() {
try {
cyclicBarrier.await();
} catch (Exception e) {
}
while (!isDone()) {
long i = counter % burstLength;
loggerContext.getLogger("org.bla." + nameSuffix + ".x" + i);
counter++;
if (i == 0) {
Thread.yield();
}
}
}
}
static class Resetter extends RunnableWithCounterAndDone {
LoggerContext loggerContext;
CyclicBarrier cyclicBarrier;
public int resetCount = 0;
Resetter(LoggerContext loggerContext, CyclicBarrier cyclicBarrier) {
this.loggerContext = loggerContext;
this.cyclicBarrier = cyclicBarrier;
}
public void run() {
try {
cyclicBarrier.await();
} catch (Exception e) {
}
while (!isDone()) {
loggerContext.reset();
counter++;
Thread.yield();
}
}
}
private RunnableWithCounterAndDone[] buildRunnableArray(LoggerContext loggerContext, CyclicBarrier cyclicBarrier) {
RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[CONCURRENT_RESET_THREAD_COUNT];
rArray[0] = new Resetter(loggerContext, cyclicBarrier);
for (int i = 1; i < CONCURRENT_RESET_THREAD_COUNT; i++) {
rArray[i] = new GetLoggerRunnable(loggerContext, cyclicBarrier, "mouse-" + i);
}
return rArray;
}
}