[jboss-cvs] JBoss Messaging SVN: r4008 - in trunk: src/main/org/jboss/messaging/core/config and 7 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Apr 4 10:25:21 EDT 2008
Author: timfox
Date: 2008-04-04 10:25:20 -0400 (Fri, 04 Apr 2008)
New Revision: 4008
Added:
trunk/src/main/org/jboss/messaging/core/journal/TestableJournal.java
trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java
trunk/src/main/org/jboss/messaging/core/journal/impl/Reclaimer.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/FakeJournalImplTest.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/JournalImplTestUnit.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/RealJournalImplTest.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/FakeJournalImplTest.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestUnit.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/ReclaimerTest.java
Removed:
trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFile.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTest.java
Modified:
trunk/src/etc/server/default/deploy/jbm-configuration.xml
trunk/src/main/org/jboss/messaging/core/config/Configuration.java
trunk/src/main/org/jboss/messaging/core/config/impl/ConfigurationImpl.java
trunk/src/main/org/jboss/messaging/core/config/impl/FileConfiguration.java
trunk/src/main/org/jboss/messaging/core/journal/Journal.java
trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java
trunk/src/main/org/jboss/messaging/core/journal/impl/TransactionHolder.java
trunk/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestBase.java
trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/RealJournalImplTest.java
Log:
More journal work
Modified: trunk/src/etc/server/default/deploy/jbm-configuration.xml
===================================================================
--- trunk/src/etc/server/default/deploy/jbm-configuration.xml 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/etc/server/default/deploy/jbm-configuration.xml 2008-04-04 14:25:20 UTC (rev 4008)
@@ -69,8 +69,6 @@
<journal-min-files>10</journal-min-files>
- <journal-min-available-files>10</journal-min-available-files>
-
<journal-task-period>5000</journal-task-period>
</configuration>
Modified: trunk/src/main/org/jboss/messaging/core/config/Configuration.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/config/Configuration.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/config/Configuration.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -138,10 +138,6 @@
// public void setJournalMinFiles(int journalMinFiles);
- public int getJournalMinAvailableFiles();
-
-// public void setJournalMinAvailableFiles(int journalMinAvailableFiles);
-
public long getJournalTaskPeriod();
// public void setJournalTaskPeriod(long journalTaskPeriod);
Modified: trunk/src/main/org/jboss/messaging/core/config/impl/ConfigurationImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/config/impl/ConfigurationImpl.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/config/impl/ConfigurationImpl.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -89,8 +89,6 @@
protected int journalMinFiles;
- protected int journalMinAvailableFiles;
-
protected long journalTaskPeriod;
// remoting config
@@ -424,17 +422,7 @@
{
this.journalMinFiles = journalMinFiles;
}
-
- public int getJournalMinAvailableFiles()
- {
- return journalMinAvailableFiles;
- }
-
- public void setJournalMinAvailableFiles(int journalMinAvailableFiles)
- {
- this.journalMinAvailableFiles = journalMinAvailableFiles;
- }
-
+
public long getJournalTaskPeriod()
{
return journalTaskPeriod;
Modified: trunk/src/main/org/jboss/messaging/core/config/impl/FileConfiguration.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/config/impl/FileConfiguration.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/config/impl/FileConfiguration.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -127,8 +127,6 @@
this.journalMinFiles = getInteger(e, "journal-min-files", 10);
- this.journalMinAvailableFiles = getInteger(e, "journal-min-available-files", 10);
-
this.journalTaskPeriod = getLong(e, "journal-task-period", 5000L);
Modified: trunk/src/main/org/jboss/messaging/core/journal/Journal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/Journal.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/journal/Journal.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -63,4 +63,10 @@
void load(List<RecordInfo> committedRecords,
List<PreparedTransactionInfo> preparedTransactions) throws Exception;
+ // Start and stop reclaimer
+
+ void startReclaimer();
+
+ void stopReclaimer();
+
}
Added: trunk/src/main/org/jboss/messaging/core/journal/TestableJournal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/TestableJournal.java (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/TestableJournal.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,22 @@
+package org.jboss.messaging.core.journal;
+
+/**
+ *
+ * A TestableJournal
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public interface TestableJournal extends Journal
+{
+ void checkAndReclaimFiles() throws Exception;
+
+ int getDataFilesCount();
+
+ int getFreeFilesCount();
+
+ int getIDMapSize();
+
+ //void dump();
+
+}
Deleted: trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFile.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFile.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFile.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -1,89 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.messaging.core.journal.impl;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.jboss.messaging.core.journal.SequentialFile;
-
-/**
- *
- * A JournalFile
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- *
- */
-public class JournalFile
-{
- private final SequentialFile file;
-
- private final long orderingID;
-
- private int offset;
-
- private final Set<Long> positives = new HashSet<Long>();
-
- private final Set<Long> negatives = new HashSet<Long>();
-
- public JournalFile(final SequentialFile file, final long orderingID)
- {
- this.file = file;
-
- this.orderingID = orderingID;
- }
-
- public void extendOffset(final int delta)
- {
- offset += delta;
- }
-
- public int getOffset()
- {
- return offset;
- }
-
- public long getOrderingID()
- {
- return orderingID;
- }
-
- public void setOffset(final int offset)
- {
- this.offset = offset;
- }
-
- public SequentialFile getFile()
- {
- return file;
- }
-
- public void addPositive(final long id)
- {
- this.positives.add(id);
- }
-
- public void addNegative(final long id)
- {
- this.negatives.add(id);
- }
-}
Copied: trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java (from rev 3897, trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFile.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,134 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.messaging.core.journal.SequentialFile;
+import org.jboss.messaging.core.logging.Logger;
+
+/**
+ *
+ * A JournalFileImpl
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class JournalFileImpl implements JournalFile
+{
+ private static final Logger log = Logger.getLogger(JournalFileImpl.class);
+
+ private final SequentialFile file;
+
+ private final long orderingID;
+
+ private int offset;
+
+ private int posCount;
+
+ private boolean canReclaim;
+
+ private Map<JournalFile, Integer> negCounts = new HashMap<JournalFile, Integer>();
+
+ public JournalFileImpl(final SequentialFile file, final long orderingID)
+ {
+ this.file = file;
+
+ this.orderingID = orderingID;
+ }
+
+ public int getPosCount()
+ {
+ return posCount;
+ }
+
+ public boolean isCanReclaim()
+ {
+ return canReclaim;
+ }
+
+ public void setCanReclaim(final boolean canReclaim)
+ {
+ this.canReclaim = canReclaim;
+ }
+
+ public void incNegCount(final JournalFile file)
+ {
+ Integer count = negCounts.get(file);
+
+ int c = count == null ? 1 : count.intValue() + 1;
+
+ negCounts.put(file, c);
+ }
+
+ public int getNegCount(final JournalFile file)
+ {
+ Integer count = negCounts.get(file);
+
+ if (count == null)
+ {
+ return 0;
+ }
+ else
+ {
+ return count.intValue();
+ }
+ }
+
+ public void incPosCount()
+ {
+ posCount++;
+ }
+
+ public void decPosCount()
+ {
+ posCount--;
+ }
+
+ public void extendOffset(final int delta)
+ {
+ offset += delta;
+ }
+
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ public long getOrderingID()
+ {
+ return orderingID;
+ }
+
+ public void setOffset(final int offset)
+ {
+ this.offset = offset;
+ }
+
+ public SequentialFile getFile()
+ {
+ return file;
+ }
+
+
+}
Modified: trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -26,6 +26,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -33,16 +34,18 @@
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
-import org.jboss.messaging.core.journal.Journal;
import org.jboss.messaging.core.journal.PreparedTransactionInfo;
import org.jboss.messaging.core.journal.RecordInfo;
import org.jboss.messaging.core.journal.SequentialFile;
import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.TestableJournal;
import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.util.Pair;
/**
*
@@ -51,7 +54,7 @@
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
*
*/
-public class JournalImpl implements Journal
+public class JournalImpl implements TestableJournal
{
private static final Logger log = Logger.getLogger(JournalImpl.class);
@@ -71,7 +74,7 @@
public static final int MIN_FILE_SIZE = 1024;
- public static final int MIN_TASK_PERIOD = 5000;
+ public static final int MIN_TASK_PERIOD = 1000;
//Record markers - they must be all unique
@@ -102,8 +105,6 @@
private final int minFiles;
- private final int minAvailableFiles;
-
private final boolean sync;
private final SequentialFileFactory fileFactory;
@@ -115,10 +116,15 @@
public final String fileExtension;
- private final Queue<JournalFile> files = new ConcurrentLinkedQueue<JournalFile>();
+ private final Queue<JournalFile> dataFiles = new ConcurrentLinkedQueue<JournalFile>();
- private final Queue<JournalFile> availableFiles = new ConcurrentLinkedQueue<JournalFile>();
+ private final Queue<JournalFile> freeFiles = new ConcurrentLinkedQueue<JournalFile>();
+ private Map<Long, PosFiles> posFilesMap = new ConcurrentHashMap<Long, PosFiles>();
+
+ private Map<Long, TransactionNegPos> transactionInfos = new ConcurrentHashMap<Long, TransactionNegPos>();
+
+
/*
* We use a semaphore rather than synchronized since it performs better when contended
*/
@@ -136,11 +142,11 @@
private TimerTask reclaimerTask;
- private TimerTask availableFilesTask;
-
private final AtomicLong transactionIDSequence = new AtomicLong(0);
- public JournalImpl(final int fileSize, final int minFiles, final int minAvailableFiles,
+ private Reclaimer reclaimer = new Reclaimer();
+
+ public JournalImpl(final int fileSize, final int minFiles,
final boolean sync, final SequentialFileFactory fileFactory, final long taskPeriod,
final String filePrefix, final String fileExtension)
{
@@ -152,10 +158,6 @@
{
throw new IllegalArgumentException("minFiles cannot be less than 2");
}
- if (minAvailableFiles < 2)
- {
- throw new IllegalArgumentException("minAvailableFiles cannot be less than 2");
- }
if (fileFactory == null)
{
throw new NullPointerException("fileFactory is null");
@@ -177,8 +179,6 @@
this.minFiles = minFiles;
- this.minAvailableFiles = minAvailableFiles;
-
this.sync = sync;
this.fileFactory = fileFactory;
@@ -216,6 +216,8 @@
bb.flip();
appendRecord(bb, true);
+
+ posFilesMap.put(id, new PosFiles(currentFile));
}
public void appendUpdateRecord(final long id, final byte[] record) throws Exception
@@ -224,6 +226,13 @@
{
throw new IllegalStateException("Journal must be loaded first");
}
+
+ PosFiles posFiles = posFilesMap.get(id);
+
+ if (posFiles == null)
+ {
+ throw new IllegalStateException("Cannot find add info " + id);
+ }
int size = SIZE_BYTE + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
@@ -236,9 +245,11 @@
bb.put(DONE);
bb.flip();
- appendRecord(bb, true);
+ appendRecord(bb, true);
+
+ posFiles.addUpdateFile(currentFile);
}
-
+
public void appendDeleteRecord(long id) throws Exception
{
if (state != STATE_LOADED)
@@ -246,6 +257,15 @@
throw new IllegalStateException("Journal must be loaded first");
}
+ PosFiles posFiles = posFilesMap.remove(id);
+
+ if (posFiles == null)
+ {
+ throw new IllegalStateException("Cannot find add info " + id);
+ }
+
+ posFiles.addDelete(currentFile);
+
int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
@@ -255,7 +275,7 @@
bb.put(DONE);
bb.flip();
- appendRecord(bb, true);
+ appendRecord(bb, true);
}
public long getTransactionID()
@@ -270,7 +290,7 @@
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
int size = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
@@ -284,8 +304,12 @@
bb.flip();
appendRecord(bb, false);
+
+ TransactionNegPos tx = getTransactionInfo(txID);
+
+ tx.addPos(currentFile, id);
}
-
+
public void appendUpdateRecordTransactional(final long txID, final long id,
final byte[] record) throws Exception
{
@@ -293,7 +317,7 @@
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
int size = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
@@ -306,7 +330,11 @@
bb.put(DONE);
bb.flip();
- appendRecord(bb, false);
+ appendRecord(bb, false);
+
+ TransactionNegPos tx = getTransactionInfo(txID);
+
+ tx.addPos(currentFile, id);
}
public void appendDeleteRecordTransactional(final long txID, final long id) throws Exception
@@ -326,9 +354,12 @@
bb.put(DONE);
bb.flip();
- appendRecord(bb, false);
+ appendRecord(bb, false);
+
+ TransactionNegPos tx = getTransactionInfo(txID);
+
+ tx.addNeg(currentFile, id);
}
-
public void appendPrepareRecord(final long txID) throws Exception
{
@@ -337,6 +368,13 @@
throw new IllegalStateException("Journal must be loaded first");
}
+ TransactionNegPos tx = transactionInfos.get(txID);
+
+ if (tx == null)
+ {
+ throw new IllegalStateException("Cannot find tx with id " + txID);
+ }
+
int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
@@ -347,6 +385,8 @@
bb.flip();
appendRecord(bb, true);
+
+ tx.prepare(currentFile);
}
public void appendCommitRecord(final long txID) throws Exception
@@ -356,6 +396,13 @@
throw new IllegalStateException("Journal must be loaded first");
}
+ TransactionNegPos tx = transactionInfos.remove(txID);
+
+ if (tx == null)
+ {
+ throw new IllegalStateException("Cannot find tx with id " + txID);
+ }
+
int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
@@ -366,6 +413,8 @@
bb.flip();
appendRecord(bb, true);
+
+ tx.commit(currentFile);
}
public void appendRollbackRecord(final long txID) throws Exception
@@ -375,6 +424,13 @@
throw new IllegalStateException("Journal must be loaded first");
}
+ TransactionNegPos tx = transactionInfos.remove(txID);
+
+ if (tx == null)
+ {
+ throw new IllegalStateException("Cannot find tx with id " + txID);
+ }
+
int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
@@ -385,10 +441,12 @@
bb.flip();
appendRecord(bb, true);
+
+ tx.rollback(currentFile);
}
- public void load(final List<RecordInfo> committedRecords,
- final List<PreparedTransactionInfo> preparedTransactions) throws Exception
+ public synchronized void load(final List<RecordInfo> committedRecords,
+ final List<PreparedTransactionInfo> preparedTransactions) throws Exception
{
if (state != STATE_STARTED)
{
@@ -419,25 +477,13 @@
long orderingID = bb.getLong();
- orderedFiles.add(new JournalFile(file, orderingID));
+ orderedFiles.add(new JournalFileImpl(file, orderingID));
file.close();
}
- int createNum = minFiles - orderedFiles.size();
+ //Now order them by ordering id - we can't use the file name for ordering since we can re-use dataFiles
- //Preallocate some more if necessary
- for (int i = 0; i < createNum; i++)
- {
- JournalFile file = createFile();
-
- orderedFiles.add(file);
-
- file.getFile().close();
- }
-
- //Now order them by ordering id - we can't use the file name for ordering since we can re-use files
-
class JournalFileComparator implements Comparator<JournalFile>
{
public int compare(JournalFile f1, JournalFile f2)
@@ -489,6 +535,7 @@
case ADD_RECORD:
{
long id = bb.getLong();
+
int size = bb.getInt();
byte[] record = new byte[size];
bb.get(record);
@@ -501,7 +548,9 @@
else
{
records.add(new RecordInfo(id, record, false));
- hasData = true;
+ hasData = true;
+
+ posFilesMap.put(id, new PosFiles(file));
}
break;
@@ -509,6 +558,7 @@
case UPDATE_RECORD:
{
long id = bb.getLong();
+
int size = bb.getInt();
byte[] record = new byte[size];
bb.get(record);
@@ -521,7 +571,18 @@
else
{
records.add(new RecordInfo(id, record, true));
- hasData = true;
+ hasData = true;
+ file.incPosCount();
+
+ PosFiles posFiles = posFilesMap.get(id);
+
+ if (posFiles != null)
+ {
+ //It's legal for this to be null. The file(s) with the may have been deleted
+ //just leaving some updates in this file
+
+ posFiles.addUpdateFile(file);
+ }
}
break;
@@ -538,7 +599,14 @@
else
{
recordsToDelete.add(id);
- hasData = true;
+ hasData = true;
+
+ PosFiles posFiles = posFilesMap.remove(id);
+
+ if (posFiles != null)
+ {
+ posFiles.addDelete(file);
+ }
}
break;
@@ -568,7 +636,19 @@
}
tx.recordInfos.add(new RecordInfo(id, record, false));
- hasData = true;
+
+ TransactionNegPos tnp = transactionInfos.get(txID);
+
+ if (tnp == null)
+ {
+ tnp = new TransactionNegPos();
+
+ transactionInfos.put(txID, tnp);
+ }
+
+ tnp.addPos(file, id);
+
+ hasData = true;
}
break;
@@ -598,6 +678,17 @@
}
tx.recordInfos.add(new RecordInfo(id, record, true));
+
+ TransactionNegPos tnp = transactionInfos.get(txID);
+
+ if (tnp == null)
+ {
+ tnp = new TransactionNegPos();
+
+ transactionInfos.put(txID, tnp);
+ }
+
+ tnp.addPos(file, id);
hasData = true;
}
@@ -626,6 +717,18 @@
}
tx.recordsToDelete.add(id);
+
+ TransactionNegPos tnp = transactionInfos.get(txID);
+
+ if (tnp == null)
+ {
+ tnp = new TransactionNegPos();
+
+ transactionInfos.put(txID, tnp);
+ }
+
+ tnp.addNeg(file, id);
+
hasData = true;
}
@@ -651,6 +754,15 @@
}
tx.prepared = true;
+
+ TransactionNegPos tnp = transactionInfos.get(txID);
+
+ if (tnp == null)
+ {
+ throw new IllegalStateException("Cannot find tx " + txID);
+ }
+
+ tnp.prepare(file);
}
break;
@@ -675,7 +787,16 @@
}
records.addAll(tx.recordInfos);
- recordsToDelete.addAll(tx.recordsToDelete);
+ recordsToDelete.addAll(tx.recordsToDelete);
+
+ TransactionNegPos tnp = transactionInfos.remove(txID);
+
+ if (tnp == null)
+ {
+ throw new IllegalStateException("Cannot find tx " + txID);
+ }
+
+ tnp.commit(file);
}
break;
@@ -697,7 +818,16 @@
if (tx == null)
{
throw new IllegalStateException("Cannot find tx with id " + txID);
- }
+ }
+
+ TransactionNegPos tnp = transactionInfos.remove(txID);
+
+ if (tnp == null)
+ {
+ throw new IllegalStateException("Cannot find tx " + txID);
+ }
+
+ tnp.rollback(file);
}
break;
@@ -733,16 +863,14 @@
if (hasData)
{
- files.add(file);
+ dataFiles.add(file);
- //Files are always maintained closed - there may be a lot of them and we don't want to run out
- //of file handles
file.getFile().close();
}
else
{
- //Empty files with no data
- availableFiles.add(file);
+ //Empty dataFiles with no data
+ freeFiles.add(file);
//Position it ready for writing
file.getFile().position(SIZE_LONG);
@@ -750,20 +878,31 @@
}
transactionIDSequence.set(maxTransactionID + 1);
-
- //Now it's possible that some of the files are no longer needed
- checkFilesForReclamation();
+ //Create any more files we need
- //Check we have enough available files
+ //FIXME - size() involves a scan
+ int filesToCreate = minFiles - (dataFiles.size() + freeFiles.size());
- checkAndCreateAvailableFiles();
-
- for (JournalFile file: files)
+ for (int i = 0; i < filesToCreate; i++)
{
- currentFile = file;
+ freeFiles.add(createFile());
}
+
+ //The current file is the last one
+ Iterator<JournalFile> iter = dataFiles.iterator();
+
+ while (iter.hasNext())
+ {
+ currentFile = iter.next();
+
+ if (!iter.hasNext())
+ {
+ iter.remove();
+ }
+ }
+
if (currentFile != null)
{
currentFile.getFile().open();
@@ -774,13 +913,9 @@
}
else
{
- currentFile = availableFiles.remove();
-
- files.add(currentFile);
+ currentFile = freeFiles.remove();
}
-
- startTasks();
-
+
for (RecordInfo record: records)
{
if (!recordsToDelete.contains(record.id))
@@ -794,6 +929,16 @@
if (!transaction.prepared)
{
log.warn("Uncommitted transaction with id " + transaction.transactionID + " found and discarded");
+
+ TransactionNegPos transactionInfo = this.transactionInfos.get(transaction.transactionID);
+
+ if (transactionInfo == null)
+ {
+ throw new IllegalStateException("Cannot find tx " + transaction.transactionID);
+ }
+
+ //Reverse the refs
+ transactionInfo.forget();
}
else
{
@@ -809,19 +954,79 @@
state = STATE_LOADED;
}
+
+ // TestableJournal implementation --------------------------------------------------------------
- public void checkAndCreateAvailableFiles() throws Exception
+ public synchronized void checkAndReclaimFiles() throws Exception
{
- int filesToCreate = minAvailableFiles - availableFiles.size();
+ JournalFile[] files = new JournalFile[dataFiles.size()];
- for (int i = 0; i < filesToCreate; i++)
- {
- JournalFile file = createFile();
-
- availableFiles.add(file);
+ reclaimer.scan(dataFiles.toArray(files));
+
+ for (JournalFile file: dataFiles)
+ {
+ if (file.isCanReclaim())
+ {
+ //File can be reclaimed or deleted
+
+ dataFiles.remove(file);
+
+ //FIXME - size() involves a scan!!!
+ if (freeFiles.size() + dataFiles.size() + 1 < minFiles)
+ {
+ //Re-initialise it
+
+ long newOrderingID = generateOrderingID();
+
+ ByteBuffer bb = ByteBuffer.wrap(new byte[SIZE_LONG]);
+
+ bb.putLong(newOrderingID);
+
+ SequentialFile sf = file.getFile();
+
+ sf.open();
+
+ //Note we MUST re-fill it - otherwise we won't be able to detect corrupt records
+
+ //TODO - if we can avoid this somehow would be good, since filling the file is a heavyweight
+ //operation and can impact other IO operations on the disk
+ sf.fill(0, fileSize, FILL_CHARACTER);
+
+ sf.write(bb, true);
+
+ JournalFile jf = new JournalFileImpl(sf, newOrderingID);
+
+ sf.position(SIZE_LONG);
+
+ jf.setOffset(SIZE_LONG);
+
+ freeFiles.add(jf);
+ }
+ else
+ {
+ file.getFile().open();
+
+ file.getFile().delete();
+ }
+ }
}
}
+ public int getDataFilesCount()
+ {
+ return dataFiles.size();
+ }
+
+ public int getFreeFilesCount()
+ {
+ return freeFiles.size();
+ }
+
+ public int getIDMapSize()
+ {
+ return posFilesMap.size();
+ }
+
// MessagingComponent implementation ---------------------------------------------------
public synchronized void start()
@@ -841,93 +1046,54 @@
throw new IllegalStateException("Journal is already stopped");
}
- if (reclaimerTask != null)
- {
- reclaimerTask.cancel();
- }
+ stopReclaimer();
- if (availableFilesTask != null)
- {
- availableFilesTask.cancel();
- }
-
if (currentFile != null)
{
currentFile.getFile().close();
}
- for (JournalFile file: availableFiles)
+ for (JournalFile file: freeFiles)
{
file.getFile().close();
}
currentFile = null;
- files.clear();
+ dataFiles.clear();
- availableFiles.clear();
+ freeFiles.clear();
state = STATE_STOPPED;
}
- public void startTasks()
+ public void startReclaimer()
{
-// reclaimerTask = new ReclaimerTask();
-// timer.schedule(reclaimerTask, taskPeriod, taskPeriod);
-//
-// availableFilesTask = new AvailableFilesTask();
-// timer.schedule(availableFilesTask, taskPeriod, taskPeriod);
+ if (state == STATE_STOPPED)
+ {
+ throw new IllegalStateException("Journal is stopped");
+ }
+
+ reclaimerTask = new ReclaimerTask();
+
+ timer.schedule(reclaimerTask, taskPeriod, taskPeriod);
}
- // Public -----------------------------------------------------------------------------
-
- public Queue<JournalFile> getFiles()
+ public void stopReclaimer()
{
- return files;
+ if (state == STATE_STOPPED)
+ {
+ throw new IllegalStateException("Journal is already stopped");
+ }
+
+ if (reclaimerTask != null)
+ {
+ reclaimerTask.cancel();
+ }
}
- public Queue<JournalFile> getAvailableFiles()
- {
- return availableFiles;
- }
-
- public void checkFilesForReclamation() throws Exception
- {
- for (JournalFile file: files)
- {
- //TODO reclamation
- if (false && file != currentFile)
- {
- //File can be reclaimed
-
- files.remove(file);
-
- //Re-initialise it
-
- long newOrderingID = generateOrderingID();
-
- ByteBuffer bb = ByteBuffer.wrap(new byte[SIZE_LONG]);
-
- bb.putLong(newOrderingID);
-
- SequentialFile sf = file.getFile();
-
- //Note we MUST re-fill it - otherwise we won't be able to detect corrupt records
- sf.fill(0, fileSize, FILL_CHARACTER);
-
- sf.write(bb, true);
-
- JournalFile jf = new JournalFile(sf, newOrderingID);
-
- sf.position(SIZE_LONG);
-
- jf.setOffset(SIZE_LONG);
-
- availableFiles.add(jf);
- }
- }
- }
-
+ // Public -----------------------------------------------------------------------------
+
// Private -----------------------------------------------------------------------------
private void appendRecord(ByteBuffer bb, boolean sync) throws Exception
@@ -981,7 +1147,7 @@
sequentialFile.position(SIZE_LONG);
- JournalFile info = new JournalFile(sequentialFile, orderingID);
+ JournalFile info = new JournalFileImpl(sequentialFile, orderingID);
info.extendOffset(SIZE_LONG);
@@ -1018,62 +1184,225 @@
}
if (currentFile == null || fileSize - currentFile.getOffset() < size)
+ {
+ currentFile.getFile().close();
+
+ dataFiles.add(currentFile);
+
+ //FIXME - isEmpty() involves a scan!!
+ if (!freeFiles.isEmpty())
+ {
+ currentFile = freeFiles.remove();
+ }
+ else
+ {
+ currentFile = createFile();
+ }
+ }
+ }
+
+ private TransactionNegPos getTransactionInfo(final long txID)
+ {
+ TransactionNegPos tx = transactionInfos.get(txID);
+
+ if (tx == null)
{
- checkAndCreateAvailableFiles();
+ tx = new TransactionNegPos();
- currentFile.getFile().close();
-
- currentFile = availableFiles.remove();
-
- files.add(currentFile);
+ transactionInfos.put(txID, tx);
}
+
+ return tx;
}
+
+ // Inner classes ---------------------------------------------------------------------------
+
private class ReclaimerTask extends TimerTask
{
- public boolean cancel()
+ public synchronized boolean cancel()
{
timer.cancel();
return super.cancel();
}
- public void run()
+ public synchronized void run()
{
try
{
- //checkFilesForReclamation();
+ checkAndReclaimFiles();
}
catch (Exception e)
{
- log.error("Failure in running reclaimer", e);
+ log.error("Failure in running ReclaimerTask", e);
cancel();
}
}
- }
+ }
- private class AvailableFilesTask extends TimerTask
+ private static class PosFiles
{
- public boolean cancel()
+ private final JournalFile addFile;
+
+ private List<JournalFile> updateFiles;
+
+ PosFiles(final JournalFile addFile)
{
- timer.cancel();
+ this.addFile = addFile;
- return super.cancel();
+ addFile.incPosCount();
}
-
- public void run()
+
+ void addUpdateFile(final JournalFile updateFile)
{
- try
+ if (updateFiles == null)
{
- //checkAndCreateAvailableFiles();
+ updateFiles = new ArrayList<JournalFile>();
}
- catch (Exception e)
+
+ updateFiles.add(updateFile);
+
+ updateFile.incPosCount();
+ }
+
+ void addDelete(final JournalFile file)
+ {
+ file.incNegCount(addFile);
+
+ if (updateFiles != null)
{
- log.error("Failure in running availableFileChecker", e);
+ for (JournalFile jf: updateFiles)
+ {
+ file.incNegCount(jf);
+ }
+ }
+ }
+ }
+
+ private class TransactionNegPos
+ {
+ private List<Pair<JournalFile, Long>> pos;
+
+ private List<Pair<JournalFile, Long>> neg;
+
+ private Set<JournalFile> transactionPos;
+
+ void addTXPosCount(final JournalFile file)
+ {
+ if (transactionPos == null)
+ {
+ transactionPos = new HashSet<JournalFile>();
+ }
+
+ if (!transactionPos.contains(file))
+ {
+ transactionPos.add(file);
- cancel();
+ //We add a pos for the transaction itself in the file - this prevents any transactional operations
+ //being deleted before a commit or rollback is written
+ file.incPosCount();
+ }
+ }
+
+ void addPos(final JournalFile file, final long id)
+ {
+ addTXPosCount(file);
+
+ if (pos == null)
+ {
+ pos = new ArrayList<Pair<JournalFile, Long>>();
}
- }
- }
+
+ pos.add(new Pair<JournalFile, Long>(file, id));
+ }
+
+ void addNeg(final JournalFile file, final long id)
+ {
+ addTXPosCount(file);
+
+ if (neg == null)
+ {
+ neg = new ArrayList<Pair<JournalFile, Long>>();
+ }
+
+ neg.add(new Pair<JournalFile, Long>(file, id));
+ }
+
+ void commit(final JournalFile file)
+ {
+ if (pos != null)
+ {
+ for (Pair<JournalFile, Long> p: pos)
+ {
+ PosFiles posFiles = posFilesMap.get(p.b);
+
+ if (posFiles == null)
+ {
+ posFiles = new PosFiles(p.a);
+
+ posFilesMap.put(p.b, posFiles);
+ }
+ else
+ {
+ posFiles.addUpdateFile(p.a);
+ }
+ }
+ }
+
+ if (neg != null)
+ {
+ for (Pair<JournalFile, Long> n: neg)
+ {
+ PosFiles posFiles = posFilesMap.remove(n.b);
+
+ if (posFiles == null)
+ {
+ throw new IllegalStateException("Cannot find add info " + n.b);
+ }
+
+ posFiles.addDelete(n.a);
+ }
+ }
+
+ //Now add negs for the pos we added in each file in which there were transactional operations
+
+ for (JournalFile jf: transactionPos)
+ {
+ file.incNegCount(jf);
+ }
+ }
+
+ void rollback(JournalFile file)
+ {
+ //Now add negs for the pos we added in each file in which there were transactional operations
+ //Note that we do this on rollback as we do on commit, since we need to ensure the file containing
+ //the rollback record doesn't get deleted before the files with the transactional operations are deleted
+ //Otherwise we may run into problems especially with XA where we are just left with a prepare when the tx
+ //has actually been rolled back
+
+ for (JournalFile jf: transactionPos)
+ {
+ file.incNegCount(jf);
+ }
+ }
+
+ void prepare(JournalFile file)
+ {
+ //We don't want the prepare record getting deleted before time
+
+ addTXPosCount(file);
+ }
+
+ void forget()
+ {
+ //The transaction was not committed or rolled back in the file, so we reverse any pos counts we added
+
+ for (JournalFile jf: transactionPos)
+ {
+ jf.decPosCount();
+ }
+ }
+ }
}
Added: trunk/src/main/org/jboss/messaging/core/journal/impl/Reclaimer.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/Reclaimer.java (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/Reclaimer.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl;
+
+import org.jboss.messaging.core.logging.Logger;
+
+
+/**
+ *
+ * A ReclaimerTest
+ *
+ * The journal consists of an ordered list of journal files Fn where 0 <= n <= N
+ *
+ * A journal file can contain either positives (pos) or negatives (neg)
+ *
+ * (Positives correspond either to adds or updates, and negatives correspond to deletes).
+ *
+ * A file Fn can be deleted if, and only if the following criteria are satisified
+ *
+ * 1) All pos in a file Fn, must have corresponding neg in any file Fm where m >= n.
+ *
+ * 2) All pos that correspond to any neg in file Fn, must all live in any file Fm where 0 <= m <= n
+ * which are also marked for deletion in the same pass of the algorithm.
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class Reclaimer
+{
+ private static final Logger log = Logger.getLogger(Reclaimer.class);
+
+ public void scan(final JournalFile[] files)
+ {
+ for (int i = 0; i < files.length; i++)
+ {
+ //First we evaluate criterion 1)
+
+ JournalFile currentFile = files[i];
+
+ int posCount = currentFile.getPosCount();
+
+ int totNeg = 0;
+
+ for (int j = i; j < files.length; j++)
+ {
+ totNeg += files[j].getNegCount(currentFile);
+ }
+
+ currentFile.setCanReclaim(true);
+
+ if (posCount <= totNeg)
+ {
+ //Now we evaluate criterion 2)
+
+ for (int j = 0; j <= i; j++)
+ {
+ JournalFile file = files[j];
+
+ int negCount = currentFile.getNegCount(file);
+
+ if (negCount != 0)
+ {
+ if (file.isCanReclaim())
+ {
+ //Ok
+ }
+ else
+ {
+ currentFile.setCanReclaim(false);
+
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ currentFile.setCanReclaim(false);
+ }
+ }
+ }
+}
Modified: trunk/src/main/org/jboss/messaging/core/journal/impl/TransactionHolder.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/TransactionHolder.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/TransactionHolder.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -14,6 +14,7 @@
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
*
*/
+
public class TransactionHolder
{
public TransactionHolder(final long id)
Modified: trunk/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -100,7 +100,7 @@
SequentialFileFactory bindingsFF = new NIOSequentialFileFactory(bindingsDir);
- bindingsJournal = new JournalImpl(1024 * 1024, 2, 2, true, bindingsFF, 30000, "jbm-bindings", "bindings");
+ bindingsJournal = new JournalImpl(1024 * 1024, 2, true, bindingsFF, 10000, "jbm-bindings", "bindings");
String journalDir = config.getJournalDirectory();
@@ -113,8 +113,8 @@
SequentialFileFactory journalFF = new NIOSequentialFileFactory(journalDir);
- messageJournal = new JournalImpl(config.getJournalFileSize(), config.getJournalMinFiles(),
- config.getJournalMinAvailableFiles(), config.isJournalSync(), journalFF,
+ messageJournal = new JournalImpl(config.getJournalFileSize(),
+ config.getJournalMinFiles(), config.isJournalSync(), journalFF,
config.getJournalTaskPeriod(), "jbm-data", "jbm");
}
@@ -514,8 +514,12 @@
bindingsJournal.start();
+ bindingsJournal.startReclaimer();
+
messageJournal.start();
+ messageJournal.startReclaimer();
+
started = true;
}
Added: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/FakeJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/FakeJournalImplTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/FakeJournalImplTest.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl.test.timing;
+
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.impl.test.unit.fakes.FakeSequentialFileFactory;
+
+/**
+ *
+ * A FakeJournalImplTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class FakeJournalImplTest extends JournalImplTestUnit
+{
+ protected SequentialFileFactory getFileFactory() throws Exception
+ {
+ return new FakeSequentialFileFactory();
+ }
+}
+
Added: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/JournalImplTestUnit.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/JournalImplTestUnit.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/JournalImplTestUnit.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,176 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl.test.timing;
+
+import java.util.ArrayList;
+
+import org.jboss.messaging.core.journal.Journal;
+import org.jboss.messaging.core.journal.RecordInfo;
+import org.jboss.messaging.core.journal.impl.JournalImpl;
+import org.jboss.messaging.core.journal.impl.NIOSequentialFileFactory;
+import org.jboss.messaging.core.journal.impl.test.unit.JournalImplTestBase;
+import org.jboss.messaging.core.logging.Logger;
+
+/**
+ *
+ * A RealJournalImplTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public abstract class JournalImplTestUnit extends JournalImplTestBase
+{
+ private static final Logger log = Logger.getLogger(JournalImplTestUnit.class);
+
+
+
+ public void testAddUpdateDeleteManyLargeFileSize() throws Exception
+ {
+ final int numberAdds = 10000;
+
+ final int numberUpdates = 5000;
+
+ final int numberDeletes = 3000;
+
+ long[] adds = new long[numberAdds];
+
+ for (int i = 0; i < numberAdds; i++)
+ {
+ adds[i] = i;
+ }
+
+ long[] updates = new long[numberUpdates];
+
+ for (int i = 0; i < numberUpdates; i++)
+ {
+ updates[i] = i;
+ }
+
+ long[] deletes = new long[numberDeletes];
+
+ for (int i = 0; i < numberDeletes; i++)
+ {
+ deletes[i] = i;
+ }
+
+ setup(10, 10 * 1024 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+ add(adds);
+ update(updates);
+ delete(deletes);
+ stopJournal();
+ createJournal();
+ startJournal();
+ loadAndCheck();
+
+ }
+
+ public void testAddUpdateDeleteManySmallFileSize() throws Exception
+ {
+ final int numberAdds = 10000;
+
+ final int numberUpdates = 5000;
+
+ final int numberDeletes = 3000;
+
+ long[] adds = new long[numberAdds];
+
+ for (int i = 0; i < numberAdds; i++)
+ {
+ adds[i] = i;
+ }
+
+ long[] updates = new long[numberUpdates];
+
+ for (int i = 0; i < numberUpdates; i++)
+ {
+ updates[i] = i;
+ }
+
+ long[] deletes = new long[numberDeletes];
+
+ for (int i = 0; i < numberDeletes; i++)
+ {
+ deletes[i] = i;
+ }
+
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+ add(adds);
+ update(updates);
+ delete(deletes);
+ stopJournal();
+ createJournal();
+ startJournal();
+ loadAndCheck();
+
+ }
+
+ public void testReclaimAndReload() throws Exception
+ {
+ setup(5, 10 * 1024 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ journal.startReclaimer();
+
+ long start = System.currentTimeMillis();
+
+ for (int count = 0; count < 100000; count++)
+ {
+ add(count);
+
+ if (count >= 5000)
+ {
+ delete(count - 5000);
+ }
+
+ if (count % 10000 == 0)
+ {
+ log.info("Done: " + count);
+ }
+ }
+
+ long end = System.currentTimeMillis();
+
+ double rate = 1000 * ((double)100000) / (end - start);
+
+ log.info("Rate of " + rate + " adds/removes per sec");
+
+ stopJournal();
+ createJournal();
+ startJournal();
+ loadAndCheck();
+
+ assertEquals(5000, journal.getIDMapSize());
+
+ stopJournal();
+ }
+
+}
+
+
Added: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/RealJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/RealJournalImplTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/timing/RealJournalImplTest.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl.test.timing;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import org.jboss.messaging.core.journal.Journal;
+import org.jboss.messaging.core.journal.RecordInfo;
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.impl.JournalImpl;
+import org.jboss.messaging.core.journal.impl.NIOSequentialFileFactory;
+import org.jboss.messaging.core.logging.Logger;
+
+/**
+ *
+ * A RealJournalImplTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class RealJournalImplTest extends JournalImplTestUnit
+{
+ private static final Logger log = Logger.getLogger(RealJournalImplTest.class);
+
+ protected String journalDir = System.getProperty("user.home") + "/journal-test";
+
+ protected SequentialFileFactory getFileFactory() throws Exception
+ {
+ File file = new File(journalDir);
+
+ log.info("deleting directory " + journalDir);
+
+ deleteDirectory(file);
+
+ file.mkdir();
+
+ return new NIOSequentialFileFactory(journalDir);
+ }
+
+ public void testSpeedNonTransactional() throws Exception
+ {
+ Journal journal =
+ new JournalImpl(10 * 1024 * 1024, 10, true, new NIOSequentialFileFactory(journalDir),
+ 5000, "jbm-data", "jbm");
+
+ journal.start();
+
+ journal.load(new ArrayList<RecordInfo>(), null);
+
+ final int numMessages = 10000;
+
+ byte[] data = new byte[1024];
+
+ long start = System.currentTimeMillis();
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ journal.appendAddRecord(i, data);
+ }
+
+ long end = System.currentTimeMillis();
+
+ double rate = 1000 * (double)numMessages / (end - start);
+
+ log.info("Rate " + rate + " records/sec");
+
+ }
+
+ public void testSpeedTransactional() throws Exception
+ {
+ Journal journal =
+ new JournalImpl(10 * 1024 * 1024, 10, true, new NIOSequentialFileFactory(journalDir),
+ 5000, "jbm-data", "jbm");
+
+ journal.start();
+
+ journal.load(new ArrayList<RecordInfo>(), null);
+
+ final int numMessages = 10000;
+
+ byte[] data = new byte[1024];
+
+ long start = System.currentTimeMillis();
+
+ int count = 0;
+ for (int i = 0; i < numMessages; i++)
+ {
+ journal.appendAddRecordTransactional(i, count++, data);
+
+ journal.appendCommitRecord(i);
+ }
+
+ long end = System.currentTimeMillis();
+
+ double rate = 1000 * (double)numMessages / (end - start);
+
+ log.info("Rate " + rate + " records/sec");
+
+ }
+}
+
Copied: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/FakeJournalImplTest.java (from rev 3884, trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTest.java)
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/FakeJournalImplTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/FakeJournalImplTest.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl.test.unit;
+
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.impl.test.unit.fakes.FakeSequentialFileFactory;
+
+/**
+ *
+ * A FakeJournalImplTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class FakeJournalImplTest extends JournalImplTestUnit
+{
+ protected SequentialFileFactory getFileFactory() throws Exception
+ {
+ return new FakeSequentialFileFactory();
+ }
+}
Deleted: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTest.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTest.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -1,45 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.messaging.core.journal.impl.test.unit;
-
-import org.jboss.messaging.core.journal.SequentialFileFactory;
-import org.jboss.messaging.core.journal.impl.test.unit.fakes.FakeSequentialFileFactory;
-
-/**
- *
- * A JournalImplTest
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- *
- */
-public class JournalImplTest extends JournalImplTestBase
-{
- protected void prepareDirectory() throws Exception
- {
- //NOOP
- }
-
- protected SequentialFileFactory getFileFactory() throws Exception
- {
- return new FakeSequentialFileFactory();
- }
-}
Modified: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestBase.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestBase.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -21,7 +21,6 @@
*/
package org.jboss.messaging.core.journal.impl.test.unit;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -30,10 +29,10 @@
import java.util.ListIterator;
import java.util.Map;
-import org.jboss.messaging.core.journal.Journal;
import org.jboss.messaging.core.journal.PreparedTransactionInfo;
import org.jboss.messaging.core.journal.RecordInfo;
import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.TestableJournal;
import org.jboss.messaging.core.journal.impl.JournalImpl;
import org.jboss.messaging.core.logging.Logger;
import org.jboss.messaging.test.unit.RandomUtil;
@@ -50,45 +49,31 @@
{
private static final Logger log = Logger.getLogger(JournalImplTestBase.class);
- private List<RecordInfo> records = new LinkedList<RecordInfo>();
+ protected List<RecordInfo> records = new LinkedList<RecordInfo>();
- private Journal journal;
+ protected TestableJournal journal;
- private int recordLength = 1024;
+ protected int recordLength = 1024;
- private Map<Long, TransactionHolder> transactions = new LinkedHashMap<Long, TransactionHolder>();
+ protected Map<Long, TransactionHolder> transactions = new LinkedHashMap<Long, TransactionHolder>();
- private int minFiles;
+ protected int minFiles;
- private int minAvailableFiles;
+ protected int fileSize;
- private int fileSize;
+ protected boolean sync;
- private boolean sync;
+ protected String filePrefix = "jbm";
- private String filePrefix = "jbm";
+ protected String fileExtension = "jbm";
- private String fileExtension = "jbm";
-
- private SequentialFileFactory fileFactory;
-
- private void logThem()
- {
- log.info("**** loggingg attributes***");
- log.info("recordlength:" + recordLength);
- log.info("minfiles:" + minFiles);
- log.info("minavailableFiles:" + minAvailableFiles);
- log.info("filesize:" + fileSize);
- log.info("sync:" + sync);
- }
-
+ protected SequentialFileFactory fileFactory;
+
protected void setUp() throws Exception
{
super.setUp();
- prepareDirectory();
-
- fileFactory = getFileFactory();
+ resetFileFactory();
transactions.clear();
@@ -115,1021 +100,18 @@
journal = null;;
}
- protected abstract void prepareDirectory() throws Exception;
-
- protected abstract SequentialFileFactory getFileFactory() throws Exception;
-
- // General tests
- // =============
-
- public void testState() throws Exception
+ protected void resetFileFactory() throws Exception
{
- setup(10, 10, 10 * 1024, true);
- createJournal();
- try
- {
- load();
- fail("Should throw exception");
- }
- catch (IllegalStateException e)
- {
- //OK
- }
- try
- {
- stopJournal();
- fail("Should throw exception");
- }
- catch (IllegalStateException e)
- {
- //OK
- }
- startJournal();
- try
- {
- startJournal();
- fail("Should throw exception");
- }
- catch (IllegalStateException e)
- {
- //OK
- }
- stopJournal();
- startJournal();
- load();
- try
- {
- load();
- fail("Should throw exception");
- }
- catch (IllegalStateException e)
- {
- //OK
- }
- try
- {
- startJournal();
- fail("Should throw exception");
- }
- catch (IllegalStateException e)
- {
- //OK
- }
- stopJournal();
+ fileFactory = getFileFactory();
}
- public void testParams() throws Exception
- {
- try
- {
- new JournalImpl(JournalImpl.MIN_FILE_SIZE - 1, 10, 10, true, fileFactory, 5000, filePrefix, fileExtension);
-
- fail("Should throw exception");
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
+ protected abstract SequentialFileFactory getFileFactory() throws Exception;
- try
- {
- new JournalImpl(10 * 1024, 1, 10, true, fileFactory, 5000, filePrefix, fileExtension);
-
- fail("Should throw exception");
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- new JournalImpl(10 * 1024, 10, 1, true, fileFactory, 5000, filePrefix, fileExtension);
-
- fail("Should throw exception");
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- new JournalImpl(10 * 1024, 10, 10, true, null, 5000, filePrefix, fileExtension);
-
- fail("Should throw exception");
- }
- catch (NullPointerException e)
- {
- //Ok
- }
-
- try
- {
- new JournalImpl(10 * 1024, 10, 10, true, fileFactory, JournalImpl.MIN_TASK_PERIOD - 1, filePrefix, fileExtension);
-
- fail("Should throw exception");
- }
- catch (IllegalArgumentException e)
- {
- //Ok
- }
-
- try
- {
- new JournalImpl(10 * 1024, 10, 10, true, fileFactory, 5000, null, fileExtension);
-
- fail("Should throw exception");
- }
- catch (NullPointerException e)
- {
- //Ok
- }
-
- try
- {
- new JournalImpl(10 * 1024, 10, 10, true, fileFactory, 5000, filePrefix, null);
-
- fail("Should throw exception");
- }
- catch (NullPointerException e)
- {
- //Ok
- }
-
- }
-
- // Non transactional tests
- // =======================
-
- public void testSimpleAdd() throws Exception
- {
- setup(10, 10, 10 * 1024, true);
- createJournal();
- startJournal();
- load();
- add(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testMultipleAdd() throws Exception
- {
- setup(10, 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, 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, 10 * 1024, true);
- createJournal();
- startJournal();
- load();
- add(1);
- update(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testMultipleAddUpdate() throws Exception
- {
- setup(10, 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, 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, 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, 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, 10 * 1024, true);
- createJournal();
- startJournal();
- load();
- add(1);
- update(1);
- delete(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testMultipleAddUpdateDelete() throws Exception
- {
- setup(10, 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, 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, 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, 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, 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, 10, 2048, true);
- createJournal();
- startJournal();
- load();
-
- for (int i = 0; i < 1000; i++)
- {
- byte[] record = generateRecord(10 + (int)(1500 * Math.random()));
-
- journal.appendAddRecord(i, record);
-
- records.add(new RecordInfo(i, record, false));
- }
-
- for (int i = 0; i < 1000; i++)
- {
- byte[] record = generateRecord(10 + (int)(1024 * Math.random()));
-
- journal.appendUpdateRecord(i, record);
-
- records.add(new RecordInfo(i, record, true));
- }
-
- for (int i = 0; i < 1000; i++)
- {
- journal.appendDeleteRecord(i);
-
- removeRecordsForID(i);
- }
-
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- stopJournal();
- }
-
- public void testAddUpdateDeleteManySmallFileSize() throws Exception
- {
- final int numberAdds = 10000;
-
- final int numberUpdates = 5000;
-
- final int numberDeletes = 3000;
-
- long[] adds = new long[numberAdds];
-
- for (int i = 0; i < numberAdds; i++)
- {
- adds[i] = i;
- }
-
- long[] updates = new long[numberUpdates];
-
- for (int i = 0; i < numberUpdates; i++)
- {
- updates[i] = i;
- }
-
- long[] deletes = new long[numberDeletes];
-
- for (int i = 0; i < numberDeletes; i++)
- {
- deletes[i] = i;
- }
-
- setup(10, 10, 10 * 1024, true);
- createJournal();
- startJournal();
- load();
- add(adds);
- update(updates);
- delete(deletes);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
-
- }
-
- public void testAddUpdateDeleteManyLargeFileSize() throws Exception
- {
- final int numberAdds = 10000;
-
- final int numberUpdates = 5000;
-
- final int numberDeletes = 3000;
-
- long[] adds = new long[numberAdds];
-
- for (int i = 0; i < numberAdds; i++)
- {
- adds[i] = i;
- }
-
- long[] updates = new long[numberUpdates];
-
- for (int i = 0; i < numberUpdates; i++)
- {
- updates[i] = i;
- }
-
- long[] deletes = new long[numberDeletes];
-
- for (int i = 0; i < numberDeletes; i++)
- {
- deletes[i] = i;
- }
-
- setup(10, 10, 10 * 1024 * 1024, true);
- createJournal();
- startJournal();
- load();
- add(adds);
- update(updates);
- delete(deletes);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
-
- }
-
- public void testAddUpdateDeleteRestartAndContinue() throws Exception
- {
- setup(10, 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 testAddUpdateDeleteTransactionalRestartAndContinue() throws Exception
- {
- setup(10, 10, 10 * 1024, true);
- createJournal();
- startJournal();
- load();
- add(1, 1, 2, 3);
- updateTx(1, 1, 2);
- commit(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- addTx(2, 4, 5, 6);
- update(2, 5);
- delete(2, 3);
- commit(2);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- addTx(3, 7, 8);
- deleteTx(3, 1, 2);
- deleteTx(3, 4, 5, 6);
- commit(3);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testFillFileExactly() throws Exception
- {
- this.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 = 1 + 8 + 4 + this.recordLength + 1;
-
- int fileSize = numRecords * realLength + 8; //8 for timestamp
-
- setup(10, 10, fileSize, true);
-
- logThem();
-
- 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 1,3,5,7,10);
- commit(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testTransactionAddDeleteDifferentOrder() throws Exception
- {
- setup(10, 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, 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, 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, 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, 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();
- }
-
- // XA tests
- // ========
-
- public void testXASimpleNotPrepared() throws Exception
- {
- setup(10, 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, 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);
- prepare(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testXASimpleCommit() throws Exception
- {
- setup(10, 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);
- prepare(1);
- commit(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testXASimpleRollback() throws Exception
- {
- setup(10, 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);
- prepare(1);
- rollback(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testXAChangesNotVisibleNotPrepared() throws Exception
- {
- setup(10, 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, 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);
- prepare(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testXAChangesNotVisibleRollback() throws Exception
- {
- setup(10, 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);
- prepare(1);
- rollback(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testXAChangesisibleCommit() throws Exception
- {
- setup(10, 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);
- prepare(1);
- commit(1);
- stopJournal();
- createJournal();
- startJournal();
- loadAndCheck();
- }
-
- public void testXAMultiple() throws Exception
- {
- setup(10, 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);
- prepare(2);
- deleteTx(1, 1, 2, 11, 14, 15);
- prepare(1);
- deleteTx(3, 28, 31, 32, 9);
- prepare(3);
-
- commit(1);
- rollback(2);
- commit(3);
- }
-
// Private ---------------------------------------------------------------------------------
- void setup(int minFiles, int minAvailableFiles, int fileSize, boolean sync)
+ protected void setup(int minFreeFiles, int fileSize, boolean sync)
{
- this.minFiles = minFiles;
- this.minAvailableFiles = minAvailableFiles;
+ this.minFiles = minFreeFiles;
this.fileSize = fileSize;
this.sync = sync;
}
@@ -1137,20 +119,23 @@
public void createJournal() throws Exception
{
journal =
- new JournalImpl(fileSize, minFiles, minAvailableFiles, sync, fileFactory, 5000, filePrefix, fileExtension);
+ new JournalImpl(fileSize, minFiles, sync, fileFactory, 1000, filePrefix, fileExtension);
}
- private void startJournal() throws Exception
+ protected void startJournal() throws Exception
{
journal.start();
}
- private void stopJournal() throws Exception
+ protected void stopJournal() throws Exception
{
+ //We do a reclaim in here
+ journal.checkAndReclaimFiles();
+
journal.stop();
}
- private void loadAndCheck() throws Exception
+ protected void loadAndCheck() throws Exception
{
List<RecordInfo> committedRecords = new ArrayList<RecordInfo>();
@@ -1181,12 +166,12 @@
checkTransactionsEquivalent(prepared, preparedTransactions);
}
- private void load() throws Exception
+ protected void load() throws Exception
{
journal.load(null, null);
}
- private void add(long... arguments) throws Exception
+ protected void add(long... arguments) throws Exception
{
for (int i = 0; i < arguments.length; i++)
{
@@ -1198,7 +183,7 @@
}
}
- private void update(long... arguments) throws Exception
+ protected void update(long... arguments) throws Exception
{
for (int i = 0; i < arguments.length; i++)
{
@@ -1210,7 +195,7 @@
}
}
- private void delete(long... arguments) throws Exception
+ protected void delete(long... arguments) throws Exception
{
for (int i = 0; i < arguments.length; i++)
{
@@ -1220,7 +205,7 @@
}
}
- private void addTx(long txID, long... arguments) throws Exception
+ protected void addTx(long txID, long... arguments) throws Exception
{
TransactionHolder tx = getTransaction(txID);
@@ -1235,7 +220,7 @@
}
}
- private void updateTx(long txID, long... arguments) throws Exception
+ protected void updateTx(long txID, long... arguments) throws Exception
{
TransactionHolder tx = getTransaction(txID);
@@ -1249,7 +234,7 @@
}
}
- private void deleteTx(long txID, long... arguments) throws Exception
+ protected void deleteTx(long txID, long... arguments) throws Exception
{
TransactionHolder tx = getTransaction(txID);
@@ -1262,7 +247,7 @@
}
- private void prepare(long txID) throws Exception
+ protected void prepare(long txID) throws Exception
{
TransactionHolder tx = transactions.get(txID);
@@ -1281,7 +266,7 @@
tx.prepared = true;
}
- private void commit(long txID) throws Exception
+ protected void commit(long txID) throws Exception
{
TransactionHolder tx = transactions.get(txID);
@@ -1295,7 +280,7 @@
this.commitTx(txID);
}
- private void rollback(long txID) throws Exception
+ protected void rollback(long txID) throws Exception
{
TransactionHolder tx = transactions.remove(txID);
@@ -1324,7 +309,7 @@
}
}
- private void removeRecordsForID(long id)
+ protected void removeRecordsForID(long id)
{
for (ListIterator<RecordInfo> iter = records.listIterator(); iter.hasNext();)
{
@@ -1337,7 +322,7 @@
}
}
- private TransactionHolder getTransaction(long txID)
+ protected TransactionHolder getTransaction(long txID)
{
TransactionHolder tx = transactions.get(txID);
@@ -1351,7 +336,7 @@
return tx;
}
- private void checkTransactionsEquivalent(List<PreparedTransactionInfo> expected, List<PreparedTransactionInfo> actual)
+ protected void checkTransactionsEquivalent(List<PreparedTransactionInfo> expected, List<PreparedTransactionInfo> actual)
{
assertEquals("Lists not same length", expected.size(), actual.size());
@@ -1386,7 +371,7 @@
}
}
- private void checkRecordsEquivalent(List<RecordInfo> expected, List<RecordInfo> actual)
+ protected void checkRecordsEquivalent(List<RecordInfo> expected, List<RecordInfo> actual)
{
assertEquals("Lists not same length", expected.size(), actual.size());
@@ -1408,7 +393,7 @@
}
}
- private byte[] generateRecord(int length)
+ protected byte[] generateRecord(int length)
{
byte[] record = new byte[length];
for (int i = 0; i < length; i++)
Added: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestUnit.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestUnit.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/JournalImplTestUnit.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,2131 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl.test.unit;
+
+import java.util.List;
+
+import org.jboss.messaging.core.journal.RecordInfo;
+import org.jboss.messaging.core.journal.impl.JournalImpl;
+import org.jboss.messaging.core.logging.Logger;
+
+/**
+ *
+ * A JournalImplTestBase
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public abstract class JournalImplTestUnit extends JournalImplTestBase
+{
+ private static final Logger log = Logger.getLogger(JournalImplTestUnit.class);
+
+ // General tests
+ // =============
+
+ public void testState() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ try
+ {
+ load();
+ fail("Should throw exception");
+ }
+ catch (IllegalStateException e)
+ {
+ //OK
+ }
+ try
+ {
+ stopJournal();
+ fail("Should throw exception");
+ }
+ catch (IllegalStateException e)
+ {
+ //OK
+ }
+ startJournal();
+ try
+ {
+ startJournal();
+ fail("Should throw exception");
+ }
+ catch (IllegalStateException e)
+ {
+ //OK
+ }
+ stopJournal();
+ startJournal();
+ load();
+ try
+ {
+ load();
+ fail("Should throw exception");
+ }
+ catch (IllegalStateException e)
+ {
+ //OK
+ }
+ try
+ {
+ startJournal();
+ fail("Should throw exception");
+ }
+ catch (IllegalStateException e)
+ {
+ //OK
+ }
+ stopJournal();
+ }
+
+ public void testParams() throws Exception
+ {
+ try
+ {
+ new JournalImpl(JournalImpl.MIN_FILE_SIZE - 1, 10, true, fileFactory, 5000, filePrefix, fileExtension);
+
+ fail("Should throw exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ new JournalImpl(10 * 1024, 1, true, fileFactory, 5000, filePrefix, fileExtension);
+
+ fail("Should throw exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ new JournalImpl(10 * 1024, 10, true, null, 5000, filePrefix, fileExtension);
+
+ fail("Should throw exception");
+ }
+ catch (NullPointerException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ new JournalImpl(10 * 1024, 10, true, fileFactory, JournalImpl.MIN_TASK_PERIOD - 1, filePrefix, fileExtension);
+
+ fail("Should throw exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ new JournalImpl(10 * 1024, 10, true, fileFactory, 5000, null, fileExtension);
+
+ fail("Should throw exception");
+ }
+ catch (NullPointerException e)
+ {
+ //Ok
+ }
+
+ try
+ {
+ new JournalImpl(10 * 1024, 10, true, fileFactory, 5000, filePrefix, null);
+
+ fail("Should throw exception");
+ }
+ catch (NullPointerException e)
+ {
+ //Ok
+ }
+
+ }
+
+ public void testFilesImmediatelyAfterload() throws Exception
+ {
+ try
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files.size());
+
+ for (String file: files)
+ {
+ assertTrue(file.startsWith(filePrefix));
+ }
+
+ stopJournal();
+
+ resetFileFactory();
+
+ setup(20, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ files = fileFactory.listFiles(fileExtension);
+
+ assertEquals(20, files.size());
+
+ for (String file: files)
+ {
+ assertTrue(file.startsWith(filePrefix));
+ }
+
+ stopJournal();
+
+ fileExtension = "tim";
+
+ resetFileFactory();
+
+ setup(17, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ files = fileFactory.listFiles(fileExtension);
+
+ assertEquals(17, files.size());
+
+ for (String file: files)
+ {
+ assertTrue(file.startsWith(filePrefix));
+ }
+
+ stopJournal();
+
+ filePrefix = "echidna";
+
+ resetFileFactory();
+
+ setup(11, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ files = fileFactory.listFiles(fileExtension);
+
+ assertEquals(11, files.size());
+
+ for (String file: files)
+ {
+ assertTrue(file.startsWith(filePrefix));
+ }
+
+ stopJournal();
+ }
+ finally
+ {
+ filePrefix = "jbm";
+
+ fileExtension = "jbm";
+ }
+ }
+
+ public void testCreateFilesOnLoad() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ 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);
+
+ assertEquals(20, files2.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files2.contains(file));
+ }
+
+ stopJournal();
+ }
+
+ public void testReduceFreeFiles() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ stopJournal();
+
+ setup(5, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files2.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files2.contains(file));
+ }
+
+ stopJournal();
+ }
+
+ public void testCheckCreateMoreFiles() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ //Fill all the files
+
+ for (int i = 0; i < 90; i++)
+ {
+ add(i);
+ }
+
+ assertEquals(9, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(90, journal.getIDMapSize());
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files2.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files2.contains(file));
+ }
+
+ //Now add some more
+
+ for (int i = 90; i < 95; i++)
+ {
+ add(i);
+ }
+
+ assertEquals(10, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(95, journal.getIDMapSize());
+
+ List<String> files3 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(11, files3.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files3.contains(file));
+ }
+
+ //And a load more
+
+ for (int i = 95; i < 200; i++)
+ {
+ add(i);
+ }
+
+ assertEquals(22, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(200, journal.getIDMapSize());
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(23, files4.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files4.contains(file));
+ }
+
+ stopJournal();
+ }
+
+ public void testReclaim() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ for (int i = 0; i < 100; i++)
+ {
+ add(i);
+ }
+
+ assertEquals(11, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(100, journal.getIDMapSize());
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(12, files4.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files4.contains(file));
+ }
+
+ //Now delete half of them
+
+ for (int i = 0; i < 50; i++)
+ {
+ delete(i);
+ }
+
+ assertEquals(11, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(50, journal.getIDMapSize());
+
+ //Make sure the deletes aren't in the current file
+
+ for (int i = 100; i < 110; i++)
+ {
+ add(i);
+ }
+
+ assertEquals(12, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(60, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ //Several of them should be reclaimed - and others deleted - the total number of files should not drop below
+ //10
+
+ assertEquals(7, journal.getDataFilesCount());
+ assertEquals(2, journal.getFreeFilesCount());
+ assertEquals(60, journal.getIDMapSize());
+
+ List<String> files5 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files5.size());
+
+ //Now delete the rest
+
+ for (int i = 50; i < 110; i++)
+ {
+ delete(i);
+ }
+
+ //And fill the current file
+
+ for (int i = 110; i < 120; i++)
+ {
+ add(i);
+ delete(i);
+ }
+
+ journal.checkAndReclaimFiles();
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files6 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files6.size());
+
+ stopJournal();
+ }
+
+ public void testReclaimAddUpdateDeleteDifferentFiles1() throws Exception
+ {
+ setup(2, 1046, true); //Make sure there is one record per file
+ createJournal();
+ startJournal();
+ load();
+
+ add(1);
+ update(1);
+ delete(1);
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files1.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files2.size());
+
+ //1 gets deleted and 1 gets reclaimed
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ stopJournal();
+ }
+
+ public void testReclaimAddUpdateDeleteDifferentFiles2() throws Exception
+ {
+ setup(2, 1046, true); //Make sure there is one record per file
+ createJournal();
+ startJournal();
+ load();
+
+ add(1);
+ update(1);
+ add(2);
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files1.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files2.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ 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(boolean commit) throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ for (int i = 0; i < 100; i++)
+ {
+ addTx(1, i);
+ }
+
+ assertEquals(11, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(12, files2.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files2.contains(file));
+ }
+
+ journal.checkAndReclaimFiles();
+
+ //Make sure nothing reclaimed
+
+ assertEquals(11, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files3 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(12, files3.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files3.contains(file));
+ }
+
+ //Add a load more updates
+
+ for (int i = 100; i < 200; i++)
+ {
+ updateTx(1, i);
+ }
+
+ assertEquals(22, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(23, files4.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files4.contains(file));
+ }
+
+ journal.checkAndReclaimFiles();
+
+ //Make sure nothing reclaimed
+
+ assertEquals(22, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files5 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(23, files5.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files5.contains(file));
+ }
+
+ //Now delete them
+
+ for (int i = 0; i < 200; i++)
+ {
+ deleteTx(1, i);
+ }
+
+ assertEquals(22, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files7 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(23, files7.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files7.contains(file));
+ }
+
+ journal.checkAndReclaimFiles();
+
+ assertEquals(22, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ List<String> files8 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(23, files8.size());
+
+ for (String file: files1)
+ {
+ 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);
+ }
+
+ assertEquals(23, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(10, journal.getIDMapSize());
+
+ List<String> files9 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(24, files9.size());
+
+ for (String file: files1)
+ {
+ assertTrue(files9.contains(file));
+ }
+
+ journal.checkAndReclaimFiles();
+
+ //Most Should now be reclaimed - leaving 10 left in total
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(8, journal.getFreeFilesCount());
+ assertEquals(10, journal.getIDMapSize());
+
+ List<String> files10 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files10.size());
+ }
+
+ public void testReclaimTransactionalSimple() throws Exception
+ {
+ setup(2, 1054, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1); // in file 0
+
+ deleteTx(1, 1); // in file 1
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files2.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ //Make sure we move on to the next file
+
+ add(2); // in file 2
+
+ List<String> files3 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files3.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ commit(1); // in file 3
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(4, files4.size());
+
+ assertEquals(3, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ //Make sure we move on to the next file
+
+ add(3); // in file 4
+
+ List<String> files5 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(5, files5.size());
+
+ assertEquals(4, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ List<String> files6 = fileFactory.listFiles(fileExtension);
+
+ //Three should get deleted (files 0, 1, 3)
+
+ assertEquals(2, files6.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ //Now restart
+
+ stopJournal();
+ createJournal();
+ startJournal();
+ loadAndCheck();
+
+ assertEquals(2, files6.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+ }
+
+ public void testAddDeleteCommitTXIDMap1() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ deleteTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ commit(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+ }
+
+ public void testAddCommitTXIDMap1() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ commit(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+ }
+
+ public void testAddDeleteCommitTXIDMap2() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ add(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ deleteTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ commit(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+ }
+
+
+ public void testAddDeleteRollbackTXIDMap1() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ deleteTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ rollback(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+ }
+
+ public void testAddRollbackTXIDMap1() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ rollback(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+ }
+
+ public void testAddDeleteRollbackTXIDMap2() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ add(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ deleteTx(1, 1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ rollback(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+ }
+
+ public void testAddDeleteIDMap() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(10, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ add(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ delete(1);
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(9, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ }
+
+ public void testCommitRecordsInFileReclaim() throws Exception
+ {
+ setup(2, 1054, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1);
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files2.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ //Make sure we move on to the next file
+
+ commit(1);
+
+ List<String> files3 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files3.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ add(2);
+
+ //Move on to another file
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files4.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ //Nothing should be reclaimed
+
+ List<String> files5 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files5.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ 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, 1300, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1); // in file 0
+
+ //Make sure we move on to the next file
+
+ add(2); // in file 1
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files2.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ commit(1); // in file 1
+
+ List<String> files3 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files3.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ delete(2); // in file 1
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files4.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ //Move on to another file
+
+ add(3); // in file 2
+
+ List<String> files5 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files5.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ List<String> files6 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files6.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+
+ //Restart
+
+ stopJournal();
+ createJournal();
+ startJournal();
+ loadAndCheck();
+
+ List<String> files7 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files7.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(2, journal.getIDMapSize());
+ }
+
+ public void testRollbackRecordsInFileNoReclaim() throws Exception
+ {
+ setup(2, 1300, true);
+ createJournal();
+ startJournal();
+ load();
+
+ List<String> files1 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files1.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ addTx(1, 1); // in file 0
+
+ //Make sure we move on to the next file
+
+ add(2); // in file 1
+
+ List<String> files2 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files2.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ rollback(1); // in file 1
+
+ List<String> files3 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files3.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ delete(2); // in file 1
+
+ List<String> files4 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files4.size());
+
+ assertEquals(1, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(0, journal.getIDMapSize());
+
+ //Move on to another file
+
+ add(3); // in file 2 (current file)
+
+ List<String> files5 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(3, files5.size());
+
+ assertEquals(2, journal.getDataFilesCount());
+ assertEquals(0, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ journal.checkAndReclaimFiles();
+
+ List<String> files6 = fileFactory.listFiles(fileExtension);
+
+ // files 0 and 1 should be deleted
+
+ assertEquals(2, files6.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+
+ //Restart
+
+ stopJournal();
+ createJournal();
+ startJournal();
+ loadAndCheck();
+
+ List<String> files7 = fileFactory.listFiles(fileExtension);
+
+ assertEquals(2, files7.size());
+
+ assertEquals(0, journal.getDataFilesCount());
+ assertEquals(1, journal.getFreeFilesCount());
+ assertEquals(1, journal.getIDMapSize());
+ }
+
+
+
+ // Non transactional tests
+ // =======================
+
+ public void testSimpleAdd() throws Exception
+ {
+ setup(10, 10 * 1024, true);
+ createJournal();
+ startJournal();
+ load();
+ 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 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, 2048, true);
+ createJournal();
+ startJournal();
+ load();
+
+ for (int i = 0; i < 1000; i++)
+ {
+ byte[] record = generateRecord(10 + (int)(1500 * Math.random()));
+
+ journal.appendAddRecord(i, record);
+
+ records.add(new RecordInfo(i, record, false));
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ byte[] record = generateRecord(10 + (int)(1024 * Math.random()));
+
+ journal.appendUpdateRecord(i, record);
+
+ records.add(new RecordInfo(i, record, true));
+ }
+
+ for (int i = 0; i < 1000; i++)
+ {
+ journal.appendDeleteRecord(i);
+
+ 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 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
+ {
+ this.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 = 1 + 8 + 4 + this.recordLength + 1;
+
+ int fileSize = numRecords * realLength + 8; //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);
+ 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);
+ 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);
+ prepare(1);
+ 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);
+ prepare(1);
+ 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);
+ prepare(1);
+ 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);
+ prepare(1);
+ 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);
+ prepare(1);
+ 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);
+ prepare(1);
+ 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);
+ prepare(2);
+ deleteTx(1, 1, 2, 11, 14, 15);
+ prepare(1);
+ deleteTx(3, 28, 31, 32, 9);
+ prepare(3);
+
+ commit(1);
+ rollback(2);
+ commit(3);
+ }
+
+}
Modified: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/RealJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/RealJournalImplTest.java 2008-04-04 11:01:48 UTC (rev 4007)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/RealJournalImplTest.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -38,14 +38,14 @@
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
*
*/
-public class RealJournalImplTest extends JournalImplTestBase
+public class RealJournalImplTest extends JournalImplTestUnit
{
private static final Logger log = Logger.getLogger(RealJournalImplTest.class);
protected String journalDir = System.getProperty("user.home") + "/journal-test";
- protected void prepareDirectory() throws Exception
- {
+ protected SequentialFileFactory getFileFactory() throws Exception
+ {
File file = new File(journalDir);
log.info("deleting directory " + journalDir);
@@ -53,40 +53,8 @@
deleteDirectory(file);
file.mkdir();
- }
-
- protected SequentialFileFactory getFileFactory() throws Exception
- {
+
return new NIOSequentialFileFactory(journalDir);
- }
+ }
- public void testSpeed() throws Exception
- {
- Journal journal =
- new JournalImpl(10 * 1024 * 1024, 10, 10, true, new NIOSequentialFileFactory(journalDir),
- 5000, "jbm-data", "jbm");
-
- journal.start();
-
- journal.load(new ArrayList<RecordInfo>(), null);
-
- final int numMessages = 10000;
-
- byte[] data = new byte[1024];
-
- long start = System.currentTimeMillis();
-
- for (int i = 0; i < numMessages; i++)
- {
- journal.appendAddRecord(i, data);
- }
-
- long end = System.currentTimeMillis();
-
- double rate = 1000 * (double)numMessages / (end - start);
-
- log.info("Rate " + rate + " records/sec");
-
- }
-
}
Added: trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/ReclaimerTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/ReclaimerTest.java (rev 0)
+++ trunk/tests/src/org/jboss/messaging/core/journal/impl/test/unit/ReclaimerTest.java 2008-04-04 14:25:20 UTC (rev 4008)
@@ -0,0 +1,872 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.journal.impl.test.unit;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.messaging.core.journal.SequentialFile;
+import org.jboss.messaging.core.journal.impl.JournalFile;
+import org.jboss.messaging.core.journal.impl.Reclaimer;
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.test.unit.UnitTestCase;
+
+/**
+ *
+ * A ReclaimerTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class ReclaimerTest extends UnitTestCase
+{
+ private static final Logger log = Logger.getLogger(ReclaimerTest.class);
+
+ private JournalFile[] files;
+
+ private Reclaimer reclaimer;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ reclaimer = new Reclaimer();
+ }
+
+ public void testOneFilePosNegAll() throws Exception
+ {
+ setup(1);
+
+ setupPosNeg(0, 10, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ }
+
+ public void testOneFilePosNegNotAll() throws Exception
+ {
+ setup(1);
+
+ setupPosNeg(0, 10, 7);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ }
+
+ public void testOneFilePosOnly() throws Exception
+ {
+ setup(1);
+
+ setupPosNeg(0, 10);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ }
+
+ public void testOneFileNegOnly() throws Exception
+ {
+ setup(1);
+
+ setupPosNeg(0, 0, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ }
+
+
+ public void testTwoFilesPosNegAllDifferentFiles() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10);
+ setupPosNeg(1, 0, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+
+ }
+
+ public void testTwoFilesPosNegAllSameFiles() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10, 10);
+ setupPosNeg(1, 10, 0, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+
+ }
+
+ public void testTwoFilesPosNegMixedFiles() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10, 7);
+ setupPosNeg(1, 10, 3, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ }
+
+ public void testTwoFilesPosNegAllFirstFile() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10, 10);
+ setupPosNeg(1, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCantDelete(1);
+ }
+
+ public void testTwoFilesPosNegAllSecondFile() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10);
+ setupPosNeg(1, 10, 0, 10);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ }
+
+ public void testTwoFilesPosOnly() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10);
+ setupPosNeg(1, 10);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ }
+
+ public void testTwoFilesxyz() throws Exception
+ {
+ setup(2);
+
+ setupPosNeg(0, 10);
+ setupPosNeg(1, 10, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCantDelete(1);
+ }
+
+ //Can-can-can
+
+ public void testThreeFiles1() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 0, 0, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles2() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 7, 0, 0);
+ setupPosNeg(1, 10, 3, 5, 0);
+ setupPosNeg(2, 10, 0, 5, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles3() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 1, 0, 0);
+ setupPosNeg(1, 10, 6, 5, 0);
+ setupPosNeg(2, 10, 3, 5, 10);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles3_1() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 1, 0, 0);
+ setupPosNeg(1, 10, 6, 5, 0);
+ setupPosNeg(2, 0, 3, 5, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles3_2() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 1, 0, 0);
+ setupPosNeg(1, 0, 6, 0, 0);
+ setupPosNeg(2, 0, 3, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+
+
+
+ //Cant-can-can
+
+
+ public void testThreeFiles4() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 5, 0);
+ setupPosNeg(2, 10, 0, 5, 10);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles5() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 5, 0);
+ setupPosNeg(2, 0, 0, 5, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles6() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 0, 0, 0);
+ setupPosNeg(1, 10, 0, 5, 0);
+ setupPosNeg(2, 0, 0, 5, 10);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+ public void testThreeFiles7() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 0, 0, 0);
+ setupPosNeg(1, 10, 0, 5, 0);
+ setupPosNeg(2, 0, 0, 5, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCanDelete(2);
+ }
+
+
+ //Cant can cant
+
+ public void testThreeFiles8() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 0, 0, 2);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles9() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 1, 0, 2);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles10() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 1, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles11() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 0, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 0, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles12() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 0, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 0, 3, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ //Cant-cant-cant
+
+ public void testThreeFiles13() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 2, 3, 0);
+ setupPosNeg(2, 10, 1, 5, 7);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles14() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 0, 2, 0, 0);
+ setupPosNeg(2, 10, 1, 0, 7);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles15() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 2, 3, 0);
+ setupPosNeg(2, 0, 1, 5, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles16() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 0, 2, 0, 0);
+ setupPosNeg(2, 0, 1, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles17() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 3, 0);
+ setupPosNeg(2, 10, 1, 5, 7);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles18() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 3, 0);
+ setupPosNeg(2, 10, 1, 0, 7);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles19() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 3, 0);
+ setupPosNeg(2, 10, 1, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles20() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 3, 0, 0);
+ setupPosNeg(1, 10, 0, 0, 0);
+ setupPosNeg(2, 10, 1, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles21() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 0, 0, 0);
+ setupPosNeg(1, 10, 0, 0, 0);
+ setupPosNeg(2, 10, 0, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCantDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ // Can-can-cant
+
+ public void testThreeFiles22() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 0, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles23() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 10, 0);
+ setupPosNeg(2, 10, 3, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles24() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 7, 0, 0);
+ setupPosNeg(1, 10, 3, 10, 0);
+ setupPosNeg(2, 10, 3, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles25() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 7, 0, 0);
+ setupPosNeg(1, 0, 3, 10, 0);
+ setupPosNeg(2, 10, 3, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles26() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 7, 0, 0);
+ setupPosNeg(1, 0, 3, 10, 0);
+ setupPosNeg(2, 10, 0, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCanDelete(1);
+ assertCantDelete(2);
+ }
+
+
+ //Can-cant-cant
+
+ public void testThreeFiles27() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 0, 0);
+ setupPosNeg(2, 10, 0, 0, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles28() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 3, 0);
+ setupPosNeg(2, 10, 0, 0, 5);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles29() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 3, 0);
+ setupPosNeg(2, 10, 0, 6, 5);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+ public void testThreeFiles30() throws Exception
+ {
+ setup(3);
+
+ setupPosNeg(0, 10, 10, 0, 0);
+ setupPosNeg(1, 10, 0, 3, 0);
+ setupPosNeg(2, 0, 0, 6, 0);
+
+ reclaimer.scan(files);
+
+ assertCanDelete(0);
+ assertCantDelete(1);
+ assertCantDelete(2);
+ }
+
+
+ // Private ------------------------------------------------------------------------
+
+ private void setup(int numFiles)
+ {
+ files = new JournalFile[numFiles];
+
+ for (int i = 0; i < numFiles; i++)
+ {
+ files[i] = new MockJournalFile();
+ }
+ }
+
+ private void setupPosNeg(int fileNumber, int pos, int... neg)
+ {
+ JournalFile file = files[fileNumber];
+
+ for (int i = 0; i < pos; i++)
+ {
+ file.incPosCount();
+ }
+
+ for (int i = 0; i < neg.length; i++)
+ {
+ JournalFile reclaimable2 = files[i];
+
+ for (int j = 0; j < neg[i]; j++)
+ {
+ file.incNegCount(reclaimable2);
+ }
+ }
+ }
+
+ private void assertCanDelete(int... fileNumber)
+ {
+ for (int num: fileNumber)
+ {
+ assertTrue(files[num].isCanReclaim());
+ }
+ }
+
+ private void assertCantDelete(int... fileNumber)
+ {
+ for (int num: fileNumber)
+ {
+ assertFalse(files[num].isCanReclaim());
+ }
+ }
+
+ class MockJournalFile implements JournalFile
+ {
+ private Set<Long> transactionIDs = new HashSet<Long>();
+
+ private Set<Long> transactionTerminationIDs = new HashSet<Long>();
+
+ private Set<Long> transactionPrepareIDs = new HashSet<Long>();
+
+ private Map<JournalFile, Integer> negCounts = new HashMap<JournalFile, Integer>();
+
+ private int posCount;
+
+ private boolean canDelete;
+
+ public void extendOffset(int delta)
+ {
+ }
+
+ public SequentialFile getFile()
+ {
+ return null;
+ }
+
+ public int getOffset()
+ {
+ return 0;
+ }
+
+ public long getOrderingID()
+ {
+ return 0;
+ }
+
+ public void setOffset(int offset)
+ {
+ }
+
+ public int getNegCount(final JournalFile file)
+ {
+ Integer count = negCounts.get(file);
+
+ if (count != null)
+ {
+ return count.intValue();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ public void incNegCount(final JournalFile file)
+ {
+ Integer count = negCounts.get(file);
+
+ int c = count == null ? 1 : count.intValue() + 1;
+
+ negCounts.put(file, c);
+ }
+
+ public int getPosCount()
+ {
+ return posCount;
+ }
+
+ public void incPosCount()
+ {
+ this.posCount++;
+ }
+
+ public void decPosCount()
+ {
+ this.posCount--;
+ }
+
+ public boolean isCanReclaim()
+ {
+ return canDelete;
+ }
+
+ public void setCanReclaim(boolean canDelete)
+ {
+ this.canDelete = canDelete;
+ }
+
+ public void addTransactionID(long id)
+ {
+ transactionIDs.add(id);
+ }
+
+ public void addTransactionPrepareID(long id)
+ {
+ transactionPrepareIDs.add(id);
+ }
+
+ public void addTransactionTerminationID(long id)
+ {
+ transactionTerminationIDs.add(id);
+ }
+
+ public boolean containsTransactionID(long id)
+ {
+ return transactionIDs.contains(id);
+ }
+
+ public boolean containsTransactionPrepareID(long id)
+ {
+ return transactionPrepareIDs.contains(id);
+ }
+
+ public boolean containsTransactionTerminationID(long id)
+ {
+ return transactionTerminationIDs.contains(id);
+ }
+
+ public Set<Long> getTranactionTerminationIDs()
+ {
+ return transactionTerminationIDs;
+ }
+
+ public Set<Long> getTransactionPrepareIDs()
+ {
+ return transactionPrepareIDs;
+ }
+
+ public Set<Long> getTransactionsIDs()
+ {
+ return transactionIDs;
+ }
+ }
+}
More information about the jboss-cvs-commits
mailing list