001package ch.qos.logback.classic;
002
003import java.util.concurrent.CyclicBarrier;
004
005import org.junit.Ignore;
006import org.junit.Test;
007
008import ch.qos.logback.core.contention.AbstractMultiThreadedHarness;
009import ch.qos.logback.core.contention.RunnableWithCounterAndDone;
010import ch.qos.logback.core.testUtil.StatusChecker;
011
012@Ignore
013public class LoggerContextConcurrentResetTest {
014    static int CONCURRENT_RESET_THREAD_COUNT = 10;
015
016    // see http://jira.qos.ch/browse/LOGBACK-397
017    @Test(timeout = 1000)
018    public void concurrentReset() throws InterruptedException {
019        LoggerContext loggerContext = new LoggerContext();
020        CyclicBarrier cyclicBarrier = new CyclicBarrier(CONCURRENT_RESET_THREAD_COUNT);
021        StatusChecker statusChecker = new StatusChecker(loggerContext);
022        int desiredResetCount = 100;
023        RunnableWithCounterAndDone[] runnableArray = buildRunnableArray(loggerContext, cyclicBarrier);
024        Harness harness = new Harness((Resetter) runnableArray[0], desiredResetCount);
025        harness.execute(runnableArray);
026        statusChecker.assertIsErrorFree();
027    }
028
029    class Harness extends AbstractMultiThreadedHarness {
030        int desiredResetCount;
031        Resetter resetter;
032
033        Harness(Resetter resetter, int desiredResetCount) {
034            this.resetter = resetter;
035            this.desiredResetCount = desiredResetCount;
036        }
037
038        public void waitUntilEndCondition() throws InterruptedException {
039            while (resetter.getCounter() < desiredResetCount) {
040                Thread.yield();
041            }
042        }
043    }
044
045    static class GetLoggerRunnable extends RunnableWithCounterAndDone {
046
047        final int burstLength = 30;
048        LoggerContext loggerContext;
049        CyclicBarrier cyclicBarrier;
050        String nameSuffix;
051
052        GetLoggerRunnable(LoggerContext loggerContext, CyclicBarrier cyclicBarrier, String nameSuffix) {
053            this.loggerContext = loggerContext;
054            this.cyclicBarrier = cyclicBarrier;
055            this.nameSuffix = nameSuffix;
056        }
057
058        public void run() {
059            try {
060                cyclicBarrier.await();
061            } catch (Exception e) {
062            }
063
064            while (!isDone()) {
065                long i = counter % burstLength;
066                loggerContext.getLogger("org.bla." + nameSuffix + ".x" + i);
067                counter++;
068                if (i == 0) {
069                    Thread.yield();
070                }
071            }
072        }
073    }
074
075    static class Resetter extends RunnableWithCounterAndDone {
076        LoggerContext loggerContext;
077        CyclicBarrier cyclicBarrier;
078        public int resetCount = 0;
079
080        Resetter(LoggerContext loggerContext, CyclicBarrier cyclicBarrier) {
081            this.loggerContext = loggerContext;
082            this.cyclicBarrier = cyclicBarrier;
083        }
084
085        public void run() {
086            try {
087                cyclicBarrier.await();
088            } catch (Exception e) {
089            }
090            while (!isDone()) {
091                loggerContext.reset();
092                counter++;
093                Thread.yield();
094            }
095        }
096    }
097
098    private RunnableWithCounterAndDone[] buildRunnableArray(LoggerContext loggerContext, CyclicBarrier cyclicBarrier) {
099        RunnableWithCounterAndDone[] rArray = new RunnableWithCounterAndDone[CONCURRENT_RESET_THREAD_COUNT];
100        rArray[0] = new Resetter(loggerContext, cyclicBarrier);
101        for (int i = 1; i < CONCURRENT_RESET_THREAD_COUNT; i++) {
102            rArray[i] = new GetLoggerRunnable(loggerContext, cyclicBarrier, "mouse-" + i);
103        }
104        return rArray;
105    }
106}