/*
* 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.unit.core.journal.impl;
import java.io.File;
import java.nio.ByteBuffer;
import java.util.List;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQIOErrorException;
import org.apache.activemq.artemis.core.io.SequentialFile;
import org.apache.activemq.artemis.core.journal.EncodingSupport;
import org.apache.activemq.artemis.core.journal.RecordInfo;
import org.apache.activemq.artemis.core.journal.TestableJournal;
import org.apache.activemq.artemis.core.journal.impl.JournalImpl;
import org.apache.activemq.artemis.tests.unit.UnitTestLogger;
import org.apache.activemq.artemis.tests.unit.core.journal.impl.fakes.SimpleEncoding;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
public abstract class JournalImplTestUnit extends JournalImplTestBase {
@Override
@After
public void tearDown() throws Exception {
//stop journal first to let it manage its files
stopComponent(journal);
List<String> files = fileFactory.listFiles(fileExtension);
for (String file : files) {
SequentialFile seqFile = fileFactory.createSequentialFile(file);
Assert.assertEquals(fileSize, seqFile.size());
}
super.tearDown();
}
// General tests
// =============
@Test
public void testState() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
try {
load();
Assert.fail("Should throw exception");
} catch (IllegalStateException e) {
// OK
}
startJournal();
try {
startJournal();
Assert.fail("Should throw exception");
} catch (IllegalStateException e) {
// OK
}
stopJournal();
startJournal();
load();
try {
load();
Assert.fail("Should throw exception");
} catch (IllegalStateException e) {
// OK
}
try {
startJournal();
Assert.fail("Should throw exception");
} catch (IllegalStateException e) {
// OK
}
stopJournal();
}
@Test
public void testRestartJournal() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
stopJournal();
startJournal();
load();
byte[] record = new byte[1000];
for (int i = 0; i < record.length; i++) {
record[i] = (byte) 'a';
}
// Appending records after restart should be valid (not throwing any
// exceptions)
for (int i = 0; i < 100; i++) {
journal.appendAddRecord(1, (byte) 1, new SimpleEncoding(2, (byte) 'a'), false);
}
stopJournal();
}
@Test
public void testParams() throws Exception {
try {
new JournalImpl(JournalImpl.MIN_FILE_SIZE - 1, 10, 10, 0, 0, fileFactory, filePrefix, fileExtension, 1);
Assert.fail("Should throw exception");
} catch (IllegalArgumentException e) {
// Ok
}
try {
new JournalImpl(10 * 1024, 1, 0, 0, 0, fileFactory, filePrefix, fileExtension, 1);
Assert.fail("Should throw exception");
} catch (IllegalArgumentException e) {
// Ok
}
try {
new JournalImpl(10 * 1024, 10, 0, 0, 0, null, filePrefix, fileExtension, 1);
Assert.fail("Should throw exception");
} catch (NullPointerException e) {
// Ok
}
try {
new JournalImpl(10 * 1024, 10, 0, 0, 0, fileFactory, null, fileExtension, 1);
Assert.fail("Should throw exception");
} catch (IllegalArgumentException e) {
// Ok
}
try {
new JournalImpl(10 * 1024, 10, 0, 0, 0, fileFactory, filePrefix, null, 1);
Assert.fail("Should throw exception");
} catch (IllegalArgumentException e) {
// Ok
}
try {
new JournalImpl(10 * 1024, 10, 0, 0, 0, fileFactory, filePrefix, null, 0);
Assert.fail("Should throw exception");
} catch (IllegalArgumentException e) {
// Ok
}
}
@Test
public void testVersionCheck() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
stopJournal();
fileFactory.start();
List<String> files = fileFactory.listFiles(fileExtension);
for (String fileStr : files) {
SequentialFile file = fileFactory.createSequentialFile(fileStr);
ByteBuffer buffer = fileFactory.newBuffer(JournalImpl.SIZE_HEADER);
for (int i = 0; i < JournalImpl.SIZE_HEADER; i++) {
buffer.put(Byte.MAX_VALUE);
}
buffer.rewind();
file.open();
file.position(0);
file.writeDirect(buffer, sync);
file.close();
}
fileFactory.stop();
startJournal();
boolean exceptionHappened = false;
try {
load();
} catch (ActiveMQIOErrorException ioe) {
exceptionHappened = true;
} catch (ActiveMQException e) {
Assert.fail("invalid exception type:" + e.getType());
}
Assert.assertTrue("Exception was expected", exceptionHappened);
stopJournal();
}
// Validates the if the journal will work when the IDs are over MaxInt
@Test
public void testMaxInt() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
stopJournal();
fileFactory.start();
List<String> files = fileFactory.listFiles(fileExtension);
long fileID = Integer.MAX_VALUE;
for (String fileStr : files) {
SequentialFile file = fileFactory.createSequentialFile(fileStr);
file.open();
JournalImpl.initFileHeader(fileFactory, file, journal.getUserVersion(), fileID++);
file.close();
}
fileFactory.stop();
startJournal();
load();
for (long i = 0; i < 100; i++) {
add(i);
stopJournal();
startJournal();
loadAndCheck();
}
stopJournal();
}
@Test
public void testFilesImmediatelyAfterload() throws Exception {
try {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files.size());
for (String file : files) {
Assert.assertTrue(file.startsWith(filePrefix));
}
stopJournal();
resetFileFactory();
setup(20, 10 * 1024, true);
createJournal();
startJournal();
load();
files = fileFactory.listFiles(fileExtension);
Assert.assertEquals(20, files.size());
for (String file : files) {
Assert.assertTrue(file.startsWith(filePrefix));
}
stopJournal();
fileExtension = "tim";
resetFileFactory();
setup(17, 10 * 1024, true);
createJournal();
startJournal();
load();
files = fileFactory.listFiles(fileExtension);
Assert.assertEquals(17, files.size());
for (String file : files) {
Assert.assertTrue(file.startsWith(filePrefix));
}
stopJournal();
filePrefix = "echidna";
resetFileFactory();
setup(11, 10 * 1024, true);
createJournal();
startJournal();
load();
files = fileFactory.listFiles(fileExtension);
Assert.assertEquals(11, files.size());
for (String file : files) {
Assert.assertTrue(file.startsWith(filePrefix));
}
stopJournal();
} finally {
filePrefix = "amq";
fileExtension = "amq";
}
}
@Test
public void testEmptyReopen() throws Exception {
setup(2, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
stopJournal();
setup(2, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files2.size());
for (String file : files1) {
Assert.assertTrue(files2.contains(file));
}
stopJournal();
}
@Test
public void testCreateFilesOnLoad() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
stopJournal();
// Now restart with different number of minFiles - should create 10 more
setup(20, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(20, files2.size());
for (String file : files1) {
Assert.assertTrue(files2.contains(file));
}
stopJournal();
}
@Test
public void testReduceFreeFiles() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
stopJournal();
setup(5, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files2.size());
for (String file : files1) {
Assert.assertTrue(files2.contains(file));
}
stopJournal();
}
private int calculateRecordsPerFile(final int fileSize, final int alignment, int recordSize) {
recordSize = calculateRecordSize(recordSize, alignment);
int headerSize = calculateRecordSize(JournalImpl.SIZE_HEADER, alignment);
return (fileSize - headerSize) / recordSize;
}
/**
* Use: calculateNumberOfFiles (fileSize, numberOfRecords, recordSize, numberOfRecords2, recordSize2, , ...., numberOfRecordsN, recordSizeN);
*/
private int calculateNumberOfFiles(TestableJournal journal, final int fileSize, final int alignment, final int... record) throws Exception {
if (journal != null) {
journal.flush();
}
int headerSize = calculateRecordSize(JournalImpl.SIZE_HEADER, alignment);
int currentPosition = headerSize;
int totalFiles = 0;
for (int i = 0; i < record.length; i += 2) {
int numberOfRecords = record[i];
int recordSize = calculateRecordSize(record[i + 1], alignment);
while (numberOfRecords > 0) {
int recordsFit = (fileSize - currentPosition) / recordSize;
if (numberOfRecords < recordsFit) {
currentPosition = currentPosition + numberOfRecords * recordSize;
numberOfRecords = 0;
} else if (recordsFit > 0) {
currentPosition = currentPosition + recordsFit * recordSize;
numberOfRecords -= recordsFit;
} else {
totalFiles++;
currentPosition = headerSize;
}
}
}
return totalFiles;
}
@Test
public void testCheckCreateMoreFiles() throws Exception {
setup(2, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Fill all the files
for (int i = 0; i < 91; i++) {
add(i);
}
int numberOfFiles = calculateNumberOfFiles(journal, 10 * 1024, journal.getAlignment(), 91, JournalImpl.SIZE_ADD_RECORD + recordLength);
Assert.assertEquals(numberOfFiles, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(91, journal.getIDMapSize());
List<String> files2 = fileFactory.listFiles(fileExtension);
// The Journal will aways have a file ready to be opened
Assert.assertEquals(numberOfFiles + 2, files2.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files2.contains(file));
}
// Now add some more
for (int i = 90; i < 95; i++) {
add(i);
}
numberOfFiles = calculateNumberOfFiles(journal, 10 * 1024, journal.getAlignment(), 95, JournalImpl.SIZE_ADD_RECORD + recordLength);
Assert.assertEquals(numberOfFiles, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(95, journal.getIDMapSize());
List<String> files3 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(numberOfFiles + 2, files3.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files3.contains(file));
}
// And a load more
for (int i = 95; i < 200; i++) {
add(i);
}
numberOfFiles = calculateNumberOfFiles(journal, 10 * 1024, journal.getAlignment(), 200, JournalImpl.SIZE_ADD_RECORD + recordLength);
Assert.assertEquals(numberOfFiles, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(200, journal.getIDMapSize());
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(numberOfFiles + 2, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files4.contains(file));
}
stopJournal();
}
@Test
public void testOrganicallyGrowNoLimit() throws Exception {
setup(2, -1, 10 * 1024, true, 50);
createJournal();
journal.setAutoReclaim(true);
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Fill all the files
for (int i = 0; i < 200; i++) {
add(i);
journal.forceMoveNextFile();
}
for (int i = 0; i < 200; i++) {
delete(i);
}
journal.forceMoveNextFile();
journal.checkReclaimStatus();
files1 = fileFactory.listFiles(fileExtension);
Assert.assertTrue(files1.size() > 200);
int numberOfFiles = files1.size();
for (int i = 300; i < 350; i++) {
add(i);
journal.forceMoveNextFile();
}
journal.checkReclaimStatus();
files1 = fileFactory.listFiles(fileExtension);
Assert.assertTrue(files1.size() > 200);
Assert.assertEquals(numberOfFiles, files1.size());
System.out.println("we have " + files1.size() + " files now");
stopJournal();
}
@Test
public void testOrganicallyWithALimit() throws Exception {
setup(2, 5, 10 * 1024, true, 50);
createJournal();
journal.setAutoReclaim(true);
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Fill all the files
for (int i = 0; i < 200; i++) {
add(i);
journal.forceMoveNextFile();
}
journal.checkReclaimStatus();
for (int i = 0; i < 200; i++) {
delete(i);
}
journal.forceMoveNextFile();
journal.checkReclaimStatus();
files1 = fileFactory.listFiles(fileExtension);
Assert.assertTrue("supposed to have less than 10 but it had " + files1.size() + " files created", files1.size() < 10);
stopJournal();
}
// Validate the methods that are used on assertions
@Test
public void testCalculations() throws Exception {
Assert.assertEquals(0, calculateNumberOfFiles(journal, 10 * 1024, 1, 1, 10, 2, 20));
Assert.assertEquals(0, calculateNumberOfFiles(journal, 10 * 1024, 512, 1, 1));
Assert.assertEquals(0, calculateNumberOfFiles(journal, 10 * 1024, 512, 19, 10));
Assert.assertEquals(1, calculateNumberOfFiles(journal, 10 * 1024, 512, 20, 10));
Assert.assertEquals(0, calculateNumberOfFiles(journal, 3000, 500, 2, 1000, 1, 500));
Assert.assertEquals(1, calculateNumberOfFiles(journal, 3000, 500, 2, 1000, 1, 1000));
Assert.assertEquals(9, calculateNumberOfFiles(journal, 10240, 1, 90, 1038, 45, 10));
Assert.assertEquals(11, calculateNumberOfFiles(journal, 10 * 1024, 512, 60, 14 + 1024, 30, 14));
}
@Test
public void testReclaim() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
int addRecordsPerFile = calculateRecordsPerFile(10 * 1024, journal.getAlignment(), JournalImpl.SIZE_ADD_RECORD + 1 + recordLength);
System.out.println(JournalImpl.SIZE_ADD_RECORD + 1 + recordLength);
// Fills exactly 10 files
int initialNumberOfAddRecords = addRecordsPerFile * 10;
for (int i = 0; i < initialNumberOfAddRecords; i++) {
add(i);
}
// We have already 10 files, but since we have the last file on exact
// size, the counter will be numberOfUsedFiles -1
Assert.assertEquals(9, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(initialNumberOfAddRecords, journal.getIDMapSize());
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(11, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files4.contains(file));
}
// Now delete half of them
for (int i = 0; i < initialNumberOfAddRecords / 2; i++) {
delete(i);
}
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(initialNumberOfAddRecords / 2, journal.getIDMapSize());
// Make sure the deletes aren't in the current file
for (int i = 0; i < 10; i++) {
add(initialNumberOfAddRecords + i);
}
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(initialNumberOfAddRecords / 2 + 10, journal.getIDMapSize());
checkAndReclaimFiles();
// Several of them should be reclaimed - and others deleted - the total
// number of files should not drop below
// 10
Assert.assertEquals(journal.getAlignment() == 1 ? 6 : 7, journal.getDataFilesCount());
Assert.assertEquals(journal.getAlignment() == 1 ? 2 : 1, journal.getFreeFilesCount());
Assert.assertEquals(initialNumberOfAddRecords / 2 + 10, journal.getIDMapSize());
List<String> files5 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files5.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
// Now delete the rest
for (int i = initialNumberOfAddRecords / 2; i < initialNumberOfAddRecords + 10; i++) {
delete(i);
}
// And fill the current file
for (int i = 110; i < 120; i++) {
add(i);
delete(i);
}
checkAndReclaimFiles();
Assert.assertEquals(journal.getAlignment() == 1 ? 0 : 1, journal.getDataFilesCount());
Assert.assertEquals(journal.getAlignment() == 1 ? 8 : 7, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files6 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files6.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
stopJournal();
}
@Test
public void testReclaimAddUpdateDeleteDifferentFiles1() throws Exception {
// Make sure there is one record per file
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(JournalImpl.SIZE_ADD_RECORD + 1 + recordLength, getAlignment()), true);
createJournal();
startJournal();
load();
add(1);
update(1);
delete(1);
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files1.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files2 = fileFactory.listFiles(fileExtension);
// 1 file for nextOpenedFile
Assert.assertEquals(4, files2.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
// 1 gets deleted and 1 gets reclaimed
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
stopJournal();
}
@Test
public void testReclaimAddUpdateDeleteDifferentFiles2() throws Exception {
// Make sure there is one record per file
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(JournalImpl.SIZE_ADD_RECORD + 1 + recordLength, getAlignment()), true);
createJournal();
startJournal();
load();
add(1);
update(1);
add(2);
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files1.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files2.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
stopJournal();
}
@Test
public void testReclaimTransactionalAddCommit() throws Exception {
testReclaimTransactionalAdd(true);
}
@Test
public void testReclaimTransactionalAddRollback() throws Exception {
testReclaimTransactionalAdd(false);
}
// TODO commit and rollback, also transactional deletes
private void testReclaimTransactionalAdd(final boolean commit) throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
for (int i = 0; i < 100; i++) {
addTx(1, i);
}
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 100, recordLength), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 100, recordLength) + 2, files2.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files2.contains(file));
}
checkAndReclaimFiles();
// Make sure nothing reclaimed
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 100, recordLength), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files3 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 100, recordLength) + 2, files3.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files3.contains(file));
}
// Add a load more updates
for (int i = 100; i < 200; i++) {
updateTx(1, i);
}
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength) + 2, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files4.contains(file));
}
checkAndReclaimFiles();
// Make sure nothing reclaimed
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files5 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(24, files5.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files5.contains(file));
}
// Now delete them
for (int i = 0; i < 200; i++) {
deleteTx(1, i);
}
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files7 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX) + 2, files7.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files7.contains(file));
}
checkAndReclaimFiles();
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
List<String> files8 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX) + 2, files8.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files8.contains(file));
}
// Commit
if (commit) {
commit(1);
} else {
rollback(1);
}
// Add more records to make sure we get to the next file
for (int i = 200; i < 210; i++) {
add(i);
}
int files = calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX, 1, JournalImpl.SIZE_COMMIT_RECORD, 10, JournalImpl.SIZE_ADD_RECORD + recordLength);
for (int i = 0; i < 100 && journal.getDataFilesCount() != files; i++) {
Thread.sleep(10);
}
Assert.assertEquals(files, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(10, journal.getIDMapSize());
List<String> files9 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX, 1, JournalImpl.SIZE_COMMIT_RECORD, 10, JournalImpl.SIZE_ADD_RECORD + recordLength) + 2, files9.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
for (String file : files1) {
Assert.assertTrue(files9.contains(file));
}
checkAndReclaimFiles();
// Most Should now be reclaimed - leaving 10 left in total
Assert.assertEquals(journal.getAlignment() == 1 ? 1 : 2, journal.getDataFilesCount());
Assert.assertEquals(journal.getAlignment() == 1 ? 7 : 6, journal.getFreeFilesCount());
Assert.assertEquals(10, journal.getIDMapSize());
List<String> files10 = fileFactory.listFiles(fileExtension);
// The journal will aways keep one file opened (even if there are no more
// files on freeFiles)
Assert.assertEquals(10, files10.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
}
@Test
public void testReclaimTransactionalSimple() throws Exception {
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()), true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1); // in file 0
deleteTx(1, 1); // in file 1
journal.debugWait();
System.out.println("journal tmp :" + journal.debug());
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files2.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Make sure we move on to the next file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 2); // in file 2
journal.debugWait();
System.out.println("journal tmp2 :" + journal.debug());
List<String> files3 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files3.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
UnitTestLogger.LOGGER.debug("data files count " + journal.getDataFilesCount());
UnitTestLogger.LOGGER.debug("free files count " + journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
commit(1); // in file 3
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(5, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
// Make sure we move on to the next file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 3); // in file 4
List<String> files5 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(6, files5.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(4, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files6 = fileFactory.listFiles(fileExtension);
// Three should get deleted (files 0, 1, 3)
Assert.assertEquals(3, files6.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
// Now restart
journal.checkReclaimStatus();
System.out.println("journal:" + journal.debug());
stopJournal(false);
createJournal();
startJournal();
loadAndCheck();
Assert.assertEquals(3, files6.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
}
@Test
public void testAddDeleteCommitTXIDMap1() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
deleteTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
commit(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
}
@Test
public void testAddCommitTXIDMap1() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
commit(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
}
@Test
public void testAddDeleteCommitTXIDMap2() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
add(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
deleteTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
commit(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
}
@Test
public void testAddDeleteRollbackTXIDMap1() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
deleteTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
rollback(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
}
@Test
public void testAddRollbackTXIDMap1() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
rollback(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
}
@Test
public void testAddDeleteRollbackTXIDMap2() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
add(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
deleteTx(1, 1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
rollback(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
}
@Test
public void testAddDeleteIDMap() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(10, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
add(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
delete(1);
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(8, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
}
@Test
public void testCommitRecordsInFileReclaim() throws Exception {
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()), true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1);
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files2.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Make sure we move on to the next file
commit(1);
List<String> files3 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files3.size());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 2);
// Move on to another file
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files4.size());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
checkAndReclaimFiles();
// Nothing should be reclaimed
List<String> files5 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files5.size());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
}
// file 1: add 1 tx,
// file 2: commit 1, add 2, delete 2
// file 3: add 3
@Test
public void testCommitRecordsInFileNoReclaim() throws Exception {
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) +
512, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1); // in file 0
// Make sure we move on to the next file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 2); // in file 1
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files2.size());
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
commit(1); // in file 1
List<String> files3 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_COMMIT_RECORD + 1) + 2, files3.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_COMMIT_RECORD), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
delete(2); // in file 1
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_COMMIT_RECORD + 1, 1, JournalImpl.SIZE_DELETE_RECORD + 1) + 2, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_COMMIT_RECORD + 1, 1, JournalImpl.SIZE_DELETE_RECORD + 1), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
// Move on to another file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 3); // in file 2
List<String> files5 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files6 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
// Restart
stopJournal();
createJournal();
startJournal();
loadAndCheck();
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
}
@Test
public void testRollbackRecordsInFileNoReclaim() throws Exception {
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) +
512, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1); // in file 0
// Make sure we move on to the next file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 2); // in file 1
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files2.size());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
rollback(1); // in file 1
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_ROLLBACK_RECORD + 1), journal.getDataFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_ROLLBACK_RECORD + 1), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
delete(2); // in file 1
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_ROLLBACK_RECORD + 1, 1, JournalImpl.SIZE_DELETE_RECORD + 1) + 2, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength, 1, JournalImpl.SIZE_ROLLBACK_RECORD + 1, 1, JournalImpl.SIZE_DELETE_RECORD + 1), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Move on to another file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 3); // in file 2
// (current
// file)
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files6 = fileFactory.listFiles(fileExtension);
// files 0 and 1 should be deleted
Assert.assertEquals(journal.getAlignment() == 1 ? 2 : 3, files6.size());
Assert.assertEquals(journal.getAlignment() == 1 ? 0 : 1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
// Restart
stopJournal();
createJournal();
startJournal();
loadAndCheck();
List<String> files7 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(journal.getAlignment() == 1 ? 2 : 3, files7.size());
Assert.assertEquals(journal.getAlignment() == 1 ? 0 : 1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
}
@Test
public void testEmptyPrepare() throws Exception {
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) +
512, true);
createJournal();
startJournal();
load();
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
commit(1);
xid = new SimpleEncoding(10, (byte) 1);
prepare(2, xid);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
rollback(2);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testPrepareNoReclaim() throws Exception {
setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) +
512, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1); // in file 0
// Make sure we move on to the next file
addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD, 2); // in file 1
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files2.size());
Assert.assertEquals(calculateNumberOfFiles(journal, fileSize, journal.getAlignment(), 2, recordLength), journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid); // in file 1
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
Assert.assertEquals(1, journal.getOpenedFilesCount());
delete(2); // in file 1
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Move on to another file
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 3); // in file 2
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files6 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files6.size());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD - 1, 4); // in file 3
List<String> files7 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(5, files7.size());
Assert.assertEquals(3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
commit(1); // in file 4
List<String> files8 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(5, files8.size());
Assert.assertEquals(3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(3, journal.getIDMapSize());
// Restart
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testPrepareReclaim() throws Exception {
setup(2, 100 * 1024, true);
createJournal();
startJournal();
load();
List<String> files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
addTx(1, 1); // in file 0
files1 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(2, files1.size());
Assert.assertEquals(0, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Make sure we move on to the next file
journal.forceMoveNextFile();
journal.debugWait();
addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 2); // in file 1
List<String> files2 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files2.size());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid); // in file 1
List<String> files3 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files3.size());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
delete(2); // in file 1
List<String> files4 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(3, files4.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(1, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(0, journal.getIDMapSize());
// Move on to another file
journal.forceMoveNextFile();
addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD, 3); // in file 2
checkAndReclaimFiles();
List<String> files5 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files5.size());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
Assert.assertEquals(1, journal.getOpenedFilesCount());
checkAndReclaimFiles();
List<String> files6 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files6.size());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getIDMapSize());
Assert.assertEquals(1, journal.getOpenedFilesCount());
journal.forceMoveNextFile();
addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD, 4); // in file 3
List<String> files7 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(5, files7.size());
Assert.assertEquals(3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
commit(1); // in file 3
List<String> files8 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(5, files8.size());
Assert.assertEquals(3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(3, journal.getIDMapSize());
Assert.assertEquals(1, journal.getOpenedFilesCount());
delete(1); // in file 3
List<String> files9 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(5, files9.size());
Assert.assertEquals(3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files10 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(journal.getAlignment() == 1 ? 5 : 5, files10.size());
Assert.assertEquals(journal.getAlignment() == 1 ? 3 : 3, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
journal.forceMoveNextFile();
addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD, 5); // in file 4
List<String> files11 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(6, files11.size());
Assert.assertEquals(4, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(3, journal.getIDMapSize());
checkAndReclaimFiles();
List<String> files12 = fileFactory.listFiles(fileExtension);
// File 0, and File 1 should be deleted
Assert.assertEquals(4, files12.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(3, journal.getIDMapSize());
// Restart
stopJournal();
createJournal();
startJournal();
loadAndCheck();
delete(4);
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(2, journal.getIDMapSize());
addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD, 6);
UnitTestLogger.LOGGER.debug("Debug journal on testPrepareReclaim ->\n" + debugJournal());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(3, journal.getIDMapSize());
checkAndReclaimFiles();
// file 3 should now be deleted
List<String> files15 = fileFactory.listFiles(fileExtension);
Assert.assertEquals(4, files15.size());
Assert.assertEquals(1, journal.getOpenedFilesCount());
Assert.assertEquals(2, journal.getDataFilesCount());
Assert.assertEquals(0, journal.getFreeFilesCount());
Assert.assertEquals(3, journal.getIDMapSize());
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
// Non transactional tests
// =======================
@Test
public void testSimpleAdd() throws Exception {
setup(2, 10 * 1024, true);
createJournal();
startJournal();
load();
sync = true;
add(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAdd() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddNonContiguous() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
stopJournal();
}
@Test
public void testSimpleAddUpdate() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1);
update(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdate() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
update(1, 2, 4, 7, 9, 10);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateAll() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
update(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateNonContiguous() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
add(3, 7, 10, 13, 56, 100, 200, 202, 203);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateAllNonContiguous() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
update(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testSimpleAddUpdateDelete() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1);
update(1);
delete(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testSimpleAddUpdateDeleteTransactional() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1);
commit(1);
updateTx(2, 1);
commit(2);
deleteTx(3, 1);
commit(3);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateDelete() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
update(1, 2, 4, 7, 9, 10);
delete(1, 4, 7, 9, 10);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateDeleteAll() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
update(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
update(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateDeleteNonContiguous() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
add(3, 7, 10, 13, 56, 100, 200, 202, 203);
delete(3, 10, 56, 100, 200, 203);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateDeleteAllNonContiguous() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
update(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
delete(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateDeleteDifferentOrder() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
update(203, 202, 201, 200, 102, 100, 1, 3, 5, 7, 10, 13, 56);
delete(56, 13, 10, 7, 5, 3, 1, 203, 202, 201, 200, 102, 100);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleAddUpdateDeleteDifferentRecordLengths() throws Exception {
setup(10, 20480, true);
createJournal();
startJournal();
load();
for (int i = 0; i < 100; i++) {
byte[] record = generateRecord(RandomUtil.randomInterval(1500, 10000));
journal.appendAddRecord(i, (byte) 0, record, false);
records.add(new RecordInfo(i, (byte) 0, record, false, (short) 0));
}
for (int i = 0; i < 100; i++) {
byte[] record = generateRecord(10 + RandomUtil.randomInterval(1500, 10000));
journal.appendUpdateRecord(i, (byte) 0, record, false);
records.add(new RecordInfo(i, (byte) 0, record, true, (short) 0));
}
for (int i = 0; i < 100; i++) {
journal.appendDeleteRecord(i, false);
removeRecordsForID(i);
}
stopJournal();
createJournal();
startJournal();
loadAndCheck();
stopJournal();
}
@Test
public void testAddUpdateDeleteRestartAndContinue() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
update(1, 2);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
add(4, 5, 6);
update(5);
delete(3);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
add(7, 8);
delete(1, 2);
delete(4, 5, 6);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testSimpleAddTXReload() throws Exception {
setup(2, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testSimpleAddTXXAReload() throws Exception {
setup(2, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1);
EncodingSupport xid = new SimpleEncoding(10, (byte) 'p');
prepare(1, xid);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testAddUpdateDeleteTransactionalRestartAndContinue() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
updateTx(1, 1, 2);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
addTx(2, 4, 5, 6);
update(2, 2);
delete(2, 3);
commit(2);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
addTx(3, 7, 8);
deleteTx(3, 1);
deleteTx(3, 4, 5, 6);
commit(3);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testFillFileExactly() throws Exception {
recordLength = 500;
int numRecords = 2;
// The real appended record size in the journal file = SIZE_BYTE +
// SIZE_LONG + SIZE_INT + recordLength + SIZE_BYTE
int realLength = calculateRecordSize(JournalImpl.SIZE_ADD_RECORD + recordLength, getAlignment());
int fileSize = numRecords * realLength + calculateRecordSize(8, getAlignment()); // 8
// for
// timestamp
setup(10, fileSize, true);
createJournal();
startJournal();
load();
add(1, 2);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
add(3, 4);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
add(4, 5, 6, 7, 8, 9, 10);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
// Transactional tests
// ===================
@Test
public void testSimpleTransaction() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1);
updateTx(1, 1);
deleteTx(1, 1);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionDontDeleteAll() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3);
updateTx(1, 1, 2);
deleteTx(1, 1);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionDeleteAll() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3);
updateTx(1, 1, 2);
deleteTx(1, 1, 2, 3);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionUpdateFromBeforeTx() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
addTx(1, 4, 5, 6);
updateTx(1, 1, 5);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionDeleteFromBeforeTx() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
addTx(1, 4, 5, 6);
deleteTx(1, 1, 2, 3, 4, 5, 6);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionChangesNotVisibleOutsideTXtestTransactionChangesNotVisibleOutsideTX() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
addTx(1, 4, 5, 6);
updateTx(1, 1, 2, 4, 5);
deleteTx(1, 1, 2, 3, 4, 5, 6);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleTransactionsDifferentIDs() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6);
updateTx(1, 1, 3, 5);
deleteTx(1, 1, 2, 3, 4, 5, 6);
commit(1);
addTx(2, 11, 12, 13, 14, 15, 16);
updateTx(2, 11, 13, 15);
deleteTx(2, 11, 12, 13, 14, 15, 16);
commit(2);
addTx(3, 21, 22, 23, 24, 25, 26);
updateTx(3, 21, 23, 25);
deleteTx(3, 21, 22, 23, 24, 25, 26);
commit(3);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleInterleavedTransactionsDifferentIDs() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6);
addTx(3, 21, 22, 23, 24, 25, 26);
updateTx(1, 1, 3, 5);
addTx(2, 11, 12, 13, 14, 15, 16);
deleteTx(1, 1, 2, 3, 4, 5, 6);
updateTx(2, 11, 13, 15);
updateTx(3, 21, 23, 25);
deleteTx(2, 11, 12, 13, 14, 15, 16);
deleteTx(3, 21, 22, 23, 24, 25, 26);
commit(1);
commit(2);
commit(3);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testMultipleInterleavedTransactionsSameIDs() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8);
addTx(1, 9, 10, 11, 12);
addTx(2, 13, 14, 15, 16, 17);
addTx(3, 18, 19, 20, 21, 22);
updateTx(1, 1, 2, 3);
updateTx(2, 4, 5, 6);
commit(2);
updateTx(3, 7, 8);
deleteTx(1, 1, 2);
commit(1);
deleteTx(3, 7, 8);
commit(3);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionMixed() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
addTx(1, 675, 676, 677, 700, 703);
update(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
updateTx(1, 677, 700);
delete(1, 3, 5, 7, 10, 13, 56, 100, 102, 200, 201, 202, 203);
deleteTx(1, 703, 675);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testTransactionAddDeleteDifferentOrder() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);
deleteTx(1, 9, 8, 5, 3, 7, 6, 2, 1, 4);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testAddOutsideTXThenUpdateInsideTX() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
updateTx(1, 1, 2, 3);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testAddOutsideTXThenDeleteInsideTX() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
deleteTx(1, 1, 2, 3);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testRollback() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
deleteTx(1, 1, 2, 3);
rollback(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testRollbackMultiple() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3);
deleteTx(1, 1, 2, 3);
addTx(2, 4, 5, 6);
rollback(1);
rollback(2);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testIsolation1() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3);
deleteTx(1, 1, 2, 3);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testIsolation2() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3);
try {
update(1);
Assert.fail("Should throw exception");
} catch (IllegalStateException e) {
// Ok
}
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testIsolation3() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3);
try {
delete(1);
Assert.fail("Should throw exception");
} catch (IllegalStateException e) {
// Ok
}
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
// XA tests
// ========
@Test
public void testXASimpleNotPrepared() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);
updateTx(1, 1, 2, 3, 4, 7, 8);
deleteTx(1, 1, 2, 3, 4, 5);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXASimplePrepared() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);
updateTx(1, 1, 2, 3, 4, 7, 8);
deleteTx(1, 1, 2, 3, 4, 5);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXASimpleCommit() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);
updateTx(1, 1, 2, 3, 4, 7, 8);
deleteTx(1, 1, 2, 3, 4, 5);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXASimpleRollback() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);
updateTx(1, 1, 2, 3, 4, 7, 8);
deleteTx(1, 1, 2, 3, 4, 5);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
rollback(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXAChangesNotVisibleNotPrepared() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6);
addTx(1, 7, 8, 9, 10);
updateTx(1, 1, 2, 3, 7, 8, 9);
deleteTx(1, 1, 2, 3, 4, 5);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXAChangesNotVisiblePrepared() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6);
addTx(1, 7, 8, 9, 10);
updateTx(1, 1, 2, 3, 7, 8, 9);
deleteTx(1, 1, 2, 3, 4, 5);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXAChangesNotVisibleRollback() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6);
addTx(1, 7, 8, 9, 10);
updateTx(1, 1, 2, 3, 7, 8, 9);
deleteTx(1, 1, 2, 3, 4, 5);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
rollback(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXAChangesisibleCommit() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6);
addTx(1, 7, 8, 9, 10);
updateTx(1, 1, 2, 3, 7, 8, 9);
deleteTx(1, 1, 2, 3, 4, 5);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(1, xid);
commit(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testXAMultiple() throws Exception {
setup(10, 10 * 1024, true);
createJournal();
startJournal();
load();
add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
addTx(1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
addTx(2, 21, 22, 23, 24, 25, 26, 27);
updateTx(1, 1, 3, 6, 11, 14, 17);
addTx(3, 28, 29, 30, 31, 32, 33, 34, 35);
updateTx(3, 7, 8, 9, 10);
deleteTx(2, 4, 5, 6, 23, 25, 27);
EncodingSupport xid = new SimpleEncoding(10, (byte) 0);
prepare(2, xid);
deleteTx(1, 1, 2, 11, 14, 15);
prepare(1, xid);
deleteTx(3, 28, 31, 32, 9);
prepare(3, xid);
commit(1);
rollback(2);
commit(3);
}
@Test
public void testTransactionOnDifferentFiles() throws Exception {
setup(2, 512 + 2 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1, 2, 3, 4, 5, 6);
updateTx(1, 1, 3, 5);
commit(1);
deleteTx(2, 1, 2, 3, 4, 5, 6);
commit(2);
// Just to make sure the commit won't be released. The commit will be on
// the same file as addTx(3);
addTx(3, 11);
addTx(4, 31);
commit(3);
UnitTestLogger.LOGGER.debug("Debug on Journal before stopJournal - \n" + debugJournal());
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testReclaimAfterUpdate() throws Exception {
setup(2, 60 * 1024, true);
createJournal();
startJournal();
load();
int transactionID = 0;
for (int i = 0; i < 100; i++) {
add(i);
if (i % 10 == 0 && i > 0) {
journal.forceMoveNextFile();
}
update(i);
}
for (int i = 100; i < 200; i++) {
addTx(transactionID, i);
if (i % 10 == 0 && i > 0) {
journal.forceMoveNextFile();
}
commit(transactionID++);
update(i);
}
System.out.println("Before stop ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
stopJournal();
createJournal();
startJournal();
loadAndCheck();
System.out.println("After start ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
journal.forceMoveNextFile();
for (int i = 0; i < 100; i++) {
delete(i);
}
System.out.println("After delete ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
for (int i = 100; i < 200; i++) {
updateTx(transactionID, i);
}
System.out.println("After updatetx ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
journal.forceMoveNextFile();
commit(transactionID++);
System.out.println("After commit ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
for (int i = 100; i < 200; i++) {
updateTx(transactionID, i);
deleteTx(transactionID, i);
}
System.out.println("After delete ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
commit(transactionID++);
System.out.println("Before reclaim/after commit ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
stopJournal();
createJournal();
startJournal();
loadAndCheck();
System.out.println("After reclaim ****************************");
System.out.println(journal.debug());
System.out.println("*****************************************");
journal.forceMoveNextFile();
checkAndReclaimFiles();
Assert.assertEquals(0, journal.getDataFilesCount());
stopJournal();
createJournal();
startJournal();
loadAndCheck();
Assert.assertEquals(0, journal.getDataFilesCount());
}
@Test
public void testAddTexThenUpdate() throws Exception {
setup(2, 60 * 1024, true);
createJournal();
startJournal();
load();
addTx(1, 1);
addTx(1, 2);
updateTx(1, 1);
updateTx(1, 3);
commit(1);
update(1);
stopJournal();
createJournal();
startJournal();
loadAndCheck();
}
@Test
public void testLoadTruncatedFile() throws Exception {
setup(2, 2 * 1024, true);
createJournal();
startJournal();
String testDir = getTestDir();
new File(testDir + File.separator + filePrefix + "-1." + fileExtension).createNewFile();
try {
load();
} catch (Exception e) {
Assert.fail("Unexpected exception: " + e.toString());
}
}
protected abstract int getAlignment();
}