Package org.hornetq.tests.unit.core.journal.impl

Source Code of org.hornetq.tests.unit.core.journal.impl.JournalImplTestUnit

/*
* Copyright 2009 Red Hat, Inc.
* Red Hat 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.hornetq.tests.unit.core.journal.impl;

import java.nio.ByteBuffer;
import java.util.List;

import junit.framework.Assert;

import org.hornetq.api.core.HornetQException;
import org.hornetq.core.journal.EncodingSupport;
import org.hornetq.core.journal.RecordInfo;
import org.hornetq.core.journal.SequentialFile;
import org.hornetq.core.journal.impl.JournalImpl;
import org.hornetq.core.logging.Logger;
import org.hornetq.tests.unit.core.journal.impl.fakes.SimpleEncoding;
import org.hornetq.tests.util.RandomUtil;

/**
*
* A JournalImplTestBase
*
* @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
* @author <a href="mailto:clebert.suconic@jboss.com">Clebert Suconic</a>
*
*/
public abstract class JournalImplTestUnit extends JournalImplTestBase
{
   private static final Logger log = Logger.getLogger(JournalImplTestUnit.class);

   protected void tearDown() throws Exception
   {
      List<String> files = fileFactory.listFiles(fileExtension);

      for (String file : files)
      {
         SequentialFile seqFile = fileFactory.createSequentialFile(file, 1);
         assertEquals(fileSize, seqFile.size());
      }

      super.tearDown();
   }

   // General tests
   // =============

   public void testState() throws Exception
   {
      setup(10, 10 * 1024, true);
      createJournal();
      try
      {
         load();
         Assert.fail("Should throw exception");
      }
      catch (IllegalStateException e)
      {
         // OK
      }
      try
      {
         stopJournal();
         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();
   }

   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();
   }

   public void testParams() throws Exception
   {
      try
      {
         new JournalImpl(JournalImpl.MIN_FILE_SIZE - 1, 10, 0, 0, fileFactory, filePrefix, fileExtension, 1);

         Assert.fail("Should throw exception");
      }
      catch (IllegalArgumentException e)
      {
         // Ok
      }

      try
      {
         new JournalImpl(10 * 1024, 1, 0, 0, fileFactory, filePrefix, fileExtension, 1);

         Assert.fail("Should throw exception");
      }
      catch (IllegalArgumentException e)
      {
         // Ok
      }

      try
      {
         new JournalImpl(10 * 1024, 10, 0, 0, null, filePrefix, fileExtension, 1);

         Assert.fail("Should throw exception");
      }
      catch (NullPointerException e)
      {
         // Ok
      }

      try
      {
         new JournalImpl(10 * 1024, 10, 0, 0, fileFactory, null, fileExtension, 1);

         Assert.fail("Should throw exception");
      }
      catch (NullPointerException e)
      {
         // Ok
      }

      try
      {
         new JournalImpl(10 * 1024, 10, 0, 0, fileFactory, filePrefix, null, 1);

         Assert.fail("Should throw exception");
      }
      catch (NullPointerException e)
      {
         // Ok
      }

      try
      {
         new JournalImpl(10 * 1024, 10, 0, 0, fileFactory, filePrefix, null, 0);

         Assert.fail("Should throw exception");
      }
      catch (NullPointerException e)
      {
         // Ok
      }

   }


   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, 1);

         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 (HornetQException e)
      {
         exceptionHappened = true;
         assertEquals(HornetQException.IO_ERROR, e.getCode());
      }

      assertTrue("Exception was expected", exceptionHappened);
      stopJournal();


   }

   // Validates the if the journal will work when the IDs are over MaxInt
   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, 1);

         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();

   }



   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 = "hq";

         fileExtension = "hq";
      }
   }

   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();
   }

   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();
   }

   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(final int fileSize, final int alignment, final int... record) throws Exception
   {
      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;

   }

   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(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(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(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();
   }

   // Validate the methods that are used on assertions
   public void testCalculations() throws Exception
   {

      Assert.assertEquals(0, calculateNumberOfFiles(10 * 1024, 1, 1, 10, 2, 20));
      Assert.assertEquals(0, calculateNumberOfFiles(10 * 1024, 512, 1, 1));
      Assert.assertEquals(0, calculateNumberOfFiles(10 * 1024, 512, 19, 10));
      Assert.assertEquals(1, calculateNumberOfFiles(10 * 1024, 512, 20, 10));
      Assert.assertEquals(0, calculateNumberOfFiles(3000, 500, 2, 1000, 1, 500));
      Assert.assertEquals(1, calculateNumberOfFiles(3000, 500, 2, 1000, 1, 1000));
      Assert.assertEquals(9, calculateNumberOfFiles(10240, 1, 90, 1038, 45, 10));
      Assert.assertEquals(11, calculateNumberOfFiles(10 * 1024, 512, 60, 14 + 1024, 30, 14));
   }

   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();
   }

   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();
   }

   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();
   }

   public void testReclaimTransactionalAddCommit() throws Exception
   {
      testReclaimTransactionalAdd(true);
   }

   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(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(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(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(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(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(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(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(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(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(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(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);
      }

      Assert.assertEquals(calculateNumberOfFiles(fileSize,
                                                 journal.getAlignment(),
                                                 200,
                                                 recordLength,
                                                 200,
                                                 JournalImpl.SIZE_DELETE_RECORD_TX,
                                                 1,
                                                 JournalImpl.SIZE_COMMIT_RECORD,
                                                 10,
                                                 JournalImpl.SIZE_ADD_RECORD + recordLength),
                          journal.getDataFilesCount());
      Assert.assertEquals(0, journal.getFreeFilesCount());
      Assert.assertEquals(10, journal.getIDMapSize());

      List<String> files9 = fileFactory.listFiles(fileExtension);

      Assert.assertEquals(calculateNumberOfFiles(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());
   }

   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());

      JournalImplTestUnit.log.debug("data files count " + journal.getDataFilesCount());
      JournalImplTestUnit.log.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());
   }

   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());
   }

   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());
   }

   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());
   }

   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());
   }

   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());
   }

   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());
   }

   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());

   }

   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

   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(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(fileSize,
                                                 journal.getAlignment(),
                                                 2,
                                                 recordLength,
                                                 1,
                                                 JournalImpl.SIZE_COMMIT_RECORD + 1) + 2, files3.size());
      Assert.assertEquals(1, journal.getOpenedFilesCount());

      Assert.assertEquals(calculateNumberOfFiles(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(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(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());
   }

   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(fileSize,
                                                 journal.getAlignment(),
                                                 2,
                                                 recordLength,
                                                 1,
                                                 JournalImpl.SIZE_ROLLBACK_RECORD + 1), journal.getDataFilesCount());
      Assert.assertEquals(1, journal.getOpenedFilesCount());

      Assert.assertEquals(calculateNumberOfFiles(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(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(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());
   }

   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();

   }

   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(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();

   }

   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);

      JournalImplTestUnit.log.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
   // =======================

   public void testSimpleAdd() throws Exception
   {
      setup(2, 10 * 1024, true);
      createJournal();
      startJournal();
      load();
      sync = true;
      add(1);
      stopJournal();
      createJournal();
      startJournal();
      loadAndCheck();
   }

   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();
   }

   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();
   }

   public void testSimpleAddUpdate() throws Exception
   {
      setup(10, 10 * 1024, true);
      createJournal();
      startJournal();
      load();
      add(1);
      update(1);
      stopJournal();
      createJournal();
      startJournal();
      loadAndCheck();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   public void testSimpleAddUpdateDelete() throws Exception
   {
      setup(10, 10 * 1024, true);
      createJournal();
      startJournal();
      load();
      add(1);
      update(1);
      delete(1);
      stopJournal();
      createJournal();
      startJournal();
      loadAndCheck();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   public void testSimpleAddTXReload() throws Exception
   {
      setup(2, 10 * 1024, true);
      createJournal();
      startJournal();
      load();
      addTx(1, 1);
      commit(1);

      stopJournal();
      createJournal();
      startJournal();
      loadAndCheck();

   }

   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();

   }

   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();
   }

   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
   // ===================

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   public void testTransactionChangesNotVisibleOutsideTX() 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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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
   // ========

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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();
   }

   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);
   }

   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);

      JournalImplTestUnit.log.debug("Debug on Journal before stopJournal - \n" + debugJournal());

      stopJournal();
      createJournal();
      startJournal();
      loadAndCheck();
   }

   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();
      journal.checkReclaimStatus();

      Assert.assertEquals(0, journal.getDataFilesCount());

      stopJournal();
      createJournal();
      startJournal();
      loadAndCheck();

      Assert.assertEquals(0, journal.getDataFilesCount());
   }

   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();

   }

   protected abstract int getAlignment();

}
TOP

Related Classes of org.hornetq.tests.unit.core.journal.impl.JournalImplTestUnit

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.