/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.stress.journal;
import java.io.File;
import java.io.FilenameFilter;
import org.apache.activemq.artemis.core.io.SequentialFileFactory;
import org.apache.activemq.artemis.core.io.nio.NIOSequentialFileFactory;
import org.apache.activemq.artemis.core.journal.impl.JournalImpl;
import org.apache.activemq.artemis.tests.unit.core.journal.impl.JournalImplTestBase;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.apache.activemq.artemis.utils.SimpleIDGenerator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* This class will control mix up compactor between each operation of a test
*/
public abstract class MixupCompactorTestBase extends JournalImplTestBase {
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
private ReusableLatch startedCompactingLatch = null;
private ReusableLatch releaseCompactingLatch = null;
private Thread tCompact = null;
int startCompactAt;
int joinCompactAt;
int secondCompactAt;
int currentOperation;
SimpleIDGenerator idGen = new SimpleIDGenerator(1000);
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
// Public --------------------------------------------------------
@Override
@Before
public void setUp() throws Exception {
super.setUp();
tCompact = null;
startedCompactingLatch = new ReusableLatch(1);
releaseCompactingLatch = new ReusableLatch(1);
setup(2, 60 * 1024, false);
}
@Override
@After
public void tearDown() throws Exception {
File testDir = new File(getTestDir());
File[] files = testDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.startsWith(filePrefix) && name.endsWith(fileExtension);
}
});
for (File file : files) {
Assert.assertEquals("File " + file + " doesn't have the expected number of bytes", fileSize, file.length());
}
super.tearDown();
}
@Override
public void createJournal() throws Exception {
journal = new JournalImpl(fileSize, minFiles, minFiles, 0, 0, fileFactory, filePrefix, fileExtension, maxAIO) {
@Override
public void onCompactDone() {
startedCompactingLatch.countDown();
try {
releaseCompactingLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
journal.setAutoReclaim(false);
}
@Test
public void testMixOperations() throws Exception {
currentOperation = 0;
internalTest();
int MAX_OPERATIONS = testMix(-1, -1, -1);
System.out.println("Using MAX_OPERATIONS = " + MAX_OPERATIONS);
for (int startAt = 0; startAt < MAX_OPERATIONS; startAt++) {
for (int joinAt = startAt; joinAt < MAX_OPERATIONS; joinAt++) {
for (int secondAt = joinAt; secondAt < MAX_OPERATIONS; secondAt++) {
System.out.println("start=" + startAt + ", join=" + joinAt + ", second=" + secondAt);
try {
tearDown();
setUp();
testMix(startAt, joinAt, secondAt);
} catch (Throwable e) {
throw new Exception("Error at compact=" + startCompactAt +
", joinCompactAt=" +
joinCompactAt +
", secondCompactAt=" +
secondCompactAt, e);
}
}
}
}
}
protected int testMix(final int startAt, final int joinAt, final int secondAt) throws Exception {
startCompactAt = startAt;
joinCompactAt = joinAt;
secondCompactAt = secondAt;
currentOperation = 0;
internalTest();
return currentOperation;
}
@Override
protected void beforeJournalOperation() throws Exception {
checkJournalOperation();
}
/**
* @throws InterruptedException
* @throws Exception
*/
protected void checkJournalOperation() throws Exception {
if (startCompactAt == currentOperation) {
threadCompact();
}
if (joinCompactAt == currentOperation) {
joinCompact();
}
if (secondCompactAt == currentOperation) {
journal.testCompact();
}
currentOperation++;
}
protected abstract void internalTest() throws Exception;
private void joinCompact() throws InterruptedException {
releaseCompactingLatch.countDown();
tCompact.join();
tCompact = null;
}
private void threadCompact() throws InterruptedException {
tCompact = new Thread() {
@Override
public void run() {
try {
journal.testCompact();
} catch (Exception e) {
e.printStackTrace();
}
}
};
tCompact.start();
startedCompactingLatch.await();
}
@Override
protected SequentialFileFactory getFileFactory() throws Exception {
return new NIOSequentialFileFactory(getTestDirfile(), 1);
}
}