[jboss-cvs] JBoss Messaging SVN: r4143 - in trunk: native and 13 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon May 5 17:55:56 EDT 2008


Author: clebert.suconic at jboss.com
Date: 2008-05-05 17:55:56 -0400 (Mon, 05 May 2008)
New Revision: 4143

Added:
   trunk/native/.cdtproject
   trunk/native/.project
   trunk/native/.settings/
   trunk/native/.settings/org.eclipse.cdt.core.prefs
   trunk/native/src/org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl.h
   trunk/src/main/org/jboss/messaging/core/asyncio/impl/AsynchronousFileImpl.java
   trunk/src/main/org/jboss/messaging/core/journal/IOCallback.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFile.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFileFactory.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/AbstractSequentialFactory.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/AIOSequentialFileFactoryTest.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FileFactoryTestBase.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealAIOJournalImplTest.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealNIOJournalImplTest.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplAIOTest.java
Removed:
   trunk/native/.settings/org.eclipse.cdt.core.prefs
   trunk/native/src/org_jboss_messaging_core_asyncio_impl_JlibAIO.h
   trunk/src/main/org/jboss/messaging/core/asyncio/impl/JlibAIO.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealJournalImplTest.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFile.java
Modified:
   trunk/.classpath
   trunk/build-messaging.xml
   trunk/native/src/AIOController.cpp
   trunk/native/src/AIOController.h
   trunk/native/src/AsyncFile.cpp
   trunk/native/src/AsyncFile.h
   trunk/native/src/JNICallbackAdapter.cpp
   trunk/native/src/JNICallbackAdapter.h
   trunk/native/src/LibAIOController.cpp
   trunk/native/src/Makefile.am
   trunk/src/etc/jbm-configuration.xml
   trunk/src/main/org/jboss/messaging/core/asyncio/AsynchronousFile.java
   trunk/src/main/org/jboss/messaging/core/journal/Journal.java
   trunk/src/main/org/jboss/messaging/core/journal/SequentialFile.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFile.java
   trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFileFactory.java
   trunk/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java
   trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/MultiThreadWriteNativeTest.java
   trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/SingleThreadWriteNativeTest.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FakeJournalImplTest.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestBase.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestUnit.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/SequentialFileFactoryTestBase.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFileFactory.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/JournalImplTestUnit.java
   trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplTest.java
   trunk/tests/src/org/jboss/messaging/tests/util/UnitTestCase.java
Log:
JBMESSAGING-1283 - Initial commit of AIO into trunk

Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/.classpath	2008-05-05 21:55:56 UTC (rev 4143)
@@ -52,7 +52,6 @@
 	<classpathentry kind="lib" path="thirdparty/jboss/integration/lib/jboss-transaction-spi.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/jboss-jaspi-api/lib/jboss-jaspi-api.jar"/>
 	<classpathentry kind="lib" path="thirdparty/slf4j/api/lib/slf4j-api-1.4.3.jar"/>
-	<classpathentry kind="lib" path="tests/lib/jdbc-drivers/mysql-connector-java-5.1.5-bin.jar"/>
 	<classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/>
 	<classpathentry kind="var" path="ANT_HOME/lib/ant-junit.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/common/lib/jboss-common.jar"/>

Modified: trunk/build-messaging.xml
===================================================================
--- trunk/build-messaging.xml	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/build-messaging.xml	2008-05-05 21:55:56 UTC (rev 4143)
@@ -623,6 +623,7 @@
              timeout="${junit.timeout}">
 
          <jvmarg value="-Xmx1024M"/>
+         <jvmarg value="-Djava.library.path=native/src/.libs"/>
          <!--<jvmarg line="-Xmx512M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/>-->
          <!--<jvmarg value="-ea"/>-->
          <sysproperty key="jbm.remoting.disable.invm" value="${disable.invm}"/>
@@ -726,4 +727,4 @@
       <echo message="${test.execution.classpath.unix}" file="${test.execution.classpath.file}"/>
    </target>
 
-</project>
\ No newline at end of file
+</project>

Copied: trunk/native/.cdtproject (from rev 4128, branches/trunk_tmp_aio/native/.cdtproject)
===================================================================
--- trunk/native/.cdtproject	                        (rev 0)
+++ trunk/native/.cdtproject	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<?eclipse-cdt version="2.0"?>
+<cdtproject id="org.eclipse.cdt.make.core.make">
+  <extension point="org.eclipse.cdt.core.BinaryParser" id="org.eclipse.cdt.core.ELF"/>
+  <data>
+    <item id="scannerConfiguration">
+      <autodiscovery enabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile" problemReportingEnabled="true"/>
+      <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
+        <buildOutputProvider>
+          <openAction enabled="true" filePath=""/>
+          <parser enabled="true"/>
+        </buildOutputProvider>
+        <scannerInfoProvider id="specsFile">
+          <runAction useDefault="true" command="gcc" arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}"/>
+          <parser enabled="true"/>
+        </scannerInfoProvider>
+      </profile>
+      <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
+        <buildOutputProvider>
+          <openAction enabled="false" filePath=""/>
+          <parser enabled="true"/>
+        </buildOutputProvider>
+        <scannerInfoProvider id="makefileGenerator">
+          <runAction useDefault="true" command="make" arguments="-f ${project_name}_scd.mk"/>
+          <parser enabled="false"/>
+        </scannerInfoProvider>
+      </profile>
+      <profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
+        <buildOutputProvider>
+          <openAction enabled="false" filePath=""/>
+          <parser enabled="true"/>
+        </buildOutputProvider>
+        <scannerInfoProvider id="specsFile">
+          <runAction useDefault="true" command="gcc" arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}"/>
+          <parser enabled="false"/>
+        </scannerInfoProvider>
+      </profile>
+      <profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
+        <buildOutputProvider>
+          <openAction enabled="false" filePath=""/>
+          <parser enabled="true"/>
+        </buildOutputProvider>
+        <scannerInfoProvider id="specsFile">
+          <runAction useDefault="true" command="gcc" arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}"/>
+          <parser enabled="false"/>
+        </scannerInfoProvider>
+      </profile>
+    </item>
+    <item id="org.eclipse.cdt.core.pathentry">
+      <pathentry kind="src" path=""/>
+      <pathentry kind="out" path=""/>
+      <pathentry kind="con" path="org.eclipse.cdt.make.core.DISCOVERED_SCANNER_INFO"/>
+    </item>
+  </data>
+</cdtproject>
\ No newline at end of file

Copied: trunk/native/.project (from rev 4128, branches/trunk_tmp_aio/native/.project)
===================================================================
--- trunk/native/.project	                        (rev 0)
+++ trunk/native/.project	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>JBM-native</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.make.core.makeBuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.stopOnError</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.target.auto</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.command</key>
+					<value>make</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
+					<value>false</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.append_environment</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.target.clean</key>
+					<value>clean</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.arguments</key>
+					<value></value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.build.target.inc</key>
+					<value>all</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.core.errorOutputParser</key>
+					<value>org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser;</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.enableFullBuild</key>
+					<value>true</value>
+				</dictionary>
+				<dictionary>
+					<key>org.eclipse.cdt.make.core.environment</key>
+					<value></value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.make.core.makeNature</nature>
+		<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+	</natures>
+</projectDescription>

Copied: trunk/native/.settings (from rev 4128, branches/trunk_tmp_aio/native/.settings)

Deleted: trunk/native/.settings/org.eclipse.cdt.core.prefs
===================================================================
--- branches/trunk_tmp_aio/native/.settings/org.eclipse.cdt.core.prefs	2008-04-28 19:03:12 UTC (rev 4128)
+++ trunk/native/.settings/org.eclipse.cdt.core.prefs	2008-05-05 21:55:56 UTC (rev 4143)
@@ -1,3 +0,0 @@
-#Mon Apr 28 10:33:08 GMT-05:00 2008
-eclipse.preferences.version=1
-indexerId=org.eclipse.cdt.core.domsourceindexer

Copied: trunk/native/.settings/org.eclipse.cdt.core.prefs (from rev 4128, branches/trunk_tmp_aio/native/.settings/org.eclipse.cdt.core.prefs)
===================================================================
--- trunk/native/.settings/org.eclipse.cdt.core.prefs	                        (rev 0)
+++ trunk/native/.settings/org.eclipse.cdt.core.prefs	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,3 @@
+#Mon Apr 28 10:33:08 GMT-05:00 2008
+eclipse.preferences.version=1
+indexerId=org.eclipse.cdt.core.domsourceindexer

Modified: trunk/native/src/AIOController.cpp
===================================================================
--- trunk/native/src/AIOController.cpp	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/AIOController.cpp	2008-05-05 21:55:56 UTC (rev 4143)
@@ -27,7 +27,7 @@
 {
 }
 
-void AIOController::log(THREAD_CONTEXT threadContext, short level, char * message)
+void AIOController::log(THREAD_CONTEXT threadContext, short level, const char * message)
 {
 	jmethodID methodID = 0;
 	

Modified: trunk/native/src/AIOController.h
===================================================================
--- trunk/native/src/AIOController.h	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/AIOController.h	2008-05-05 21:55:56 UTC (rev 4143)
@@ -41,7 +41,7 @@
 	/*
 	 * level = 0-error, 1-warn, 2-info, 3-debug
 	 */
-	void log(THREAD_CONTEXT threadContext, short level, char * message);
+	void log(THREAD_CONTEXT threadContext, short level, const char * message);
 	
 	int fileHandle;
 	AsyncFile fileOutput;

Modified: trunk/native/src/AsyncFile.cpp
===================================================================
--- trunk/native/src/AsyncFile.cpp	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/AsyncFile.cpp	2008-05-05 21:55:56 UTC (rev 4143)
@@ -81,14 +81,16 @@
 #endif
 
 	events = (struct io_event *)malloc (maxIO * sizeof (struct io_event));
+	
+	if (events == 0)
+	{
+		throw AIOException (1, "Can't allocate ioEvents");
+	}
 
 }
 
 AsyncFile::~AsyncFile()
 {
-	::pthread_mutex_destroy(&fileMutex);
-	::pthread_mutex_destroy(&pollerMutex);
-	free(events);
 	if (io_queue_release(aioContext))
 	{
 		throw AIOException(2,"Can't release aio");
@@ -97,8 +99,16 @@
 	{
 		throw AIOException(2,"Can't close file");
 	}
+	free(events);
+	::pthread_mutex_destroy(&fileMutex);
+	::pthread_mutex_destroy(&pollerMutex);
 }
 
+int isException (THREAD_CONTEXT threadContext)
+{
+	return JNI_ENV(threadContext)->ExceptionOccurred() != 0;
+}
+
 void AsyncFile::pollEvents(THREAD_CONTEXT threadContext)
 {
 	
@@ -114,8 +124,13 @@
 	
 	while (pollerRunning)
 	{
-		int result = io_getevents(this->aioContext, 1, maxIO, events, &oneSecond);
+		if (isException(threadContext))
+		{
+			return;
+		}
+		int result = io_getevents(this->aioContext, 1, maxIO, events, 0);
 		
+		
 #ifdef DEBUG
 		fprintf (stderr, "poll, pollerRunning=%d\n", pollerRunning); fflush(stderr);
 #endif
@@ -134,39 +149,40 @@
 			
 			struct iocb * iocbp = events[i].obj;
 	
-			CallbackAdapter * adapter = (CallbackAdapter *) iocbp->data;
-			
-			long result = events[i].res;
-			if (result < 0)
+			if (iocbp->data == (void *) -1)
 			{
-				std::string strerror = io_error(result);
-				adapter->onError(threadContext, result, strerror);
+				pollerRunning = 0;
+//				controller->log(threadContext, 2, "Received poller request to stop");
 			}
 			else
 			{
-				adapter->completeBlock(threadContext);
-				adapter->deleteRef(threadContext);
+				CallbackAdapter * adapter = (CallbackAdapter *) iocbp->data;
+				
+				long result = events[i].res;
+				if (result < 0)
+				{
+					std::string strerror = io_error(result);
+					adapter->onError(threadContext, result, strerror);
+				}
+				else
+				{
+					adapter->completeBlock(threadContext);
+					adapter->deleteRef(threadContext);
+				}
 			}
 			
 			delete iocbp;
 		}
 	}
 	
-	controller->log(threadContext, 2, "Poller finished execution");
+//	controller->log(threadContext, 2, "Poller finished execution");
 	
 }
 
 
-void AsyncFile::preAllocate(THREAD_CONTEXT threadContext, int blocks, size_t size)
+void AsyncFile::preAllocate(THREAD_CONTEXT , off_t position, int blocks, size_t size, int fillChar)
 {
-	size_t currentSize = lseek (fileHandle, 0, SEEK_END);
-	
-	if (currentSize >= blocks * size)
-	{
-		controller->log(threadContext,2,"File being reused");
-		return;
-	}
-	
+
 	if (size % ALIGNMENT != 0)
 	{
 		throw AIOException (101, "You can only pre allocate files in multiples of 512");
@@ -178,10 +194,10 @@
 		throw AIOException(10, "Error on posix_memalign");
 	}
 	
-	memset(preAllocBuffer, 0, size);
+	memset(preAllocBuffer, fillChar, size);
 	
 	
-	if (::lseek (fileHandle, 0, SEEK_SET) < 0) throw AIOException (11, "Error positioning the file");
+	if (::lseek (fileHandle, position, SEEK_SET) < 0) throw AIOException (11, "Error positioning the file");
 	
 	for (int i=0; i<blocks; i++)
 	{
@@ -191,7 +207,7 @@
 		}
 	}
 	
-	if (::lseek (fileHandle, 0, SEEK_SET) < 0) throw AIOException (11, "Error positioning the file");
+	if (::lseek (fileHandle, position, SEEK_SET) < 0) throw AIOException (11, "Error positioning the file");
 	
 	free (preAllocBuffer);
 }
@@ -285,7 +301,22 @@
 void AsyncFile::stopPoller(THREAD_CONTEXT threadContext)
 {
 	pollerRunning = 0;
-	controller->log(threadContext, 2,"Setting poller to stop");
+	
+	
+	struct iocb * iocb = new struct iocb();
+	::io_prep_pwrite(iocb, fileHandle, 0, 0, 0);
+	iocb->data = (void *) -1;
+
+	int result = 0;
+	
+	while ((result = ::io_submit(aioContext, 1, &iocb)) == (-EAGAIN))
+	{
+		fprintf(stderr, "Couldn't send request to stop poller, trying again");
+		controller->log(threadContext, 1, "Couldn't send request to stop poller, trying again");
+		::usleep(WAIT_FOR_SPOT);
+	}
+	
+//	controller->log(threadContext, 2,"Sent data to stop");
 	// It will wait the Poller to gives up its lock
 	LockClass lock(&pollerMutex);
 }

Modified: trunk/native/src/AsyncFile.h
===================================================================
--- trunk/native/src/AsyncFile.h	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/AsyncFile.h	2008-05-05 21:55:56 UTC (rev 4143)
@@ -79,9 +79,8 @@
 	
 	// Finishes the polling thread (if any) and return
 	void stopPoller(THREAD_CONTEXT threadContext);
+	void preAllocate(THREAD_CONTEXT threadContext, off_t position, int blocks, size_t size, int fillChar);
 	
-	void preAllocate(THREAD_CONTEXT threadContext, int numberOfBlocks, size_t size);
-	
 	void pollEvents(THREAD_CONTEXT threadContext);
 	
 };

Modified: trunk/native/src/JNICallbackAdapter.cpp
===================================================================
--- trunk/native/src/JNICallbackAdapter.cpp	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/JNICallbackAdapter.cpp	2008-05-05 21:55:56 UTC (rev 4143)
@@ -22,10 +22,11 @@
 #include <iostream>
 #include "JavaUtilities.h"
 
-JNICallbackAdapter::JNICallbackAdapter(AIOController * _controller, jobject _obj) : CallbackAdapter(), refs(1)
+JNICallbackAdapter::JNICallbackAdapter(AIOController * _controller, jobject _callback, jobject _fileController) : CallbackAdapter(), refs(1)
 {
 	controller = _controller;
-	obj = _obj;
+	callback = _callback;
+	fileController = _fileController;
 }
 
 JNICallbackAdapter::~JNICallbackAdapter()
@@ -34,7 +35,7 @@
 
 void JNICallbackAdapter::done(THREAD_CONTEXT threadContext)
 {
-	JNI_ENV(threadContext)->CallVoidMethod(obj,controller->done); 
+	JNI_ENV(threadContext)->CallVoidMethod(fileController, controller->done, callback); 
 	return;
 }
 
@@ -42,10 +43,11 @@
 {
 	controller->log(threadContext, 0, "Libaio event generated errors, callback object was informed about it");
 	jstring strError = JNI_ENV(threadContext)->NewStringUTF(error.data());
-	JNI_ENV(threadContext)->CallVoidMethod(obj, controller->error, (jint)errorCode, strError);
+	JNI_ENV(threadContext)->CallVoidMethod(fileController, controller->error, callback, (jint)errorCode, strError);
 }
 
 void JNICallbackAdapter::destroy(THREAD_CONTEXT threadContext)
 {
-	JNI_ENV(threadContext)->DeleteGlobalRef(obj);
+	JNI_ENV(threadContext)->DeleteGlobalRef(callback);
+	JNI_ENV(threadContext)->DeleteGlobalRef(fileController);
 }

Modified: trunk/native/src/JNICallbackAdapter.h
===================================================================
--- trunk/native/src/JNICallbackAdapter.h	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/JNICallbackAdapter.h	2008-05-05 21:55:56 UTC (rev 4143)
@@ -31,13 +31,14 @@
 {
 private:
 	AIOController * controller;
-	jobject obj;
+	jobject callback;
+	jobject fileController;
 	int refs;
     void destroy(THREAD_CONTEXT threadContext);
 	
 public:
 	// _ob must be a global Reference (use createGloblReferente before calling the constructor)
-	JNICallbackAdapter(AIOController * _controller, jobject _ob);
+	JNICallbackAdapter(AIOController * _controller, jobject _callback, jobject _fileController);
 	virtual ~JNICallbackAdapter();
 	void done(THREAD_CONTEXT threadContext);
 	void onError(THREAD_CONTEXT threadContext, long error, std::string error);

Modified: trunk/native/src/LibAIOController.cpp
===================================================================
--- trunk/native/src/LibAIOController.cpp	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/LibAIOController.cpp	2008-05-05 21:55:56 UTC (rev 4143)
@@ -25,7 +25,7 @@
 #include <string>
 
 
-#include "org_jboss_messaging_core_asyncio_impl_JlibAIO.h"
+#include "org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl.h"
 
 
 #include "JavaUtilities.h"
@@ -41,18 +41,18 @@
  * Method:    init
  * Signature: (Ljava/lang/String;Ljava/lang/Class;)J
  */
-JNIEXPORT jlong JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_init
-  (JNIEnv * env, jclass, jstring jstrFileName, jclass callbackClass, jint maxIO, jobject logger)
+JNIEXPORT jlong JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_init
+  (JNIEnv * env, jclass clazz, jstring jstrFileName, jint maxIO, jobject logger)
 {
 	try
 	{
 		std::string fileName = convertJavaString(env, jstrFileName);
 		
 		AIOController * controller = new AIOController(fileName, (int) maxIO);
-		controller->done = env->GetMethodID(callbackClass,"done","()V");
+		controller->done = env->GetMethodID(clazz,"callbackDone","(Lorg/jboss/messaging/core/asyncio/AIOCallback;)V");
 		if (!controller->done) return 0;
 		
-		controller->error = env->GetMethodID(callbackClass, "onError", "(ILjava/lang/String;)V");
+		controller->error = env->GetMethodID(clazz, "callbackError", "(Lorg/jboss/messaging/core/asyncio/AIOCallback;ILjava/lang/String;)V");
         if (!controller->error) return 0;
         
         jclass loggerClass = env->GetObjectClass(logger);
@@ -64,7 +64,7 @@
         
         controller->logger = env->NewGlobalRef(logger);
         
-        controller->log(env,4, "Controller initialized");
+//        controller->log(env,4, "Controller initialized");
 		
 	    return (jlong)controller;
 	}
@@ -74,15 +74,28 @@
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_read
-  (JNIEnv *env, jclass, jlong controllerAddress, jlong position, jlong size, jobject jbuffer, jobject callback)
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_read
+  (JNIEnv *env, jobject objThis, jlong controllerAddress, jlong position, jlong size, jobject jbuffer, jobject callback)
 {
 	try 
 	{
 		AIOController * controller = (AIOController *) controllerAddress;
 		void * buffer = env->GetDirectBufferAddress(jbuffer);
-		CallbackAdapter * adapter = new JNICallbackAdapter(controller, env->NewGlobalRef(callback));
 		
+		if (buffer == 0)
+		{
+			throwException(env, "java/lang/IllegalStateException", "Invalid Direct Buffer used");
+			return;
+		}
+		
+		if (((long)buffer) % 512)
+		{
+			throwException(env, "java/lang/IllegalStateException", "Buffer not aligned for use with DMA");
+			return;
+		}
+		
+		CallbackAdapter * adapter = new JNICallbackAdapter(controller, env->NewGlobalRef(callback), env->NewGlobalRef(objThis));
+		
 		controller->fileOutput.read(env, position, (size_t)size, buffer, adapter);
 	}
 	catch (AIOException& e)
@@ -91,15 +104,21 @@
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_write
-  (JNIEnv *env, jclass, jlong controllerAddress, jlong position, jlong size, jobject jbuffer, jobject callback)
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_write
+  (JNIEnv *env, jobject objThis, jlong controllerAddress, jlong position, jlong size, jobject jbuffer, jobject callback)
 {
 	try 
 	{
 		AIOController * controller = (AIOController *) controllerAddress;
 		void * buffer = env->GetDirectBufferAddress(jbuffer);
-		CallbackAdapter * adapter = new JNICallbackAdapter(controller, env->NewGlobalRef(callback));
+		if (buffer == 0)
+		{
+			throwException(env, "java/lang/IllegalStateException", "Invalid Direct Buffer used");
+			return;
+		}
 		
+		CallbackAdapter * adapter = new JNICallbackAdapter(controller, env->NewGlobalRef(callback), env->NewGlobalRef(objThis));
+		
 		controller->fileOutput.write(env, position, (size_t)size, buffer, adapter);
 	}
 	catch (AIOException& e)
@@ -110,7 +129,7 @@
 
 
 
-JNIEXPORT void Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_internalPollEvents
+JNIEXPORT void Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_internalPollEvents
   (JNIEnv *env, jclass, jlong controllerAddress)
 {
 	try
@@ -124,7 +143,7 @@
 	}
 }
 
-JNIEXPORT jobject JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_newBuffer
+JNIEXPORT jobject JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_newBuffer
   (JNIEnv * env, jobject, jlong size)
 {
 	try
@@ -150,7 +169,7 @@
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_destroyBuffer
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_destroyBuffer
   (JNIEnv * env, jobject, jobject jbuffer)
 {
 	void *  buffer = env->GetDirectBufferAddress(jbuffer);
@@ -158,14 +177,26 @@
 }
 
 
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_stopPoller
+  (JNIEnv *env, jclass, jlong controllerAddress)
+{
+	try
+	{
+		AIOController * controller = (AIOController *) controllerAddress;
+		controller->fileOutput.stopPoller(env);
+	}
+	catch (AIOException& e)
+	{
+		throwException(env, "java/lang/RuntimeException", e.what());
+	}
+}
 
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_closeInternal
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_closeInternal
   (JNIEnv *env, jclass, jlong controllerAddress)
 {
 	try
 	{
 		AIOController * controller = (AIOController *) controllerAddress;
-		controller->fileOutput.stopPoller(env);
 		controller->destroy(env);
 		delete controller;
 	}
@@ -175,13 +206,17 @@
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_preAllocate
-  (JNIEnv * env, jclass, jlong controllerAddress, jint blocks, jlong size)
+
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_fill
+  (JNIEnv * env, jclass, jlong controllerAddress, jlong position, jint blocks, jlong size, jbyte fillChar)
 {
 	try
 	{
 		AIOController * controller = (AIOController *) controllerAddress;
-		controller->fileOutput.preAllocate(env, blocks, size);
+		
+		controller->fileOutput.preAllocate(env, position, blocks, size, fillChar);
+		
+		//controller->fileOutput.preAllocate(env, blocks, size);
 	}
 	catch (AIOException& e)
 	{

Modified: trunk/native/src/Makefile.am
===================================================================
--- trunk/native/src/Makefile.am	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/Makefile.am	2008-05-05 21:55:56 UTC (rev 4143)
@@ -4,4 +4,4 @@
 libJBMLibAIO_la_SOURCES = AIOController.cpp AIOController.h AIOException.h AsyncFile.cpp \
                      AsyncFile.h CallbackAdapter.h JAIODatatypes.h JavaUtilities.cpp \
                      JavaUtilities.h JNICallbackAdapter.cpp JNICallbackAdapter.h LibAIOController.cpp \
-                     LockClass.h org_jboss_messaging_core_persistence_impl_libaio_jni_impl_JlibAIO
+                     LockClass.h org_jboss_messaging_core_persistence_impl_libaio_jni_impl_AsynchronousFileImpl.h

Copied: trunk/native/src/org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl.h (from rev 4128, branches/trunk_tmp_aio/native/src/org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl.h)
===================================================================
--- trunk/native/src/org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl.h	                        (rev 0)
+++ trunk/native/src/org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl.h	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,87 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl */
+
+#ifndef _Included_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+#define _Included_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Inaccessible static: log */
+/* Inaccessible static: loaded */
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    init
+ * Signature: (Ljava/lang/String;ILorg/jboss/messaging/core/logging/Logger;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_init
+  (JNIEnv *, jclass, jstring, jint, jobject);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    write
+ * Signature: (JJJLjava/nio/ByteBuffer;Lorg/jboss/messaging/core/asyncio/AIOCallback;)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_write
+  (JNIEnv *, jobject, jlong, jlong, jlong, jobject, jobject);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    read
+ * Signature: (JJJLjava/nio/ByteBuffer;Lorg/jboss/messaging/core/asyncio/AIOCallback;)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_read
+  (JNIEnv *, jobject, jlong, jlong, jlong, jobject, jobject);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    fill
+ * Signature: (JJIJB)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_fill
+  (JNIEnv *, jclass, jlong, jlong, jint, jlong, jbyte);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    closeInternal
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_closeInternal
+  (JNIEnv *, jclass, jlong);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    stopPoller
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_stopPoller
+  (JNIEnv *, jclass, jlong);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    internalPollEvents
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_internalPollEvents
+  (JNIEnv *, jclass, jlong);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    destroyBuffer
+ * Signature: (Ljava/nio/ByteBuffer;)V
+ */
+JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_destroyBuffer
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl
+ * Method:    newBuffer
+ * Signature: (J)Ljava/nio/ByteBuffer;
+ */
+JNIEXPORT jobject JNICALL Java_org_jboss_messaging_core_asyncio_impl_AsynchronousFileImpl_newBuffer
+  (JNIEnv *, jobject, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

Deleted: trunk/native/src/org_jboss_messaging_core_asyncio_impl_JlibAIO.h
===================================================================
--- trunk/native/src/org_jboss_messaging_core_asyncio_impl_JlibAIO.h	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/native/src/org_jboss_messaging_core_asyncio_impl_JlibAIO.h	2008-05-05 21:55:56 UTC (rev 4143)
@@ -1,79 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_jboss_messaging_core_asyncio_impl_JlibAIO */
-
-#ifndef _Included_org_jboss_messaging_core_asyncio_impl_JlibAIO
-#define _Included_org_jboss_messaging_core_asyncio_impl_JlibAIO
-#ifdef __cplusplus
-extern "C" {
-#endif
-/* Inaccessible static: log */
-/* Inaccessible static: loaded */
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    init
- * Signature: (Ljava/lang/String;Ljava/lang/Class;ILorg/jboss/messaging/core/logging/Logger;)J
- */
-JNIEXPORT jlong JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_init
-  (JNIEnv *, jclass, jstring, jclass, jint, jobject);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    write
- * Signature: (JJJLjava/nio/ByteBuffer;Lorg/jboss/messaging/core/asyncio/AIOCallback;)V
- */
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_write
-  (JNIEnv *, jclass, jlong, jlong, jlong, jobject, jobject);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    read
- * Signature: (JJJLjava/nio/ByteBuffer;Lorg/jboss/messaging/core/asyncio/AIOCallback;)V
- */
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_read
-  (JNIEnv *, jclass, jlong, jlong, jlong, jobject, jobject);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    preAllocate
- * Signature: (JIJ)V
- */
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_preAllocate
-  (JNIEnv *, jclass, jlong, jint, jlong);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    closeInternal
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_closeInternal
-  (JNIEnv *, jclass, jlong);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    internalPollEvents
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_internalPollEvents
-  (JNIEnv *, jclass, jlong);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    destroyBuffer
- * Signature: (Ljava/nio/ByteBuffer;)V
- */
-JNIEXPORT void JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_destroyBuffer
-  (JNIEnv *, jobject, jobject);
-
-/*
- * Class:     org_jboss_messaging_core_asyncio_impl_JlibAIO
- * Method:    newBuffer
- * Signature: (J)Ljava/nio/ByteBuffer;
- */
-JNIEXPORT jobject JNICALL Java_org_jboss_messaging_core_asyncio_impl_JlibAIO_newBuffer
-  (JNIEnv *, jobject, jlong);
-
-#ifdef __cplusplus
-}
-#endif
-#endif

Modified: trunk/src/etc/jbm-configuration.xml
===================================================================
--- trunk/src/etc/jbm-configuration.xml	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/etc/jbm-configuration.xml	2008-05-05 21:55:56 UTC (rev 4143)
@@ -63,7 +63,7 @@
       
       <create-journal-dir>true</create-journal-dir>
       
-      <journal-type>nio</journal-type>
+      <journal-type>asyncio</journal-type>
       
       <journal-sync>true</journal-sync>
       

Modified: trunk/src/main/org/jboss/messaging/core/asyncio/AsynchronousFile.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/asyncio/AsynchronousFile.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/asyncio/AsynchronousFile.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -17,30 +17,32 @@
  */
 public interface AsynchronousFile
 {
-   
-   void close();
-   
-   /**
-    * 
-    * Note: If you are using a native Linux implementation, maxIO can't be higher than what's defined on /proc/sys/fs/aio-max-nr, or you would get an error 
-    * @param fileName
-    * @param maxIO The number of max concurrent asynchrnous IO operations. It has to be balanced between the size of your writes and the capacity of your disk.
-    */
-   void open(String fileName, int maxIO);
-
-   /** 
-    * Warning: This function will perform a synchronous IO, probably translating to a fstat call
-    * */
-   long size();
-   
-   void write(long position, long size, ByteBuffer directByteBuffer, AIOCallback aioPackage);
-   
-   void read(long position, long size, ByteBuffer directByteBuffer,  AIOCallback aioPackage);
-   
-   void preAllocate(int blocks, long size);
-
-   ByteBuffer newBuffer(long size);
-   
-   void destroyBuffer(ByteBuffer buffer);
-
+	
+	void close() throws Exception;
+	
+	/**
+	 * 
+	 * Note: If you are using a native Linux implementation, maxIO can't be higher than what's defined on /proc/sys/fs/aio-max-nr, or you would get an error 
+	 * @param fileName
+	 * @param maxIO The number of max concurrent asynchrnous IO operations. It has to be balanced between the size of your writes and the capacity of your disk.
+	 */
+	void open(String fileName, int maxIO);
+	
+	/** 
+	 * Warning: This function will perform a synchronous IO, probably translating to a fstat call
+	 * */
+	long size();
+	
+	void write(long position, long size, ByteBuffer directByteBuffer, AIOCallback aioPackage);
+	
+	void read(long position, long size, ByteBuffer directByteBuffer,  AIOCallback aioPackage);
+	
+	void fill(long position, int blocks, long size, byte fillChar);
+	
+	ByteBuffer newBuffer(long size);
+	
+	void destroyBuffer(ByteBuffer buffer);
+	
+	int getBlockSize();
+	
 }

Copied: trunk/src/main/org/jboss/messaging/core/asyncio/impl/AsynchronousFileImpl.java (from rev 4128, branches/trunk_tmp_aio/src/main/org/jboss/messaging/core/asyncio/impl/AsynchronousFileImpl.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/asyncio/impl/AsynchronousFileImpl.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/asyncio/impl/AsynchronousFileImpl.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,288 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.messaging.core.asyncio.impl;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.jboss.messaging.core.asyncio.AIOCallback;
+import org.jboss.messaging.core.asyncio.AsynchronousFile;
+import org.jboss.messaging.core.logging.Logger;
+
+/**
+ * 
+ * @author clebert.suconic at jboss.com
+ * Warning: Case you refactor the name or the package of this class
+ *          You need to make sure you also rename the C++ native calls
+ */
+public class AsynchronousFileImpl implements AsynchronousFile
+{
+	private static Logger log = Logger.getLogger(AsynchronousFileImpl.class);
+	private boolean opened = false;
+	private String fileName;
+	private Thread poller;
+	private static boolean loaded = false;
+	private int maxIO;
+	
+	Semaphore writeSemaphore;
+	
+	ReadWriteLock lock = new ReentrantReadWriteLock();
+	Lock writeLock = lock.writeLock();
+	
+	Semaphore pollerSemaphore = new Semaphore(1);
+	
+	/**
+	 *  Warning: Beware of the C++ pointer! It will bite you! :-)
+	 */ 
+	private long handler;
+	
+	private static boolean loadLibrary(String name) 
+	{
+		try
+		{
+			log.trace(name + " being loaded");
+			System.loadLibrary(name);
+			return true;
+		}
+		catch (Throwable e)
+		{
+			log.trace(name + " -> error loading it", e);
+			return false;
+		}
+		
+	}
+	
+	static
+	{
+		String libraries[] = new String[] {"JBMLibAIO", "JBMLibAIO32", "JBMLibAIO64"};
+		
+		
+		for (String library: libraries)
+		{
+			if (loadLibrary(library))
+			{
+				loaded = true;
+				break;
+			}
+		}
+		
+		if (!loaded)
+		{
+			log.debug("Couldn't locate LibAIO Wrapper");
+		}
+	}
+	
+	public static boolean isLoaded()
+	{
+		return loaded;
+	}
+	
+	
+	
+	
+	public void open(String fileName, int maxIO)
+	{
+		try
+		{
+			writeLock.lock();
+			this.maxIO = maxIO;
+			
+			this.writeSemaphore = new Semaphore(maxIO);
+			
+			if (opened)
+			{
+				throw new IllegalStateException("AsynchronousFile is already opened");
+			}
+			opened = true;
+			this.fileName=fileName;
+			handler = init (fileName, maxIO, log);
+			startPoller();
+		}
+		finally
+		{
+			writeLock.unlock();
+		}
+	}
+	
+	class PollerThread extends Thread
+	{
+		PollerThread ()
+		{
+			super("NativePoller for " + fileName);
+		}
+		public void run()
+		{
+			// informing caller that this thread already has the lock
+			try
+			{
+				pollEvents();
+			}
+			finally
+			{
+				pollerSemaphore.release();
+			}
+		}
+	}
+	
+	public void close() throws Exception
+	{
+		checkOpened();
+		
+		writeLock.lock();
+		writeSemaphore.acquire(maxIO);
+		stopPoller(handler);
+		// We need to make sure we won't call close until Poller is completely done, or we might get beautiful GPFs
+		try
+		{
+			pollerSemaphore.acquire();
+			closeInternal(handler);
+			opened = false;
+			handler = 0;
+		}
+		finally
+		{
+			writeLock.unlock();
+			pollerSemaphore.release();
+		}
+	}
+	
+	
+	public void write(long position, long size, ByteBuffer directByteBuffer, AIOCallback aioPackage)
+	{
+		checkOpened();
+		this.writeSemaphore.acquireUninterruptibly();
+		try
+		{
+			write (handler, position, size, directByteBuffer, aioPackage);
+		}
+		catch (RuntimeException e)
+		{
+			writeSemaphore.release();
+			throw e;
+		}
+		
+	}
+	
+	public void read(long position, long size, ByteBuffer directByteBuffer, AIOCallback aioPackage)
+	{
+		checkOpened();
+		this.writeSemaphore.acquireUninterruptibly();
+		try
+		{
+			read (handler, position, size, directByteBuffer, aioPackage);
+		}
+		catch (RuntimeException e)
+		{
+			writeSemaphore.release();
+			throw e;
+		}
+		
+	}
+	
+	public long size()
+	{
+		checkOpened();
+		// TODO: wire this method to ftell
+		return 0;
+	}
+	
+	public void fill(long position, int blocks, long size, byte fillChar)
+	{
+		checkOpened();
+		fill(handler, position, blocks, size, fillChar);
+	}
+	
+	public int getBlockSize()
+	{
+		return 512;
+	}
+	
+	
+	/** The JNI layer will call this method, so we could use it to unlock readWriteLocks held in the java layer */
+	@SuppressWarnings("unused") // Called by the JNI layer.. just ignore the warning
+	private void callbackDone(AIOCallback callback)
+	{
+		writeSemaphore.release();
+		callback.done();
+	}
+	
+	@SuppressWarnings("unused") // Called by the JNI layer.. just ignore the warning
+	private void callbackError(AIOCallback callback, int errorCode, String errorMessage)
+	{
+		writeSemaphore.release();
+		callback.onError(errorCode, errorMessage);
+	}
+	
+	private void pollEvents()
+	{
+		if (!opened)
+		{
+			return;
+		}
+		internalPollEvents(handler);
+	}
+	
+	private synchronized void  startPoller()
+	{
+		checkOpened();
+		
+		poller = new PollerThread(); 
+		try
+		{
+			this.pollerSemaphore.acquire();
+			poller.start();
+		}
+		catch (Exception ex)
+		{
+			log.error(ex.getMessage(), ex);
+		}
+	}
+	
+	
+	
+	private void checkOpened() 
+	{
+		if (!opened)
+		{
+			throw new RuntimeException("File is not opened");
+		}
+	}
+	
+	/** 
+	 * I'm sending aioPackageClazz here, as you could have multiple classLoaders with the same class, and I don't want the hassle of doing classLoading in the Native layer
+	 */
+	@SuppressWarnings("unchecked")
+	private static native long init(String fileName, int maxIO, Logger logger);
+	
+	private native void write(long handle, long position, long size, ByteBuffer buffer, AIOCallback aioPackage);
+	
+	private native void read(long handle, long position, long size, ByteBuffer buffer, AIOCallback aioPackage);
+	
+	private static native void fill(long handle, long position, int blocks, long size, byte fillChar);
+	
+	private static native void closeInternal(long handler);
+	
+	private static native void stopPoller(long handler);
+	
+	/** Poll asynchrounous events from internal queues */
+	private static native void internalPollEvents(long handler);
+	
+	// Should we make this method static?
+	public native void destroyBuffer(ByteBuffer buffer);
+	
+	// Should we make this method static?
+	public native ByteBuffer newBuffer(long size);
+	
+	
+	
+	
+	
+}

Deleted: trunk/src/main/org/jboss/messaging/core/asyncio/impl/JlibAIO.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/asyncio/impl/JlibAIO.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/asyncio/impl/JlibAIO.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -1,158 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.messaging.core.asyncio.impl;
-
-import java.nio.ByteBuffer;
-
-import org.jboss.messaging.core.asyncio.AIOCallback;
-import org.jboss.messaging.core.asyncio.AsynchronousFile;
-import org.jboss.messaging.core.logging.Logger;
-
-/**
- * 
- * @author clebert.suconic at jboss.com
- * Warning: Case you refactor the name or the package of this class
- *          You need to make sure you also rename the C++ native calls
- */
-public class JlibAIO implements AsynchronousFile
-{
-    private static Logger log = Logger.getLogger(JlibAIO.class);
-    private boolean opened = false;
-    private String fileName;
-    private Thread poller;
-    private static boolean loaded = true;
-    
-    /**
-     *  Warning: Beware of the C++ pointer! It will bite you! :-)
-     */ 
-    private long handler;
-    
-    static
-    {
-        try
-        {
-            log.info("JLibAIO being loaded");
-            System.loadLibrary("JBMLibAIO");
-        }
-        catch (Throwable e)
-        {
-            log.error(e.getLocalizedMessage(), e);
-            loaded = false;
-        }
-    }
-    
-    public static boolean isLoaded()
-    {
-       return loaded;
-    }
-    
-    
-
-    
-    public void open(String fileName, int maxIO)
-    {
-        opened = true;
-        this.fileName=fileName;
-        handler = init (fileName, AIOCallback.class, maxIO, log);
-        startPoller();
-    }
-    
-    class PollerThread extends Thread
-    {
-        PollerThread ()
-        {
-            super("NativePoller for " + fileName);
-        }
-        public void run()
-        {
-            pollEvents();
-        }
-    }
-    
-    private void startPoller()
-    {
-        checkOpened();
-        poller = new PollerThread(); 
-        poller.start();
-    }
-    
-    public void close()
-    {
-        checkOpened();
-        opened = false;
-        closeInternal(handler);
-        handler = 0;
-    }
-    
-    
-    public void write(long position, long size, ByteBuffer directByteBuffer, AIOCallback aioPackage)
-    {
-        checkOpened();
-        write (handler, position, size, directByteBuffer, aioPackage);
-        
-    }
-
-    public void read(long position, long size, ByteBuffer directByteBuffer, AIOCallback aioPackage)
-    {
-        checkOpened();
-        read (handler, position, size, directByteBuffer, aioPackage);
-        
-    }
-
-    public long size()
-    {
-        checkOpened();
-        // TODO: wire this method to ftell
-        return 0;
-    }
-
-    public void preAllocate(int blocks, long size)
-    {
-        checkOpened();
-        preAllocate(handler, blocks, size);
-    }
-
-    private void pollEvents()
-    {
-        checkOpened();
-        internalPollEvents(handler);
-    }
-    
-    private void checkOpened() 
-    {
-        if (!opened)
-        {
-            throw new RuntimeException("File is not opened");
-        }
-    }
-    
-    /** 
-     * I'm sending aioPackageClazz here, as you could have multiple classLoaders with the same class, and I don't want the hassle of doing classLoading in the Native layer
-     */
-    @SuppressWarnings("unchecked")
-    private static native long init(String fileName, Class aioPackageClazz, int maxIO, Logger logger);
-    
-    private static native void write(long handle, long position, long size, ByteBuffer buffer, AIOCallback aioPackage);
-
-    private static native void read(long handle, long position, long size, ByteBuffer buffer, AIOCallback aioPackage);
-    
-    private static native void preAllocate(long handle, int blocks, long size);
-
-    private static native void closeInternal(long handler);
-    
-    /** Poll asynchrounous events from internal queues */
-    private static native void internalPollEvents(long handler);
-
-    // Should we make this method static?
-    public native void destroyBuffer(ByteBuffer buffer);
-
-    // Should we make this method static?
-    public native ByteBuffer newBuffer(long size);
-   
-    
-}

Copied: trunk/src/main/org/jboss/messaging/core/journal/IOCallback.java (from rev 4128, branches/trunk_tmp_aio/src/main/org/jboss/messaging/core/journal/IOCallback.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/IOCallback.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/IOCallback.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,15 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.messaging.core.journal;
+
+import org.jboss.messaging.core.asyncio.AIOCallback;
+
+public interface IOCallback extends AIOCallback
+{
+	
+}

Modified: trunk/src/main/org/jboss/messaging/core/journal/Journal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/Journal.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/journal/Journal.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -36,6 +36,9 @@
 {
 	// Non transactional operations
 	
+	// TODO: Implement callbacks
+	void appendAddRecord(long id, byte[] record, IOCallback callback) throws Exception;
+	
 	void appendAddRecord(long id, byte[] record) throws Exception;
 	
 	void appendUpdateRecord(long id, byte[] record) throws Exception;
@@ -57,7 +60,7 @@
 	void appendPrepareRecord(long txID) throws Exception;
 	
 	void appendRollbackRecord(long txID) throws Exception;
-		
+	
 	// Load
 	
 	void load(List<RecordInfo> committedRecords,
@@ -69,4 +72,6 @@
 	
 	void stopReclaimer();
 	
+	int getAlignment() throws Exception;
+	
 }

Modified: trunk/src/main/org/jboss/messaging/core/journal/SequentialFile.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/SequentialFile.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/journal/SequentialFile.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -37,17 +37,29 @@
 	 */
 	void open() throws Exception;
 	
+	int getAlignment() throws Exception;
+	
+	int calculateBlockStart(int position) throws Exception;
+	
 	String getFileName();
 	
 	void fill(int position, int size, byte fillCharacter) throws Exception;
 	
 	void delete() throws Exception;
-
+	
+	int write(ByteBuffer bytes, boolean sync, IOCallback callback) throws Exception;
+	
 	int write(ByteBuffer bytes, boolean sync) throws Exception;
-	   
+	
+	int read(ByteBuffer bytes, IOCallback callback) throws Exception;
+	
 	int read(ByteBuffer bytes) throws Exception;
 	
 	void position(int pos) throws Exception;
 	
 	void close() throws Exception;
+	
+	ByteBuffer newBuffer(int size);
+	
+	ByteBuffer wrapBuffer(byte bytes[]);
 }

Copied: trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFile.java (from rev 4128, branches/trunk_tmp_aio/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFile.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFile.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFile.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,239 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.messaging.core.journal.impl;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.jboss.messaging.core.asyncio.AsynchronousFile;
+import org.jboss.messaging.core.asyncio.impl.AsynchronousFileImpl;
+import org.jboss.messaging.core.exception.MessagingException;
+import org.jboss.messaging.core.journal.IOCallback;
+import org.jboss.messaging.core.journal.SequentialFile;
+
+public class AIOSequentialFile implements SequentialFile
+{
+	
+	String journalDir;
+	String fileName;
+	
+	AsynchronousFile aioFile;
+	
+	AtomicLong position = new AtomicLong(0);
+	
+	public AIOSequentialFile(String journalDir, String fileName) throws Exception
+	{
+		this.journalDir = journalDir;
+		this.fileName = fileName;
+	}
+	
+	public int getAlignment() throws Exception
+	{
+		checkOpened();
+		return aioFile.getBlockSize();
+	}
+	
+	public int calculateBlockStart(int position) throws Exception
+	{
+		int alignment = getAlignment();
+		
+		int pos = ((position / alignment) + (position % alignment != 0 ? 1 : 0)) * alignment;
+		
+		return pos;
+	}
+	
+	
+	
+	public void close() throws Exception
+	{
+		checkOpened();
+		aioFile.close();
+		aioFile = null;
+		
+	}
+	
+	public void delete() throws Exception
+	{
+		if (aioFile != null)
+		{
+			aioFile.close();
+			aioFile = null;
+		}
+		
+		File file = new File(journalDir + "/" +  fileName);
+		file.delete();
+	}
+	
+	public void fill(int position, int size, byte fillCharacter)
+	throws Exception
+	{
+		checkOpened();
+		
+		int blockSize = aioFile.getBlockSize();
+		
+		if (size % (10*1024*1024) == 0)
+		{
+			blockSize = 10*1024*1024;
+		}
+		else
+			if (size % (1024*1024) == 0)
+			{
+				blockSize = 1024*1024;
+			}
+			else
+				if (size % (10*1024) == 0)
+				{
+					blockSize = 10*1024;
+				}
+				else
+				{
+					blockSize = aioFile.getBlockSize();
+				}
+		
+		int blocks = size / blockSize;
+		if (size % blockSize != 0)
+		{
+			blocks++;
+		}
+		
+		if (position % aioFile.getBlockSize() != 0)
+		{
+			position = ((position / aioFile.getBlockSize()) + 1) * aioFile.getBlockSize();
+		}
+		//System.out.println("filling " + blocks + " blocks with blockSize=" + blockSize + " on file=" + this.getFileName());
+		aioFile.fill((long)position, blocks, blockSize, (byte)fillCharacter);
+		
+	}
+	
+	public String getFileName()
+	{
+		return fileName;
+	}
+	
+	public void open() throws Exception
+	{
+		aioFile = new AsynchronousFileImpl();
+		aioFile.open(journalDir + "/" + fileName, 1000);
+		position.set(0);
+		
+	}
+	
+	public void position(int pos) throws Exception
+	{
+		position.set(pos);
+		
+	}
+	
+	public int read(ByteBuffer bytes, IOCallback callback) throws Exception
+	{
+		int bytesToRead = bytes.limit();
+		long positionToRead = position.getAndAdd(bytesToRead);
+		
+		bytes.rewind();
+		aioFile.read(positionToRead, bytesToRead, bytes, callback);
+		
+		return bytesToRead;
+	}
+	
+	public int read(ByteBuffer bytes) throws Exception
+	{
+		WaitCompletion waitCompletion = new WaitCompletion();
+		int bytesRead = read (bytes, waitCompletion);
+		
+		waitCompletion.waitLatch();
+		
+		if (waitCompletion.errorMessage != null)
+		{
+			throw new MessagingException(waitCompletion.errorCode, waitCompletion.errorMessage);
+		}
+		
+		return bytesRead;
+	}
+	
+	public int write(ByteBuffer bytes, boolean sync, IOCallback callback)
+	throws Exception
+	{
+		int bytesToWrite = bytes.limit();
+		long positionToWrite = position.getAndAdd(bytesToWrite);
+		
+		aioFile.write(positionToWrite, bytesToWrite, bytes, callback);
+		return bytesToWrite;
+	}
+	
+	public int write(ByteBuffer bytes, boolean sync) throws Exception
+	{
+		WaitCompletion waitCompletion = new WaitCompletion();
+		int bytesWritten = write (bytes, sync, waitCompletion);
+		
+		waitCompletion.waitLatch();
+		
+		if (waitCompletion.errorMessage != null)
+		{
+			throw new MessagingException(waitCompletion.errorCode, waitCompletion.errorMessage);
+		}
+		
+		return bytesWritten;
+	}
+	
+	private void checkOpened() throws Exception
+	{
+		if (aioFile == null)
+		{
+			throw new IllegalStateException ("File not opened");
+		}
+	}
+	
+	class WaitCompletion implements IOCallback
+	{
+		
+		CountDownLatch latch = new CountDownLatch(1);
+		
+		String errorMessage;
+		int errorCode = 0;
+		
+		public void done()
+		{
+			latch.countDown();
+		}
+		
+		public void onError(int errorCode, String errorMessage)
+		{
+			System.out.println("OK Error!");
+			this.errorCode = errorCode;
+			this.errorMessage = errorMessage;
+			
+			latch.countDown();
+			
+		}
+		
+		public void waitLatch() throws Exception
+		{
+			latch.await();
+		}
+		
+	}
+	
+	public ByteBuffer newBuffer(int size)
+	{
+		if (size % aioFile.getBlockSize() != 0)
+		{
+			size = ((size / aioFile.getBlockSize()) + 1) * aioFile.getBlockSize();
+		}
+		return ByteBuffer.allocateDirect(size);
+	}
+	
+	public ByteBuffer wrapBuffer(byte[] bytes)
+	{
+		ByteBuffer newbuffer = newBuffer(bytes.length);
+		newbuffer.put(bytes);
+		return newbuffer;
+	};
+	
+}

Copied: trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFileFactory.java (from rev 4128, branches/trunk_tmp_aio/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFileFactory.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFileFactory.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/AIOSequentialFileFactory.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,31 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.messaging.core.journal.impl;
+
+import org.jboss.messaging.core.journal.SequentialFile;
+import org.jboss.messaging.core.asyncio.impl.AsynchronousFileImpl;
+
+public class AIOSequentialFileFactory extends AbstractSequentialFactory
+{
+	
+	public AIOSequentialFileFactory(String journalDir)
+	{
+		super(journalDir);
+	}
+	
+	public SequentialFile createSequentialFile(String fileName, boolean sync) throws Exception
+	{
+		return new AIOSequentialFile(journalDir, fileName);
+	}
+	
+	public static boolean isSupported()
+	{
+		return AsynchronousFileImpl.isLoaded();
+	}
+	
+}

Copied: trunk/src/main/org/jboss/messaging/core/journal/impl/AbstractSequentialFactory.java (from rev 4128, branches/trunk_tmp_aio/src/main/org/jboss/messaging/core/journal/impl/AbstractSequentialFactory.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/AbstractSequentialFactory.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/AbstractSequentialFactory.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.messaging.core.journal.impl;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+
+public abstract class AbstractSequentialFactory implements SequentialFileFactory
+{
+	protected final String journalDir;
+	
+	public AbstractSequentialFactory(final String journalDir)
+	{
+		this.journalDir = journalDir;
+	}
+	
+	public List<String> listFiles(final String extension) throws Exception
+	{
+		File dir = new File(journalDir);
+		
+		FilenameFilter fnf = new FilenameFilter()
+		{
+			public boolean accept(File file, String name)
+			{
+				return name.endsWith("." + extension);
+			}
+		};
+		
+		String[] fileNames = dir.list(fnf);
+		
+		if (fileNames == null)
+		{
+			throw new IOException("Failed to list: " + journalDir);
+		}
+		
+		return Arrays.asList(fileNames);
+	}
+	
+}

Modified: trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/JournalFileImpl.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -23,6 +23,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.jboss.messaging.core.journal.SequentialFile;
 import org.jboss.messaging.core.logging.Logger;
@@ -129,6 +130,32 @@
 	{
 		return file;
 	}	
+   
+	public String toString()
+	{
+		try
+		{
+			return "JournalFileImpl: " + file.getFileName();
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+			return "Error:" + e.toString();
+		}
+	}
 	
-
+	/** Receive debug information about the journal */
+	public String debug()
+	{
+		StringBuilder builder = new StringBuilder();
+		
+		for (Entry<JournalFile, Integer> entry: negCounts.entrySet())
+		{
+			builder.append(" file = " + entry.getKey() + " negcount value = " + entry.getValue() + "\n");
+		}
+		
+		return builder.toString();
+	}
+	
+	
 }

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-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -39,6 +39,7 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.jboss.messaging.core.journal.IOCallback;
 import org.jboss.messaging.core.journal.PreparedTransactionInfo;
 import org.jboss.messaging.core.journal.RecordInfo;
 import org.jboss.messaging.core.journal.SequentialFile;
@@ -52,11 +53,14 @@
  * A JournalImpl
  * 
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
  *
  */
 public class JournalImpl implements TestableJournal
 {
 	private static final Logger log = Logger.getLogger(JournalImpl.class);
+	//private static final boolean trace = log.isTraceEnabled();
+	private static final boolean trace = true;
 	
 	private static final int STATE_STOPPED = 0;
 	
@@ -67,40 +71,62 @@
 	// The sizes of primitive types
 	
 	private static final int SIZE_LONG = 8;
-   
-   private static final int SIZE_INT = 4;
-   
-   private static final int SIZE_BYTE = 1;
-   
-   public static final int MIN_FILE_SIZE = 1024;
-   
-   public static final int MIN_TASK_PERIOD = 1000;
-   
-   //Record markers - they must be all unique
-   
+	
+	private static final int SIZE_INT = 4;
+	
+	private static final int SIZE_BYTE = 1;
+	
+	public static final int MIN_FILE_SIZE = 1024;
+	
+	public static final int MIN_TASK_PERIOD = 1000;
+	
+	//Record markers - they must be all unique
+	
+	public static final int SIZE_HEADER = 8;
+	
+	public static final int SIZE_ADD_RECORD = SIZE_BYTE + SIZE_LONG + SIZE_INT + SIZE_BYTE;
+	
 	public static final byte ADD_RECORD = 11;
 	
+	public static final byte SIZE_UPDATE_RECORD = SIZE_BYTE + SIZE_LONG + SIZE_INT + SIZE_BYTE;
+	
 	public static final byte UPDATE_RECORD = 12;
 	
+	public static final int SIZE_DELETE_RECORD = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
+	
 	public static final byte DELETE_RECORD = 13;
-			
+	
 	public static final byte ADD_RECORD_TX = 14;
 	
+	public static final int SIZE_ADD_RECORD_TX = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_INT + SIZE_BYTE; // Add the size of Bytes on this
+	
+	
+	public static final int  SIZE_UPDATE_RECORD_TX = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_INT + SIZE_BYTE;  // Add the size of Bytes on this
+	
 	public static final byte UPDATE_RECORD_TX = 15;
 	
+	public static final int  SIZE_DELETE_RECORD_TX = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_BYTE;
+	
 	public static final byte DELETE_RECORD_TX = 16;
 	
+	public static final int SIZE_PREPARE_RECORD = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
+	
 	public static final byte PREPARE_RECORD = 17;
-		
+	
+	
+	public static final byte SIZE_COMMIT_RECORD = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
+	
 	public static final byte COMMIT_RECORD = 18;
 	
+	public static final byte SIZE_ROLLBACK_RECORD = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
+	
 	public static final byte ROLLBACK_RECORD = 19;
 	
 	public static final byte DONE = 20;
 	
 	public static final byte FILL_CHARACTER = 74; // Letter 'J' 
-		
-
+	
+	
 	private final int fileSize;
 	
 	private final int minFiles;
@@ -114,8 +140,8 @@
 	public final String filePrefix;
 	
 	public final String fileExtension;
-	 
 	
+	
 	private final Queue<JournalFile> dataFiles = new ConcurrentLinkedQueue<JournalFile>();
 	
 	private final Queue<JournalFile> freeFiles = new ConcurrentLinkedQueue<JournalFile>();
@@ -123,17 +149,17 @@
 	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
 	 */
 	
 	//TODO - improve concurrency by allowing concurrent accesses if doesn't change current file
 	private final Semaphore lock = new Semaphore(1, true);
-		
+	
 	private volatile JournalFile currentFile ;
-		
+	
 	private volatile int state;
 	
 	private volatile long lastOrderingID;
@@ -147,8 +173,8 @@
 	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)
+			final boolean sync, final SequentialFileFactory fileFactory, final long taskPeriod,
+			final String filePrefix, final String fileExtension)
 	{
 		if (fileSize < MIN_FILE_SIZE)
 		{
@@ -192,12 +218,12 @@
 	
 	// Journal implementation ----------------------------------------------------------------
 	
-	public ByteBuffer allocateBuffer(final int size) throws Exception
-	{
-		return ByteBuffer.allocateDirect(size);
-	}
+	/*public ByteBuffer allocateBuffer(final int size) throws Exception
+   {
+      return ByteBuffer.allocateDirect(size);
+   }*/
 	
-	public void appendAddRecord(final long id, final byte[] record) throws Exception
+	public void appendAddRecord(long id, byte[] record, IOCallback callback) throws Exception
 	{
 		if (state != STATE_LOADED)
 		{
@@ -206,20 +232,43 @@
 		
 		int size = SIZE_BYTE + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		ByteBuffer bb = currentFile.getFile().newBuffer(size);
 		
 		bb.put(ADD_RECORD);		
 		bb.putLong(id);		
 		bb.putInt(record.length);		
 		bb.put(record);		
 		bb.put(DONE);			
-		bb.flip();
+		bb.rewind();
 		
+		appendRecord(bb, true, callback);
+		
+		posFilesMap.put(id, new PosFiles(currentFile));
+	}
+	
+	public void appendAddRecord(final long id, final byte[] record) throws Exception
+	{
+		if (state != STATE_LOADED)
+		{
+			throw new IllegalStateException("Journal must be loaded first");
+		}
+		
+		int size = SIZE_BYTE + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
+		
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
+		
+		bb.put(ADD_RECORD);     
+		bb.putLong(id);      
+		bb.putInt(record.length);     
+		bb.put(record);      
+		bb.put(DONE);
+		bb.rewind();
+		
 		appendRecord(bb, true);
 		
 		posFilesMap.put(id, new PosFiles(currentFile));
 	}
-			
+	
 	public void appendUpdateRecord(final long id, final byte[] record) throws Exception
 	{
 		if (state != STATE_LOADED)
@@ -233,23 +282,23 @@
 		{
 			throw new IllegalStateException("Cannot find add info " + id);
 		}
-			
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		int size = SIZE_UPDATE_RECORD + record.length;
 		
-		bb.put(UPDATE_RECORD);		
-		bb.putLong(id);		
-		bb.putInt(record.length);		
-		bb.put(record);		
-		bb.put(DONE);		
-		bb.flip();
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
-		appendRecord(bb, true);		
+		bb.put(UPDATE_RECORD);     
+		bb.putLong(id);      
+		bb.putInt(record.length);     
+		bb.put(record);      
+		bb.put(DONE);     
+		bb.rewind();
 		
+		appendRecord(bb, true);    
+		
 		posFiles.addUpdateFile(currentFile);
 	}
-		
+	
 	public void appendDeleteRecord(long id) throws Exception
 	{
 		if (state != STATE_LOADED)
@@ -266,76 +315,76 @@
 		
 		posFiles.addDelete(currentFile);
 		
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
+		int size = SIZE_DELETE_RECORD;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
-		bb.put(DELETE_RECORD);		
-		bb.putLong(id);		
-		bb.put(DONE);		
-		bb.flip();
-								
-		appendRecord(bb, true);							
-	}		
+		bb.put(DELETE_RECORD);     
+		bb.putLong(id);      
+		bb.put(DONE);     
+		bb.rewind();
+		
+		appendRecord(bb, true);                   
+	}     
 	
 	public long getTransactionID()
 	{
 		return transactionIDSequence.getAndIncrement();
 	}
-
+	
 	public void appendAddRecordTransactional(final long txID, final long id,
-			                                   final byte[] record) throws Exception
-   {
+			final byte[] record) throws Exception
+			{
 		if (state != STATE_LOADED)
 		{
 			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]);
-
+		int size = SIZE_ADD_RECORD_TX + record.length;
+		
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
+		
 		bb.put(ADD_RECORD_TX);
 		bb.putLong(txID);
 		bb.putLong(id);
 		bb.putInt(record.length);
 		bb.put(record);
-		bb.put(DONE);		
-		bb.flip();
+		bb.put(DONE);     
+		bb.rewind();
 		
 		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
-	{
+			{
 		if (state != STATE_LOADED)
 		{
 			throw new IllegalStateException("Journal must be loaded first");
 		}
 		
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE;
+		int size = SIZE_UPDATE_RECORD_TX + record.length; 
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
-		bb.put(UPDATE_RECORD_TX);		
-		bb.putLong(txID);		
-		bb.putLong(id);		
-		bb.putInt(record.length);		
-		bb.put(record);		
-		bb.put(DONE);		
-		bb.flip();
+		bb.put(UPDATE_RECORD_TX);     
+		bb.putLong(txID);    
+		bb.putLong(id);      
+		bb.putInt(record.length);     
+		bb.put(record);
+		bb.put(DONE);     
+		bb.rewind();
 		
 		appendRecord(bb, false);
 		
 		TransactionNegPos tx = getTransactionInfo(txID);
 		
 		tx.addPos(currentFile, id);
-	}
+			}
 	
 	public void appendDeleteRecordTransactional(final long txID, final long id) throws Exception
 	{
@@ -344,23 +393,23 @@
 			throw new IllegalStateException("Journal must be loaded first");
 		}
 		
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_BYTE;
+		int size = SIZE_DELETE_RECORD_TX;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
-		bb.put(DELETE_RECORD_TX);		
-		bb.putLong(txID);		
-		bb.putLong(id);		
-		bb.put(DONE);			
-		bb.flip();
-								
-		appendRecord(bb, false);		
+		bb.put(DELETE_RECORD_TX);     
+		bb.putLong(txID);    
+		bb.putLong(id);      
+		bb.put(DONE);        
+		bb.rewind();
 		
+		appendRecord(bb, false);      
+		
 		TransactionNegPos tx = getTransactionInfo(txID);
 		
-		tx.addNeg(currentFile, id);		
-	}	
-		
+		tx.addNeg(currentFile, id);      
+	}  
+	
 	public void appendPrepareRecord(final long txID) throws Exception
 	{
 		if (state != STATE_LOADED)
@@ -375,16 +424,16 @@
 			throw new IllegalStateException("Cannot find tx with id " + txID);
 		}
 		
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
+		int size = SIZE_PREPARE_RECORD;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
-		bb.put(PREPARE_RECORD);		
-		bb.putLong(txID);		
-		bb.put(DONE);				
-		bb.flip();
+		bb.put(PREPARE_RECORD);    
+		bb.putLong(txID);
+		bb.put(DONE);           
+		bb.rewind();
 		
-		appendRecord(bb, true);		
+		appendRecord(bb, true);    
 		
 		tx.prepare(currentFile);
 	}
@@ -402,19 +451,19 @@
 		{
 			throw new IllegalStateException("Cannot find tx with id " + txID);
 		}
-				
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		int size = SIZE_COMMIT_RECORD;
 		
-		bb.put(COMMIT_RECORD);		
-		bb.putLong(txID);		
-		bb.put(DONE);				
-		bb.flip();
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
-		appendRecord(bb, true);	
+		bb.put(COMMIT_RECORD);     
+		bb.putLong(txID);    
+		bb.put(DONE);           
+		bb.rewind();
 		
-		tx.commit(currentFile);				
+		appendRecord(bb, true); 
+		
+		tx.commit(currentFile);          
 	}
 	
 	public void appendRollbackRecord(final long txID) throws Exception
@@ -430,24 +479,24 @@
 		{
 			throw new IllegalStateException("Cannot find tx with id " + txID);
 		}
-				
-		int size = SIZE_BYTE + SIZE_LONG + SIZE_BYTE;
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[size]);
+		int size = SIZE_ROLLBACK_RECORD;
 		
-		bb.put(ROLLBACK_RECORD);		
-		bb.putLong(txID);		
-		bb.put(DONE);			
-		bb.flip();
-								
-		appendRecord(bb, true);			
+		ByteBuffer bb = currentFile.getFile().newBuffer(size); 
 		
+		bb.put(ROLLBACK_RECORD);      
+		bb.putLong(txID);
+		bb.put(DONE);        
+		bb.rewind();
+		
+		appendRecord(bb, true);       
+		
 		tx.rollback(currentFile);
 	}
-		
+	
 	public synchronized void load(final List<RecordInfo> committedRecords,
-		                           final List<PreparedTransactionInfo> preparedTransactions) throws Exception
-	{
+			final List<PreparedTransactionInfo> preparedTransactions) throws Exception
+			{
 		if (state != STATE_STARTED)
 		{
 			throw new IllegalStateException("Journal must be in started state");
@@ -462,21 +511,22 @@
 		List<String> fileNames = fileFactory.listFiles(fileExtension);
 		
 		List<JournalFile> orderedFiles = new ArrayList<JournalFile>(fileNames.size());
-				
+		
 		for (String fileName: fileNames)
 		{
 			SequentialFile file = fileFactory.createSequentialFile(fileName, sync);
 			
 			file.open();
 			
-			ByteBuffer bb = ByteBuffer.wrap(new byte[SIZE_LONG]);
+			ByteBuffer bb = file.newBuffer(SIZE_LONG);
 			
 			file.read(bb);
 			
-			bb.flip();
+			//bb.flip();
+			//bb.rewind();
 			
 			long orderingID = bb.getLong();
-						
+			
 			orderedFiles.add(new JournalFileImpl(file, orderingID));
 			
 			file.close();
@@ -487,14 +537,14 @@
 		class JournalFileComparator implements Comparator<JournalFile>
 		{
 			public int compare(JournalFile f1, JournalFile f2)
-	      {
-	         long id1 = f1.getOrderingID();
-	         long id2 = f2.getOrderingID();
-
-	         return (id1 < id2 ? -1 : (id1 == id2 ? 0 : 1));
-	      }
+			{
+				long id1 = f1.getOrderingID();
+				long id2 = f2.getOrderingID();
+				
+				return (id1 < id2 ? -1 : (id1 == id2 ? 0 : 1));
+			}
 		}
-
+		
 		Collections.sort(orderedFiles, new JournalFileComparator());
 		
 		int lastDataPos = -1;
@@ -502,11 +552,16 @@
 		long maxTransactionID = -1;
 		
 		for (JournalFile file: orderedFiles)
-		{	
-			ByteBuffer bb = ByteBuffer.wrap(new byte[fileSize]);
-			
+		{  
 			file.getFile().open();
 			
+			if (trace) 
+			{
+				trace("Loading file " + file.getFile().getFileName());
+			}
+			
+			ByteBuffer bb = file.getFile().newBuffer(fileSize);
+			
 			int bytesRead = file.getFile().read(bb);
 			
 			if (bytesRead != fileSize)
@@ -514,13 +569,14 @@
 				//deal with this better
 				
 				throw new IllegalStateException("File is wrong size " + bytesRead +
-						                          " expected " + fileSize + " : " + file.getFile().getFileName());
+						" expected " + fileSize + " : " + file.getFile().getFileName());
 			}
 			
-			bb.flip();
+//			bb.flip();
+//			bb.rewind();
 			
-			//First long is the ordering timestamp
-			bb.getLong();
+			//First long is the ordering timestamp, we just jump its position
+			bb.position(file.getFile().calculateBlockStart(SIZE_LONG));
 			
 			boolean hasData = false;
 			
@@ -530,15 +586,18 @@
 				
 				byte recordType = bb.get();
 				
+				
 				switch(recordType)
 				{
 					case ADD_RECORD:
-					{									
-						long id = bb.getLong();				
+					{                          
+						long id = bb.getLong();          
 						
-						int size = bb.getInt();						
-						byte[] record = new byte[size];						
-						bb.get(record);						
+						if (trace) log.trace("ADD Record ID = " + id);
+						
+						int size = bb.getInt();                
+						byte[] record = new byte[size];                 
+						bb.get(record);
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -546,22 +605,23 @@
 							repairFrom(pos, file);
 						}
 						else
-						{																				
+						{                                                           
 							records.add(new RecordInfo(id, record, false));
-							hasData = true;						
-
+							hasData = true;                  
+							
 							posFilesMap.put(id, new PosFiles(file));
 						}
-												
+						
 						break;
-					}										
-					case UPDATE_RECORD:						
+					}                             
+					case UPDATE_RECORD:                 
 					{
-						long id = bb.getLong();		
+						long id = bb.getLong();    
+						if (trace) log.trace("Update Record ID = " + id);
 						
-						int size = bb.getInt();						
-						byte[] record = new byte[size];						
-						bb.get(record);						
+						int size = bb.getInt();                
+						byte[] record = new byte[size];                 
+						bb.get(record);                  
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -569,12 +629,12 @@
 							repairFrom(pos, file);
 						}
 						else
-						{					
-							records.add(new RecordInfo(id, record, true));							
-							hasData = true;		
+						{              
+							records.add(new RecordInfo(id, record, true));                    
+							hasData = true;      
 							file.incPosCount();
 							
-						   PosFiles posFiles = posFilesMap.get(id);
+							PosFiles posFiles = posFilesMap.get(id);
 							
 							if (posFiles != null)
 							{
@@ -584,21 +644,23 @@
 								posFiles.addUpdateFile(file);
 							}
 						}
-												
+						
 						break;
-					}					
-					case DELETE_RECORD:						
+					}              
+					case DELETE_RECORD:                 
 					{
-						long id = bb.getLong();	
+						long id = bb.getLong(); 
 						byte end = bb.get();
 						
+						if (trace) log.trace("DeleteRecord id=" + id);
+						
 						if (end != DONE)
 						{
 							repairFrom(pos, file);
 						}
 						else
-						{						
-							recordsToDelete.add(id);							
+						{                 
+							recordsToDelete.add(id);                     
 							hasData = true;
 							
 							PosFiles posFiles = posFilesMap.remove(id);
@@ -606,19 +668,23 @@
 							if (posFiles != null)
 							{
 								posFiles.addDelete(file);
-							}							
+							}                    
 						}
 						
 						break;
-					}					
+					}              
 					case ADD_RECORD_TX:
-					{					
-						long txID = bb.getLong();							
-						maxTransactionID = Math.max(maxTransactionID, txID);						
-						long id = bb.getLong();				
-						int size = bb.getInt();						
-						byte[] record = new byte[size];						
-						bb.get(record);						
+					{              
+						long txID = bb.getLong();                    
+						maxTransactionID = Math.max(maxTransactionID, txID);                 
+						long id = bb.getLong();          
+						
+						if (trace) log.trace("AddRecordTX txID = " + txID + " , id=" + id);
+						
+						
+						int size = bb.getInt();                
+						byte[] record = new byte[size];                 
+						bb.get(record);                  
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -626,16 +692,16 @@
 							repairFrom(pos, file);
 						}
 						else
-						{						
+						{                 
 							TransactionHolder tx = transactions.get(txID);
 							
 							if (tx == null)
 							{
-								tx = new TransactionHolder(txID);								
+								tx = new TransactionHolder(txID);                        
 								transactions.put(txID, tx);
 							}
 							
-							tx.recordInfos.add(new RecordInfo(id, record, false));							
+							tx.recordInfos.add(new RecordInfo(id, record, false));                     
 							
 							TransactionNegPos tnp = transactionInfos.get(txID);
 							
@@ -648,19 +714,22 @@
 							
 							tnp.addPos(file, id);
 							
-							hasData = true;														
+							hasData = true;                                          
 						}
-					
+						
 						break;
-					}		
+					}     
 					case UPDATE_RECORD_TX:
-					{					
-						long txID = bb.getLong();	
-						maxTransactionID = Math.max(maxTransactionID, txID);						
-						long id = bb.getLong();					
-						int size = bb.getInt();						
-						byte[] record = new byte[size];						
-						bb.get(record);						
+					{              
+						long txID = bb.getLong();  
+						maxTransactionID = Math.max(maxTransactionID, txID);                 
+						long id = bb.getLong();
+						
+						if (trace) log.trace("UpdateRecordTX txID = " + txID + " , id=" + id);
+						
+						int size = bb.getInt();                
+						byte[] record = new byte[size];                 
+						bb.get(record);                  
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -668,12 +737,12 @@
 							repairFrom(pos, file);
 						}
 						else
-						{					
+						{              
 							TransactionHolder tx = transactions.get(txID);
 							
 							if (tx == null)
 							{
-								tx = new TransactionHolder(txID);								
+								tx = new TransactionHolder(txID);                        
 								transactions.put(txID, tx);
 							}
 							
@@ -689,17 +758,20 @@
 							}
 							
 							tnp.addPos(file, id);
-
-							hasData = true;							
+							
+							hasData = true;                     
 						}
-											
+						
 						break;
-					}	
+					}  
 					case DELETE_RECORD_TX:
-					{					
-						long txID = bb.getLong();	
-						maxTransactionID = Math.max(maxTransactionID, txID);						
-						long id = bb.getLong();			
+					{              
+						long txID = bb.getLong();  
+						maxTransactionID = Math.max(maxTransactionID, txID);                 
+						long id = bb.getLong();       
+						
+						if (trace) log.trace("DeleteRecordTX txID = " + txID + " , id=" + id);
+						
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -707,16 +779,16 @@
 							repairFrom(pos, file);
 						}
 						else
-						{					
+						{              
 							TransactionHolder tx = transactions.get(txID);
 							
 							if (tx == null)
 							{
-								tx = new TransactionHolder(txID);								
+								tx = new TransactionHolder(txID);                        
 								transactions.put(txID, tx);
 							}
 							
-							tx.recordsToDelete.add(id);							
+							tx.recordsToDelete.add(id);                     
 							
 							TransactionNegPos tnp = transactionInfos.get(txID);
 							
@@ -729,15 +801,18 @@
 							
 							tnp.addNeg(file, id);
 							
-							hasData = true;							
+							hasData = true;                     
 						}
-											
+						
 						break;
-					}	
+					}  
 					case PREPARE_RECORD:
 					{
-						long txID = bb.getLong();				
-						maxTransactionID = Math.max(maxTransactionID, txID);						
+						long txID = bb.getLong();           
+						
+						if (trace) log.trace("Prepare txID=" + txID);
+						
+						maxTransactionID = Math.max(maxTransactionID, txID);                 
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -752,7 +827,7 @@
 							{
 								throw new IllegalStateException("Cannot find tx with id " + txID);
 							}
-														
+							
 							tx.prepared = true;
 							
 							TransactionNegPos tnp = transactionInfos.get(txID);
@@ -762,16 +837,19 @@
 								throw new IllegalStateException("Cannot find tx " + txID);
 							}
 							
-							tnp.prepare(file);	
+							tnp.prepare(file);   
 							
-							hasData = true;			
+							hasData = true;         
 						}
 						
 						break;
 					}
 					case COMMIT_RECORD:
 					{
-						long txID = bb.getLong();	
+						long txID = bb.getLong();  
+						
+						if (trace) log.trace("Commit txID=" + txID);
+						
 						maxTransactionID = Math.max(maxTransactionID, txID);
 						byte end = bb.get();
 						
@@ -785,19 +863,19 @@
 							
 							if (tx != null)
 							{
-   							records.addAll(tx.recordInfos);							
-   							recordsToDelete.addAll(tx.recordsToDelete);	
-   							
-   							TransactionNegPos tnp = transactionInfos.remove(txID);
-   							
-   							if (tnp == null)
-   							{
-   								throw new IllegalStateException("Cannot find tx " + txID);
-   							}
-   							
-   							tnp.commit(file);			
-   							
-   							hasData = true;			
+								records.addAll(tx.recordInfos);                    
+								recordsToDelete.addAll(tx.recordsToDelete);  
+								
+								TransactionNegPos tnp = transactionInfos.remove(txID);
+								
+								if (tnp == null)
+								{
+									throw new IllegalStateException("Cannot find tx " + txID);
+								}
+								
+								tnp.commit(file);       
+								
+								hasData = true;         
 							}
 						}
 						
@@ -805,8 +883,11 @@
 					}
 					case ROLLBACK_RECORD:
 					{
-						long txID = bb.getLong();		
-						maxTransactionID = Math.max(maxTransactionID, txID);						
+						long txID = bb.getLong();     
+						
+						if (trace) log.trace("RollbacktxID=" + txID);
+						
+						maxTransactionID = Math.max(maxTransactionID, txID);                 
 						byte end = bb.get();
 						
 						if (end != DONE)
@@ -818,24 +899,24 @@
 							TransactionHolder tx = transactions.remove(txID);
 							
 							if (tx != null)
-							{								
-   							TransactionNegPos tnp = transactionInfos.remove(txID);
-   							
-   							if (tnp == null)
-   							{
-   								throw new IllegalStateException("Cannot find tx " + txID);
-   							}
-   							
-   							tnp.rollback(file);	
-   							
-   							hasData = true;			
+							{                       
+								TransactionNegPos tnp = transactionInfos.remove(txID);
+								
+								if (tnp == null)
+								{
+									throw new IllegalStateException("Cannot find tx " + txID);
+								}
+								
+								tnp.rollback(file);  
+								
+								hasData = true;         
 							}
 						}
 						
 						break;
 					}
-					case FILL_CHARACTER:						
-					{	
+					case FILL_CHARACTER:                
+					{  
 						//End of records in file - we check the file only contains fill characters from this point
 						while (bb.hasRemaining())
 						{
@@ -848,49 +929,52 @@
 							}
 						}
 						
-						break;						
-					}					
-					default:						
+						break;                  
+					}              
+					default:                
 					{
 						throw new IllegalStateException("Journal " + file.getFile().getFileName() +
-								                         " is corrupt, invalid record type " + recordType);
+								" is corrupt, invalid record type " + recordType);
 					}
 				}
 				
+				bb.position(file.getFile().calculateBlockStart(bb.position()));
+				
 				if (recordType != FILL_CHARACTER)
 				{
 					lastDataPos = bb.position();
 				}
 			}
-						
+			
 			if (hasData)
-			{			
+			{        
 				dataFiles.add(file);
 				
-				file.getFile().close();				
+				file.getFile().close();          
 			}
 			else
-			{				
+			{           
 				//Empty dataFiles with no data
 				freeFiles.add(file);
 				
-				//Position it ready for writing
-				file.getFile().position(SIZE_LONG);
-			}								
-		}			
+//				//Position it ready for writing
+				file.getFile().position(file.getFile().calculateBlockStart(SIZE_LONG));
+			}                       
+		}        
 		
 		transactionIDSequence.set(maxTransactionID + 1);
 		
 		//Create any more files we need
-				
+		
 		//FIXME - size() involves a scan
 		int filesToCreate = minFiles - (dataFiles.size() + freeFiles.size());
 		
 		for (int i = 0; i < filesToCreate; i++)
 		{
+			// Keeping all files opened can be very costly (mainly on AIO)
 			freeFiles.add(createFile());
 		}
-												
+		
 		//The current file is the last one
 		
 		Iterator<JournalFile> iter = dataFiles.iterator();
@@ -906,9 +990,9 @@
 		}
 		
 		if (currentFile != null)
-		{		
+		{     
 			currentFile.getFile().open();
-		
+			
 			currentFile.getFile().position(lastDataPos);
 			
 			currentFile.setOffset(lastDataPos);
@@ -916,8 +1000,8 @@
 		else
 		{
 			currentFile = freeFiles.remove();
-		}				
-								
+		}           
+		
 		for (RecordInfo record: records)
 		{
 			if (!recordsToDelete.contains(record.id))
@@ -953,64 +1037,77 @@
 				preparedTransactions.add(info);
 			}
 		}
-				
+		
 		state = STATE_LOADED;
+			}
+	
+	public int getAlignment() throws Exception
+	{
+		return this.currentFile.getFile().getAlignment();
 	}
 	
+	public synchronized void checkReclaimStatus() throws Exception
+	{
+		JournalFile[] files = new JournalFile[dataFiles.size()];
+		
+		reclaimer.scan(dataFiles.toArray(files));
+		
+	}
+	
 	// TestableJournal implementation --------------------------------------------------------------
-			
+	
 	public synchronized void checkAndReclaimFiles() throws Exception
-	{		
-		JournalFile[] files = new JournalFile[dataFiles.size()];
+	{
+		checkReclaimStatus();
 		
-		reclaimer.scan(dataFiles.toArray(files));
+		for (JournalFile file: dataFiles)
+		{           
+			if (file.isCanReclaim())
+			{
+				//File can be reclaimed or deleted
 				
-		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();
-   			}
-   		}
+				if (trace) log.trace("Reclaiming file " + file);
+				
+				dataFiles.remove(file);
+				
+				//FIXME - size() involves a scan!!!
+				if (freeFiles.size() + dataFiles.size() + 1 < minFiles)
+				{              
+					//Re-initialise it
+					
+					long newOrderingID = generateOrderingID();
+					
+					SequentialFile sf = file.getFile();
+					
+					sf.open();
+					
+					ByteBuffer bb = sf.newBuffer(SIZE_LONG); 
+					
+					bb.putLong(newOrderingID);
+					
+					//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);
+					
+					int bytesWritten = sf.write(bb, true);
+					
+					JournalFile jf = new JournalFileImpl(sf, newOrderingID);
+					
+					sf.position(bytesWritten);
+					
+					jf.setOffset(bytesWritten);
+					
+					freeFiles.add(jf);  
+				}
+				else
+				{
+					file.getFile().open();
+					
+					file.getFile().delete();
+				}
+			}
 		}
 	}
 	
@@ -1059,12 +1156,12 @@
 		{
 			file.getFile().close();
 		}
-
+		
 		currentFile = null;
 		
 		dataFiles.clear();
 		
-		freeFiles.clear();		
+		freeFiles.clear();      
 		
 		state = STATE_STOPPED;
 	}
@@ -1095,19 +1192,19 @@
 	}
 	
 	// Public -----------------------------------------------------------------------------
-			
+	
 	// Private -----------------------------------------------------------------------------
-		
+	
 	private void appendRecord(ByteBuffer bb, boolean sync) throws Exception
 	{
 		lock.acquire();
 		
 		int size = bb.capacity();
-				
+		
 		try
-		{   					
+		{                 
 			checkFile(size);
-			currentFile.getFile().write(bb, sync);			
+			currentFile.getFile().write(bb, sync);       
 			currentFile.extendOffset(size);
 		}
 		finally
@@ -1116,43 +1213,62 @@
 		}
 	}
 	
+	private void appendRecord(ByteBuffer bb, boolean sync, IOCallback callback) throws Exception
+	{
+		lock.acquire();
+		
+		int size = bb.capacity();
+		
+		try
+		{                 
+			checkFile(size);
+			currentFile.getFile().write(bb, sync, callback);       
+			currentFile.extendOffset(size);
+		}
+		finally
+		{
+			lock.release();
+		}
+	}
+	
 	private void repairFrom(int pos, JournalFile file) throws Exception
 	{
 		log.warn("Corruption has been detected in file: " + file.getFile().getFileName() +
-				   " in the record that starts at position " + pos + ". " + 
-				   "The most likely cause is that a crash occurred in the previous run. The corrupt record will be discarded.");
+				" in the record that starts at position " + pos + ". " + 
+		"The most likely cause is that a crash occurred in the previous run. The corrupt record will be discarded.");
 		
 		file.getFile().fill(pos, fileSize - pos, FILL_CHARACTER);
 		
 		file.getFile().position(pos);
 	}
-			
+	
 	private JournalFile createFile() throws Exception
 	{
 		long orderingID = generateOrderingID();
 		
 		String fileName = filePrefix + "-" + orderingID + "." + fileExtension;
-						
+		
+		if (trace) log.trace("Creating file " + fileName);
+		
 		SequentialFile sequentialFile = fileFactory.createSequentialFile(fileName, sync);
 		
 		sequentialFile.open();
-						
+		
 		sequentialFile.fill(0, fileSize, FILL_CHARACTER);
 		
-		ByteBuffer bb = ByteBuffer.wrap(new byte[SIZE_LONG]);
+		ByteBuffer bb = sequentialFile.newBuffer(SIZE_LONG); 
 		
 		bb.putLong(orderingID);
 		
-		bb.flip();
+		bb.rewind();
 		
-		sequentialFile.write(bb, true);
+		int bytesWritten = sequentialFile.write(bb, true);
 		
-		sequentialFile.position(SIZE_LONG);
-		
 		JournalFile info = new JournalFileImpl(sequentialFile, orderingID);
 		
-		info.extendOffset(SIZE_LONG);
 		
+		info.extendOffset(bytesWritten);
+		
 		return info;
 	}
 	
@@ -1164,29 +1280,34 @@
 		{
 			//Ensure it's unique
 			try
-			{				
+			{           
 				Thread.sleep(1);
 			}
 			catch (InterruptedException ignore)
-			{				
+			{           
 			}
 			orderingID = System.currentTimeMillis();
 		}
-		lastOrderingID = orderingID;	
+		lastOrderingID = orderingID;  
 		
 		return orderingID;
 	}
 	
 	private void checkFile(final int size) throws Exception
 	{
+		
+		if (size % currentFile.getFile().getAlignment() != 0)
+		{
+			throw new IllegalStateException("You can't write blocks in a size different than " + currentFile.getFile().getAlignment());
+		}
 		//We take into account the first timestamp long
-		if (size > fileSize - SIZE_LONG)
+		if (size > fileSize - currentFile.getFile().calculateBlockStart(SIZE_HEADER))
 		{
 			throw new IllegalArgumentException("Record is too large to store " + size);
 		}
-
+		
 		if (currentFile == null || fileSize - currentFile.getOffset() < size)
-		{					
+		{
 			currentFile.getFile().close();
 			
 			dataFiles.add(currentFile);
@@ -1200,7 +1321,7 @@
 			{
 				currentFile = createFile();
 			}
-		}		
+		}     
 	}
 	
 	private TransactionNegPos getTransactionInfo(final long txID)
@@ -1216,8 +1337,13 @@
 		
 		return tx;
 	}
-				
 	
+	private void trace(String message)
+	{
+		log.info(message);
+	}
+	
+	
 	// Inner classes ---------------------------------------------------------------------------
 	
 	private class ReclaimerTask extends TimerTask
@@ -1228,12 +1354,12 @@
 			
 			return super.cancel();
 		}
-
+		
 		public synchronized void run()
 		{
 			try
 			{
-				checkAndReclaimFiles();		
+				checkAndReclaimFiles();    
 			}
 			catch (Exception e)
 			{
@@ -1241,8 +1367,8 @@
 				
 				cancel();
 			}
-		}		
-	}	
+		}     
+	}  
 	
 	private static class PosFiles
 	{
@@ -1282,7 +1408,7 @@
 			}
 		}
 	}
-		
+	
 	private class TransactionNegPos
 	{
 		private List<Pair<JournalFile, Long>> pos;
@@ -1297,7 +1423,7 @@
 			{
 				transactionPos = new HashSet<JournalFile>();
 			}
-						
+			
 			if (!transactionPos.contains(file))
 			{
 				transactionPos.add(file);
@@ -1305,39 +1431,39 @@
 				//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);				
+		{     
+			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);		
+		{        
+			addTXPosCount(file);    
 			
 			if (neg == null)
 			{
 				neg = new ArrayList<Pair<JournalFile, Long>>();
 			}
 			
-			neg.add(new Pair<JournalFile, Long>(file, id));			
+			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)
@@ -1347,25 +1473,25 @@
 						posFilesMap.put(p.b, posFiles);
 					}
 					else
-					{					
-					   posFiles.addUpdateFile(p.a);
+					{              
+						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);
-   			}
+				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
@@ -1373,11 +1499,11 @@
 			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
@@ -1407,4 +1533,28 @@
 			}
 		}
 	}
+	
+	public String debug() throws Exception
+	{
+		this.checkReclaimStatus();
+		
+		StringBuilder builder = new StringBuilder();
+		
+		for (JournalFile file: dataFiles)
+		{
+			builder.append("DataFile:" + file + " posCounter = " + file.getPosCount() + " reclaimStatus = " +  file.isCanReclaim() + "\n");
+			if (file instanceof JournalFileImpl)
+			{
+				builder.append(((JournalFileImpl)file).debug());
+				
+			}
+		}
+		
+		builder.append("CurrentFile:" + currentFile+ " posCounter = " + currentFile.getPosCount() + "\n");
+		builder.append(((JournalFileImpl)currentFile).debug());
+		
+		
+		return builder.toString();
+	}
+	
 }

Modified: trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFile.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFile.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFile.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -26,6 +26,7 @@
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
 
+import org.jboss.messaging.core.journal.IOCallback;
 import org.jboss.messaging.core.journal.SequentialFile;
 import org.jboss.messaging.core.logging.Logger;
 
@@ -39,7 +40,7 @@
 public class NIOSequentialFile implements SequentialFile
 {
 	private static final Logger log = Logger.getLogger(NIOSequentialFile.class);
-			
+	
 	private String journalDir;
 	
 	private String fileName;
@@ -51,28 +52,39 @@
 	private FileChannel channel;
 	
 	private RandomAccessFile rfile;
-		
+	
 	public NIOSequentialFile(final String journalDir, final String fileName, final boolean sync)
 	{
 		this.journalDir = journalDir;
 		
 		this.fileName = fileName;
 		
-		this.sync = sync;		
+		this.sync = sync;    
 	}
 	
+	public int getAlignment()
+	{
+		return 1;
+	}
+	
+	public int calculateBlockStart(int position) throws Exception
+	{
+		return position;
+	}
+	
+	
 	public String getFileName()
 	{
 		return fileName;
 	}
-		
+	
 	public void open() throws Exception
-	{		
+	{     
 		file = new File(journalDir + "/" + fileName);
-
+		
 		rfile = new RandomAccessFile(file, "rw");
-
-		channel = rfile.getChannel();		
+		
+		channel = rfile.getChannel();    
 	}
 	
 	public void fill(final int position, final int size, final byte fillCharacter) throws Exception
@@ -81,17 +93,17 @@
 		
 		for (int i = 0; i < size; i++)
 		{
-			bb.put(fillCharacter);			
+			bb.put(fillCharacter);        
 		}
 		
 		bb.flip();
-
+		
 		channel.position(position);
-
+		
 		channel.write(bb);
-
-		channel.force(false);	
 		
+		channel.force(false);   
+		
 		channel.position(0);
 	}
 	
@@ -100,42 +112,84 @@
 		channel.close();
 		
 		rfile.close();
-						
+		
 		channel = null;
 		
 		rfile = null;
 		
 		file = null;
 	}
-
+	
 	public void delete() throws Exception
-	{		
+	{     
 		file.delete();
 		
-		close();		
+		close();    
 	}
-
+	
 	public int read(ByteBuffer bytes) throws Exception
 	{
-		int bytesRead = channel.read(bytes);
+		return read(bytes, null);
+	}
+	
+	public int read(ByteBuffer bytes, IOCallback callback) throws Exception
+	{
+		try
+		{
+			int bytesRead = channel.read(bytes);
+			if (callback != null)
+			{
+				callback.done();
+			}
+			bytes.flip();
+			return bytesRead;
+		}
+		catch (Exception e)
+		{
+			if (callback != null)
+			{
+				callback.onError(-1, e.getLocalizedMessage());
+			}
+			
+			throw e;
+		}
 		
-		return bytesRead;
 	}
-
+	
 	public int write(ByteBuffer bytes, boolean sync) throws Exception
 	{
+		return write(bytes, sync, null);
+	}
+	
+	public int write(ByteBuffer bytes, boolean sync, IOCallback callback) throws Exception
+	{
 		int bytesRead = channel.write(bytes);
 		
 		if (sync && this.sync)
 		{
 			channel.force(false);
 		}
-
+		
+		if (callback != null)
+		{
+			callback.done();
+		}
+		
 		return bytesRead;
 	}
-
+	
 	public void position(final int pos) throws Exception
 	{
 		channel.position(pos);
 	}
+	
+	public ByteBuffer newBuffer(int size)
+	{
+		return ByteBuffer.allocate(size);
+	}
+	
+	public ByteBuffer wrapBuffer(byte[] bytes)
+	{
+		return ByteBuffer.wrap(bytes);
+	}
 }

Modified: trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFileFactory.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFileFactory.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/NIOSequentialFileFactory.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -21,12 +21,6 @@
   */
 package org.jboss.messaging.core.journal.impl;
 
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
 import org.jboss.messaging.core.journal.SequentialFile;
 import org.jboss.messaging.core.journal.SequentialFileFactory;
 
@@ -37,13 +31,11 @@
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  *
  */
-public class NIOSequentialFileFactory implements SequentialFileFactory
+public class NIOSequentialFileFactory extends AbstractSequentialFactory implements SequentialFileFactory 
 {
-	private final String journalDir;
-	
 	public NIOSequentialFileFactory(final String journalDir)
 	{
-		this.journalDir = journalDir;
+		super(journalDir);
 	}	
 	
 	public SequentialFile createSequentialFile(final String fileName, final boolean sync)
@@ -51,25 +43,4 @@
 		return new NIOSequentialFile(journalDir, fileName, sync);
 	}
 
-	public List<String> listFiles(final String extension) throws Exception
-	{
-		File dir = new File(journalDir);
-		
-		FilenameFilter fnf = new FilenameFilter()
-		{
-			public boolean accept(File file, String name)
-			{
-				return name.endsWith("." + extension);
-			}
-		};
-		
-		String[] fileNames = dir.list(fnf);
-		
-		if (fileNames == null)
-		{
-			throw new IOException("Failed to list: " + journalDir);
-		}
-		
-		return Arrays.asList(fileNames);
-	}
 }

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-30 22:35:42 UTC (rev 4142)
+++ trunk/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -21,6 +21,7 @@
 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.AIOSequentialFileFactory;
 import org.jboss.messaging.core.journal.impl.NIOSequentialFileFactory;
 import org.jboss.messaging.core.logging.Logger;
 import org.jboss.messaging.core.message.Message;
@@ -84,9 +85,9 @@
 	
 	public JournalStorageManager(Configuration config)
 	{
-		if (config.getJournalType() != JournalType.NIO)
+		if (config.getJournalType() != JournalType.NIO && config.getJournalType() != JournalType.ASYNCIO)
 		{
-			throw new IllegalArgumentException("Only support NIO journal");
+			throw new IllegalArgumentException("Only NIO and AsyncIO are supported journals");
 		}
 		
 		String bindingsDir = config.getBindingsDirectory();
@@ -99,7 +100,7 @@
 		checkAndCreateDir(bindingsDir, config.isCreateBindingsDir());
 			
 	   SequentialFileFactory bindingsFF = new NIOSequentialFileFactory(bindingsDir);
-	      
+      
 	   bindingsJournal = new JournalImpl(1024 * 1024, 2, true, bindingsFF, 10000, "jbm-bindings", "bindings");
 	      
 	   String journalDir = config.getJournalDirectory();
@@ -111,7 +112,31 @@
 	   
 	   checkAndCreateDir(journalDir, config.isCreateBindingsDir());
 	       
-	   SequentialFileFactory journalFF = new NIOSequentialFileFactory(journalDir);
+      SequentialFileFactory journalFF = null;
+      
+      if (config.getJournalType() == JournalType.ASYNCIO)
+      {
+         if (!AIOSequentialFileFactory.isSupported())
+         {
+            log.warn("AIO wasn't located on this platform, using just standard Java NIO. If you are on Linux, install LibAIO and the required wrapper and you will get a lot of performance benefit");
+            journalFF = new NIOSequentialFileFactory(bindingsDir);
+         }
+         else
+         {
+            journalFF = new AIOSequentialFileFactory(bindingsDir);
+            log.info("AIO loaded successfully");
+         }
+      }
+      else 
+      if (config.getJournalType() == JournalType.NIO)
+      {
+         journalFF = new NIOSequentialFileFactory(bindingsDir);
+      }
+      else
+      if (config.getJournalType() == JournalType.JDBC)
+      { // Sanity check only... this is previously tested
+         throw new IllegalArgumentException("JDBC Journal is not supported yet");
+      }
 	      
 	   messageJournal = new JournalImpl(config.getJournalFileSize(), 
 	   		config.getJournalMinFiles(), config.isJournalSync(), journalFF,

Modified: trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/MultiThreadWriteNativeTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/MultiThreadWriteNativeTest.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/MultiThreadWriteNativeTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -20,10 +20,17 @@
 import junit.framework.TestCase;
 
 import org.jboss.messaging.core.asyncio.AIOCallback;
-import org.jboss.messaging.core.asyncio.impl.JlibAIO;
+import org.jboss.messaging.core.asyncio.impl.AsynchronousFileImpl;
 import org.jboss.messaging.core.logging.Logger;
 
-// you need to define java.library.path=${project-root}/native/src/.libs
+/**
+ * 
+ * you need to define -Djava.library.path=${project-root}/native/src/.libs when calling the JVM
+ * If you are running this test in eclipse you should do:
+ *   I - Run->Open Run Dialog
+ *   II - Find the class on the list (you will find it if you already tried running this testcase before)  
+ *   III - Add -Djava.library.path=<your project place>/native/src/.libs
+ *   */
 public class MultiThreadWriteNativeTest extends TestCase
 {
 
@@ -47,12 +54,12 @@
    static class ExecClass implements Runnable
    {
        
-       JlibAIO aio;
+       AsynchronousFileImpl aio;
        ByteBuffer buffer;
        AIOCallback callback;
        
        
-       public ExecClass(JlibAIO aio, ByteBuffer buffer, AIOCallback callback)
+       public ExecClass(AsynchronousFileImpl aio, ByteBuffer buffer, AIOCallback callback)
        {
            this.aio = aio;
            this.buffer = buffer;
@@ -81,7 +88,7 @@
 
    
    
-   private static void addData(JlibAIO aio, ByteBuffer buffer, AIOCallback callback) throws Exception
+   private static void addData(AsynchronousFileImpl aio, ByteBuffer buffer, AIOCallback callback) throws Exception
    {
        //aio.write(getNewPosition()*SIZE, SIZE, buffer, callback);
        executor.execute(new ExecClass(aio, buffer, callback));
@@ -125,10 +132,11 @@
    private void executeTest(boolean sync) throws Throwable
    {
        log.info(sync?"Sync test:":"Async test");
-       JlibAIO jlibAIO = new JlibAIO();
+       AsynchronousFileImpl jlibAIO = new AsynchronousFileImpl();
        jlibAIO.open(FILE_NAME, 21000);
        log.debug("Preallocating file");
-       jlibAIO.preAllocate(NUMBER_OF_THREADS,  SIZE * NUMBER_OF_LINES);
+      
+       jlibAIO.fill(0l, NUMBER_OF_THREADS,  SIZE * NUMBER_OF_LINES, (byte)0);
        log.debug("Done Preallocating file");
        
        CountDownLatch latchStart = new CountDownLatch (NUMBER_OF_THREADS + 1);
@@ -179,9 +187,9 @@
        Throwable failed = null;
        CountDownLatch latchStart;
        boolean sync;
-       JlibAIO libaio;
+       AsynchronousFileImpl libaio;
 
-       public ThreadProducer(String name, CountDownLatch latchStart, JlibAIO libaio, boolean sync)
+       public ThreadProducer(String name, CountDownLatch latchStart, AsynchronousFileImpl libaio, boolean sync)
        {
            super(name);
            this.latchStart = latchStart;
@@ -281,9 +289,9 @@
        boolean errorCalled = false;
        CountDownLatch latchDone;
        ByteBuffer releaseMe;
-       JlibAIO libaio;
+       AsynchronousFileImpl libaio;
        
-       public LocalCallback(CountDownLatch latchDone, ByteBuffer releaseMe, JlibAIO libaio)
+       public LocalCallback(CountDownLatch latchDone, ByteBuffer releaseMe, AsynchronousFileImpl libaio)
        {
            this.latchDone = latchDone;
            this.releaseMe = releaseMe;

Modified: trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/SingleThreadWriteNativeTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/SingleThreadWriteNativeTest.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/core/asyncio/impl/SingleThreadWriteNativeTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -13,16 +13,27 @@
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.concurrent.CountDownLatch;
 
 import org.jboss.messaging.core.asyncio.AIOCallback;
-import org.jboss.messaging.core.asyncio.impl.JlibAIO;
+import org.jboss.messaging.core.asyncio.impl.AsynchronousFileImpl;
+import org.jboss.messaging.core.logging.Logger;
 
 import junit.framework.TestCase;
 
-//you need to define java.library.path=${project-root}/native/src/.libs
+/**
+ * 
+ * you need to define -Djava.library.path=${project-root}/native/src/.libs when calling the JVM
+ * If you are running this test in eclipse you should do:
+ *   I - Run->Open Run Dialog
+ *   II - Find the class on the list (you will find it if you already tried running this testcase before)  
+ *   III - Add -Djava.library.path=<your project place>/native/src/.libs
+ *   */
 public class SingleThreadWriteNativeTest extends TestCase
 {
+   private static final Logger log = Logger.getLogger(SingleThreadWriteNativeTest.class);
+   
    private static CharsetEncoder UTF_8_ENCODER = Charset.forName("UTF-8").newEncoder();
    
    
@@ -52,7 +63,108 @@
        buffer.put((byte)'\n');
        
    }
+
+   public void testTwoFiles() throws Exception
+   {
+      final AsynchronousFileImpl controller = new AsynchronousFileImpl();
+      final AsynchronousFileImpl controller2 = new AsynchronousFileImpl();
+      controller.open(FILE_NAME + ".1", 10000);
+      controller2.open(FILE_NAME + ".2", 10000);
+      
+      int numberOfLines = 100000;
+      int size = 1024;
+       
+       try
+       {
+           System.out.println("++testDirectDataNoPage"); System.out.flush();
+           CountDownLatch latchDone = new CountDownLatch(numberOfLines);
+           CountDownLatch latchDone2 = new CountDownLatch(numberOfLines);
+           
+           ByteBuffer block = controller.newBuffer(size);
+           encodeBufer(block);
+
+           preAlloc(controller, numberOfLines * size);
+           preAlloc(controller2, numberOfLines * size);
+
+           ArrayList<LocalAIO> list = new ArrayList<LocalAIO>();
+           ArrayList<LocalAIO> list2 = new ArrayList<LocalAIO>();
    
+           for (int i=0; i<numberOfLines; i++)
+           {
+               list.add(new LocalAIO(latchDone));
+               list2.add(new LocalAIO(latchDone2));
+           }
+           
+          
+           long valueInitial = System.currentTimeMillis();
+   
+           System.out.println("Adding data");
+           
+           long lastTime = System.currentTimeMillis();
+           int counter = 0;
+           Iterator<LocalAIO> iter2 = list2.iterator();
+           
+           for (LocalAIO tmp: list)
+           {
+               LocalAIO tmp2 = iter2.next();
+               
+               controller.write(counter * size, size, block, tmp);
+               controller.write(counter * size, size, block, tmp2);
+               if (++counter % 5000 == 0)
+               {
+                   System.out.println(5000*1000/(System.currentTimeMillis()-lastTime) + " rec/sec (Async)");
+                   lastTime = System.currentTimeMillis();
+               }
+               
+           }
+           
+           System.out.println("Data added " + (System.currentTimeMillis() - valueInitial));
+           
+           
+           System.out.println("Finished append " + (System.currentTimeMillis() - valueInitial) + " received = " + LocalAIO.staticDone);
+           System.out.println("Flush now");
+           System.out.println("Received " + LocalAIO.staticDone);
+           long timeTotal = System.currentTimeMillis() - valueInitial;
+
+           System.out.println("Asynchronous time = " + timeTotal + " for " + numberOfLines + " registers " + " size each line = " + size  + " Records/Sec=" + (numberOfLines*1000/timeTotal) + " (Assynchronous)");
+
+           latchDone.await();
+           latchDone2.await();
+   
+           timeTotal = System.currentTimeMillis() - valueInitial;
+           System.out.println("After completions time = " + timeTotal + " for " + numberOfLines + " registers " + " size each line = " + size  + " Records/Sec=" + (numberOfLines*1000/timeTotal) + " (Assynchronous)");
+   
+           for (LocalAIO tmp: list)
+           {
+               assertEquals(1, tmp.timesDoneCalled);
+               assertTrue(tmp.doneCalled);
+               assertFalse(tmp.errorCalled);
+           }
+           
+           controller.destroyBuffer(block);
+           
+           controller.close();
+       }
+       finally
+       {
+           try {controller.close();} catch (Exception ignored){}
+       }
+       
+       
+   }
+   
+   public void testAnnoyingPoller() throws Exception
+   {
+      final AsynchronousFileImpl controller = new AsynchronousFileImpl();
+      for (int i=0; i< 1000; i++)
+      {
+         controller.open(FILE_NAME, 10000);
+         controller.close();
+         
+      }
+   }
+   
+
    public void testAddBeyongSimultaneousLimit() throws Exception
    {
        asyncData(150000,1024,100);
@@ -60,27 +172,141 @@
 
    public void testAddAsyncData() throws Exception
    {
-       asyncData(150000,1024,20000);
+       asyncData(500000,1024,30000);
    }
    
+   public void testValidateData() throws Exception
+   {
+      validateData(150000,1024,20000);
+   }
+
+   public void testInvalidReads() throws Exception
+   {
+      class LocalCallback implements AIOCallback
+      {
+
+         CountDownLatch latch = new CountDownLatch(1);
+         boolean error;
+         public void done()
+         {
+            latch.countDown();
+         }
+
+         public void onError(int errorCode, String errorMessage)
+         {
+            this.error = true;
+            latch.countDown();
+         }
+      }
+
+      AsynchronousFileImpl controller = new AsynchronousFileImpl();
+      try
+      {
+          
+          final int NUMBER_LINES = 1;
+          final int SIZE = 512;
+          
+          controller.open(FILE_NAME, 10);
+          controller.close();
+          
+          controller = new AsynchronousFileImpl();
+          
+          controller.open(FILE_NAME, 10);
+          
+          controller.fill(0,1, 512, (byte)'j');
+          
+          
+          ByteBuffer buffer = controller.newBuffer(SIZE);
+  
+          
+          buffer.clear();
+          
+          for (int i=0; i<SIZE; i++)
+          {
+              buffer.put((byte)(i%100));
+          }
+          
+          LocalCallback callbackLocal = new LocalCallback();
+          
+          controller.write(0, 512, buffer, callbackLocal);
+          
+          callbackLocal.latch.await();
+          
+          ByteBuffer newBuffer = ByteBuffer.allocateDirect(50);
+          
+          callbackLocal = new LocalCallback();
+          
+          controller.read(0, 50, newBuffer, callbackLocal);
+          
+          callbackLocal.latch.await();
+          
+          //assertTrue(callbackLocal.error);
+          
+          callbackLocal = new LocalCallback();
+          
+          byte bytes[] = new byte[512];
+          
+          try
+          {
+             newBuffer = ByteBuffer.wrap(bytes);
+             
+             controller.read(0, 512, newBuffer, callbackLocal);
+             
+             fail("An exception was supposed to be thrown");
+          }
+          catch (Exception ignored)
+          {
+          }
+          
+          //newBuffer = ByteBuffer.allocateDirect(512);
+          newBuffer = controller.newBuffer(512);
+          callbackLocal = new LocalCallback();
+          controller.read(0, 512, newBuffer,callbackLocal);
+          callbackLocal.latch.await();
+          assertFalse(callbackLocal.error);
+          
+          newBuffer.rewind();
+          
+          byte[] bytesRead = new byte[SIZE];
+          
+          newBuffer.get(bytesRead);
+          
+          for (int i=0; i<SIZE;i++)
+          {
+             assertEquals((byte)(i%100), bytesRead[i]);
+          }
+          
+          
+          controller.destroyBuffer(buffer);
+      }
+      finally
+      {
+          try { controller.close(); } catch (Throwable ignored){}
+          
+      }
+          
+   }
+
+   
    public void testRead() throws Exception
    {
-       
-       
-       
-
-       final JlibAIO controller = new JlibAIO();
+       final AsynchronousFileImpl controller = new AsynchronousFileImpl();
        try
        {
            
-           final int NUMBER_LINES = 300;
+           final int NUMBER_LINES = 1000;
            final int SIZE = 1024;
            
            controller.open(FILE_NAME, 10);
+
+           log.info("Filling file");
            
+           controller.fill(0,1, NUMBER_LINES * SIZE, (byte)'j');           
+           
            ByteBuffer buffer = controller.newBuffer(SIZE);
    
-           
+           log.info("Writing file");
+
            for (int i=0; i<NUMBER_LINES; i++)
            {
                buffer.clear();
@@ -100,6 +326,13 @@
                assertTrue(aio.doneCalled);
            }
            
+
+           // If you call close you're supposed to wait events to finish before closing it
+           log.info("Closing file");
+           controller.close();
+           log.info("Reading file");
+           controller.open(FILE_NAME, 10);
+           
            ByteBuffer newBuffer = ByteBuffer.allocateDirect(SIZE);
            
            for (int i=0; i<NUMBER_LINES; i++)
@@ -150,9 +383,199 @@
            
    }
    
+   
+   
+   public void testConcurrentClose() throws Exception
+   {
+      // The test might eventually pass if broken
+      for (int i=0; i<10; i++)
+         internalConcurrentClose();
+   }
+   
+   public void internalConcurrentClose() throws Exception
+   {
+       final AsynchronousFileImpl controller = new AsynchronousFileImpl();
+       try
+       {
+           
+           final int NUMBER_LINES = 1000;
+           CountDownLatch readLatch = new CountDownLatch (NUMBER_LINES);
+           final int SIZE = 1024;
+           
+           controller.open(FILE_NAME, 10000);
+
+           log.info("Filling file");
+           
+           controller.fill(0,1, NUMBER_LINES * SIZE, (byte)'j');           
+           
+           log.info("Writing file");
+
+           for (int i=0; i<NUMBER_LINES; i++)
+           {
+               ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE);
+              
+               buffer.clear();
+               addString ("Str value " + i + "\n", buffer);
+               for (int j=buffer.position(); j<buffer.capacity()-1;j++)
+               {
+                   buffer.put((byte)' ');
+               }
+               buffer.put((byte)'\n');
+               
+               
+               LocalAIO aio = new LocalAIO(readLatch);
+               controller.write(i * SIZE, SIZE, buffer, aio);
+           }
+           
+
+           long counter = readLatch.getCount();
+           // If you call close you're supposed to wait events to finish before closing it
+           controller.close();
+           log.info("Closed file with counter = " + counter);
+           assertEquals(0, readLatch.getCount());
+           readLatch.await();
+           log.info("Reading file");
+           controller.open(FILE_NAME, 10);
+           
+           ByteBuffer newBuffer = ByteBuffer.allocateDirect(SIZE);
+
+           ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE);
+           
+           for (int i=0; i<NUMBER_LINES; i++)
+           {
+               newBuffer.clear();
+               addString ("Str value " + i + "\n", newBuffer);
+               for (int j=newBuffer.position(); j<newBuffer.capacity()-1;j++)
+               {
+                   newBuffer.put((byte)' ');
+               }
+               newBuffer.put((byte)'\n');
+               
+               
+               CountDownLatch latch = new CountDownLatch(1);
+               LocalAIO aio = new LocalAIO(latch);
+               controller.read(i * SIZE, SIZE, buffer, aio);
+               latch.await();
+               assertFalse(aio.errorCalled);
+               assertTrue(aio.doneCalled);
+               
+               byte bytesRead[] = new byte[SIZE];
+               byte bytesCompare[] = new byte[SIZE];
+               
+               newBuffer.rewind();
+               newBuffer.get(bytesCompare);
+               buffer.rewind();
+               buffer.get(bytesRead);
+               
+               for (int count=0;count<SIZE;count++)
+               {
+                   assertEquals("byte position " + count + " differs on line " + i, bytesCompare[count], bytesRead[count]);
+               }
+               
+               
+               //byte[] byteCompare = new byte[SIZE];
+               //byte[] byteRead = new byte[SIZE];
+
+               assertTrue(buffer.equals(newBuffer));
+           }
+           
+       }
+       finally
+       {
+           try { controller.close(); } catch (Throwable ignored){}
+           
+       }
+           
+   }
+   
+   /**
+    * This method is not used unless you uncomment testValidateData
+    * The purpose of this method is to verify if the information generated by one of the write methods is correct
+    * @param numberOfLines
+    * @param size
+    * @param aioLimit
+    * @throws Exception
+    */
+   private void validateData(int numberOfLines, int size, int aioLimit) throws Exception
+   {
+       final AsynchronousFileImpl controller = new AsynchronousFileImpl();
+       controller.open(FILE_NAME, aioLimit);
+       
+       ByteBuffer compareBlock = ByteBuffer.allocateDirect(size);
+       encodeBufer(compareBlock);
+       
+       ByteBuffer readBuffer = controller.newBuffer(size);
+       
+       
+       boolean firstInvalid = false;
+       for (int i=0;i<numberOfLines;i++)
+       {
+          if (i % 1000 == 0)
+          {
+             log.info("line = " + i);
+          }
+          CountDownLatch latch = new CountDownLatch(1);
+          LocalAIO callback = new LocalAIO(latch);
+          controller.read(i * size, size, readBuffer, callback);
+
+          latch.await();
+          
+          if (!compareBuffers(compareBlock, readBuffer))
+          {
+             //log.info("Invalid line at " + i);
+             firstInvalid=true;
+          }
+          else
+          {
+             if (firstInvalid)
+             {
+                for (int line=0;line<10;line++) log.info("*********************************************");
+                log.warn("Valid line after an invalid line!!!");
+             }
+          }
+          
+          readBuffer.position(100);
+          ByteBuffer buf1 = readBuffer.slice();
+          
+          //System.out.println("buf1=" + buf1);
+          
+          
+          
+       }
+   }
+   
+   
+   private boolean compareBuffers(ByteBuffer buffer1, ByteBuffer buffer2)
+   {
+      
+      buffer1.rewind();
+      buffer2.rewind();
+      
+      if (buffer1.limit() != buffer2.limit())
+      {
+         return false;
+      }
+      
+      byte bytes1[] = new byte[buffer1.limit()];
+      byte bytes2[] = new byte[buffer2.limit()];
+      
+      buffer1.get(bytes1);
+      buffer2.get(bytes2);
+      
+      for (int i=0; i< bytes1.length; i++)
+      {
+         if (bytes1[i] != bytes2[i])
+         {
+            return false;
+         }
+      }
+      
+      return true;
+   }
+   
    private void asyncData(int numberOfLines, int size, int aioLimit) throws Exception
    {
-       final JlibAIO controller = new JlibAIO();
+       final AsynchronousFileImpl controller = new AsynchronousFileImpl();
        controller.open(FILE_NAME, aioLimit);
        
        try
@@ -182,7 +605,7 @@
            for (LocalAIO tmp: list)
            {
                controller.write(counter * size, size, block, tmp);
-               if (++counter % 5000 == 0)
+               if (++counter % 20000 == 0)
                {
                    System.out.println(5000*1000/(System.currentTimeMillis()-lastTime) + " rec/sec (Async)");
                    lastTime = System.currentTimeMillis();
@@ -233,7 +656,7 @@
            final int SIZE = 1024;
            //final int SIZE = 512;
            
-           final JlibAIO controller = new JlibAIO();
+           final AsynchronousFileImpl controller = new AsynchronousFileImpl();
            controller.open(FILE_NAME, 2000);
 
            ByteBuffer block = controller.newBuffer(SIZE);
@@ -285,11 +708,11 @@
        
    }
    
-   private void preAlloc(JlibAIO controller, long size)
+   private void preAlloc(AsynchronousFileImpl controller, long size)
    {
        System.out.println("Pre allocating");  System.out.flush();
        long startPreAllocate = System.currentTimeMillis();
-       controller.preAllocate(1, size);
+       controller.fill(0l, 1, size, (byte)0);
        long endPreAllocate = System.currentTimeMillis() - startPreAllocate;
        if (endPreAllocate != 0) System.out.println("PreAllocated the file in " + endPreAllocate + " seconds, What means " + (size/endPreAllocate) + " bytes per millisecond");
    }
@@ -297,7 +720,7 @@
    
    public void testInvalidWrite() throws Exception
    {
-       final JlibAIO controller = new JlibAIO();
+       final AsynchronousFileImpl controller = new AsynchronousFileImpl();
        controller.open(FILE_NAME, 2000);
 
        try
@@ -337,7 +760,7 @@
    
    public void testInvalidAlloc() throws Exception
    {
-       JlibAIO controller = new JlibAIO();
+       AsynchronousFileImpl controller = new AsynchronousFileImpl();
        try
        {
            // You don't need to open the file to alloc it

Added: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/AIOSequentialFileFactoryTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/AIOSequentialFileFactoryTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/AIOSequentialFileFactoryTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,63 @@
+/*
+  * 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.tests.unit.core.journal.impl;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+
+import org.jboss.messaging.core.journal.SequentialFile;
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.impl.AIOSequentialFileFactory;
+
+public class AIOSequentialFileFactoryTest extends SequentialFileFactoryTestBase
+{
+
+   protected String journalDir = System.getProperty("user.home") + "/journal-test";
+   
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+
+      File file = new File(journalDir);
+      
+      deleteDirectory(file);
+      
+      file.mkdir();     
+   }
+
+   protected SequentialFileFactory createFactory()
+   {
+      return new AIOSequentialFileFactory(journalDir);
+   }
+   
+   public void testBuffer() throws Exception
+   {
+      SequentialFile file = factory.createSequentialFile("filtetmp.log", true);
+      file.open();
+      ByteBuffer buff = file.newBuffer(10);
+      assertEquals(512, buff.limit());
+      //ByteBuffer buffer = 
+   }
+   
+
+}

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FakeJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FakeJournalImplTest.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FakeJournalImplTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -37,4 +37,9 @@
 	{
 		return new FakeSequentialFileFactory();
 	}
+
+   protected int getAlignment()
+   {
+      return 1;
+   }
 }

Added: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FileFactoryTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FileFactoryTestBase.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/FileFactoryTestBase.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,82 @@
+/*
+  * 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.tests.unit.core.journal.impl;
+
+import java.nio.ByteBuffer;
+
+import org.jboss.messaging.core.journal.SequentialFile;
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.tests.util.UnitTestCase;
+
+public abstract class FileFactoryTestBase extends UnitTestCase
+{
+   protected abstract SequentialFileFactory createFactory();
+   
+   protected SequentialFileFactory factory;
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      factory = createFactory();
+   }
+   
+
+   
+   // Protected ---------------------------------
+   
+   protected void checkFill(SequentialFile file, int pos, int size, byte fillChar) throws Exception
+   {
+      file.fill(pos, size, fillChar);
+      
+      file.close();
+      
+      file.open();
+      
+      file.position(pos);
+      
+      
+      
+      ByteBuffer bb = ByteBuffer.allocateDirect(size);
+      
+      int bytesRead = file.read(bb);
+      
+      assertEquals(size, bytesRead);
+      
+      bb.rewind();
+      
+      byte bytes[] = new byte[size];
+      
+      bb.get(bytes);
+      
+      for (int i = 0; i < size; i++)
+      {
+         //log.info(" i is " + i);
+         assertEquals(fillChar, bytes[i]);
+      }
+            
+   }
+   
+   
+
+}

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestBase.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestBase.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -68,13 +68,13 @@
 	protected String fileExtension = "jbm";
 	
 	protected SequentialFileFactory fileFactory;
-					
+	
 	protected void setUp() throws Exception
 	{
 		super.setUp();
 		
 		resetFileFactory();
-
+		
 		transactions.clear();
 		
 		records.clear();
@@ -91,7 +91,7 @@
 				journal.stop();
 			}
 			catch (Exception ignore)
-			{				
+			{           
 			}
 		}
 		
@@ -106,22 +106,22 @@
 	}
 	
 	protected abstract SequentialFileFactory getFileFactory() throws Exception;
-		
+	
 	// Private ---------------------------------------------------------------------------------
 	
 	protected void setup(int minFreeFiles, int fileSize, boolean sync)
-	{		
+	{     
 		this.minFiles = minFreeFiles;
 		this.fileSize = fileSize;
 		this.sync = sync;
 	}
 	
 	public void createJournal() throws Exception
-	{		
+	{     
 		journal =
 			new JournalImpl(fileSize, minFiles, sync, fileFactory, 1000, filePrefix, fileExtension);
 	}
-		
+	
 	protected void startJournal() throws Exception
 	{
 		journal.start();
@@ -129,10 +129,18 @@
 	
 	protected void stopJournal() throws Exception
 	{
+		stopJournal(true);
+	}
+	
+	protected void stopJournal(boolean reclaim) throws Exception
+	{
 		//We do a reclaim in here
-		journal.checkAndReclaimFiles();
+		if (reclaim)
+		{
+			journal.checkAndReclaimFiles();
+		}
 		
-		journal.stop();		
+		journal.stop();      
 	}
 	
 	protected void loadAndCheck() throws Exception
@@ -164,7 +172,7 @@
 		}
 		
 		checkTransactionsEquivalent(prepared, preparedTransactions);
-	}		
+	}     
 	
 	protected void load() throws Exception
 	{
@@ -173,51 +181,57 @@
 	
 	protected void add(long... arguments) throws Exception
 	{
+		addWithSize(recordLength, arguments);
+	}
+	
+	protected void addWithSize(int size, long... arguments) throws Exception
+	{
 		for (int i = 0; i < arguments.length; i++)
-		{		
-			byte[] record = generateRecord(recordLength);
+		{     
+			byte[] record = generateRecord(size);
 			
 			journal.appendAddRecord(arguments[i], record);
 			
-			records.add(new RecordInfo(arguments[i], record, false));			
+			records.add(new RecordInfo(arguments[i], record, false));         
 		}
 	}
 	
 	protected void update(long... arguments) throws Exception
 	{
 		for (int i = 0; i < arguments.length; i++)
-		{		
+		{     
 			byte[] updateRecord = generateRecord(recordLength);
 			
 			journal.appendUpdateRecord(arguments[i], updateRecord);
 			
-			records.add(new RecordInfo(arguments[i], updateRecord, true));	
+			records.add(new RecordInfo(arguments[i], updateRecord, true)); 
 		}
 	}
 	
 	protected void delete(long... arguments) throws Exception
 	{
 		for (int i = 0; i < arguments.length; i++)
-		{		
+		{     
 			journal.appendDeleteRecord(arguments[i]);
 			
 			removeRecordsForID(arguments[i]);
 		}
 	}
-			
+	
 	protected void addTx(long txID, long... arguments) throws Exception
 	{
 		TransactionHolder tx = getTransaction(txID);
 		
 		for (int i = 0; i < arguments.length; i++)
-		{		
-			byte[] record = generateRecord(recordLength);
+		{  
+			// SIZE_BYTE + SIZE_LONG + SIZE_LONG + SIZE_INT + record.length + SIZE_BYTE
+			byte[] record = generateRecord(recordLength - JournalImpl.SIZE_ADD_RECORD_TX );
 			
 			journal.appendAddRecordTransactional(txID, arguments[i], record);
 			
 			tx.records.add(new RecordInfo(arguments[i], record, false));
 			
-		}		
+		}     
 	}
 	
 	protected void updateTx(long txID, long... arguments) throws Exception
@@ -225,24 +239,24 @@
 		TransactionHolder tx = getTransaction(txID);
 		
 		for (int i = 0; i < arguments.length; i++)
-		{		
-			byte[] updateRecord = generateRecord(recordLength);
-							
+		{     
+			byte[] updateRecord = generateRecord(recordLength - JournalImpl.SIZE_UPDATE_RECORD_TX );
+			
 			journal.appendUpdateRecordTransactional(txID, arguments[i], updateRecord);
 			
 			tx.records.add(new RecordInfo(arguments[i], updateRecord, true));
-		}		
+		}     
 	}
-
+	
 	protected void deleteTx(long txID, long... arguments) throws Exception
 	{
 		TransactionHolder tx = getTransaction(txID);
 		
 		for (int i = 0; i < arguments.length; i++)
-		{						
+		{                 
 			journal.appendDeleteRecordTransactional(txID, arguments[i]);
 			
-			tx.deletes.add(arguments[i]);			
+			tx.deletes.add(arguments[i]);       
 		}
 		
 	}
@@ -262,7 +276,7 @@
 		}
 		
 		journal.appendPrepareRecord(txID);
-				
+		
 		tx.prepared = true;
 	}
 	
@@ -335,7 +349,7 @@
 		
 		return tx;
 	}
-			
+	
 	protected void checkTransactionsEquivalent(List<PreparedTransactionInfo> expected, List<PreparedTransactionInfo> actual)
 	{
 		assertEquals("Lists not same length", expected.size(), actual.size());
@@ -390,7 +404,7 @@
 			assertEquals("type not same", rexpected.isUpdate, ractual.isUpdate);
 			
 			assertByteArraysEquivalent(rexpected.data, ractual.data);
-		}		
+		}     
 	}
 	
 	protected byte[] generateRecord(int length)
@@ -403,6 +417,11 @@
 		return record;
 	}
 	
+	protected String debugJournal() throws Exception
+	{
+		return "***************************************************\n" + ((JournalImpl)journal).debug() + "***************************************************\n" ;
+	}
+	
 	class TransactionHolder
 	{
 		List<RecordInfo> records = new ArrayList<RecordInfo>();

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestUnit.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestUnit.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/JournalImplTestUnit.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -32,6 +32,7 @@
  * A JournalImplTestBase
  * 
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
  *
  */
 public abstract class JournalImplTestUnit extends JournalImplTestBase
@@ -94,7 +95,7 @@
 		{
 			//OK
 		}
-		stopJournal();		
+		stopJournal();    
 	}
 	
 	public void testParams() throws Exception
@@ -120,7 +121,7 @@
 		{
 			//Ok
 		}
-				
+		
 		try
 		{
 			new JournalImpl(10 * 1024, 10, true, null, 5000, filePrefix, fileExtension);
@@ -171,79 +172,79 @@
 	{
 		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();	
+			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
 		{
@@ -253,6 +254,36 @@
 		}
 	}
 	
+	public void testEmptyReopen() throws Exception
+	{
+		setup(2, 10 * 1024, true);
+		createJournal();
+		startJournal();
+		load();
+		
+		List<String> files1 = fileFactory.listFiles(fileExtension);
+		
+		assertEquals(2, files1.size());
+		
+		stopJournal();
+		
+		setup(2, 10 * 1024, true);
+		createJournal();
+		startJournal();
+		load();
+		
+		List<String> files2 = fileFactory.listFiles(fileExtension);
+		
+		assertEquals(2, files2.size());
+		
+		for (String file: files1)
+		{
+			assertTrue(files2.contains(file));
+		}
+		
+		stopJournal(); 
+	}
+	
 	public void testCreateFilesOnLoad() throws Exception
 	{
 		setup(10, 10 * 1024, true);
@@ -281,8 +312,8 @@
 		{
 			assertTrue(files2.contains(file));
 		}
-				
-		stopJournal();	
+		
+		stopJournal(); 
 	}
 	
 	public void testReduceFreeFiles() throws Exception
@@ -311,40 +342,104 @@
 		{
 			assertTrue(files2.contains(file));
 		}
-				
-		stopJournal();	
+		
+		stopJournal(); 
 	}
+	
+	private int calculateRecordsPerFile(int fileSize, int alignment, int recordSize)
+	{
+		recordSize = calculateRecordSize(recordSize, alignment);
+		return fileSize / recordSize;
+	}
+	
+	/** 
+	 * 
+	 * Use: calculateNumberOfFiles (fileSize, numberOfRecords, recordSize,  numberOfRecords2, recordSize2, , ...., numberOfRecordsN, recordSizeN);
+	 * */
+	private int calculateNumberOfFiles(int fileSize, int alignment, int ... record) throws Exception
+	{
+		
+		
+//		log.info("Processing calculateNumberOfFiles(" + fileSize + ", " + alignment);
+//		for (int recordN: record)
+//		{
+//		System.out.print(", " + recordN);
+//		}
+//		System.out.println(");");
+		
+		int headerSize = calculateRecordSize(JournalImpl.SIZE_HEADER, alignment);
+		int currentPosition = headerSize;
+		int totalFiles = 0;
+		
+		for (int i=0; i<record.length; i+=2)
+		{
+			int numberOfRecords = record[i];
+			int recordSize = calculateRecordSize(record[i+1], alignment);
 			
+//			log.info(" numberOfRecords = " + numberOfRecords + " recordSize=" + recordSize);
+			
+			while (numberOfRecords>0)
+			{
+				int recordsFit = (fileSize - currentPosition) / recordSize;
+				if (numberOfRecords < recordsFit)
+				{
+					currentPosition = currentPosition + numberOfRecords*recordSize;
+					numberOfRecords = 0;
+//					log.info("   Adding " + numberOfRecords + " records of size " + recordSize + " numberOfFiles = " + totalFiles + " Position=" + currentPosition);
+				}
+				else if (recordsFit > 0)
+				{
+					currentPosition = currentPosition + recordsFit*recordSize;
+					numberOfRecords -= recordsFit;
+//					log.info("   Adding " + recordsFit + " (fitting) of size " + recordSize + " numberOfFiles = " + totalFiles + " Position = " + currentPosition);
+				}
+				else
+				{
+					totalFiles++;
+					currentPosition = headerSize;
+//					log.info("   Exploded... totalFiles=" + totalFiles);
+				}
+			}
+		}
+		
+		// System.out.println("   Returning " + totalFiles);
+		
+		return totalFiles;
+		
+	}
+	
 	public void testCheckCreateMoreFiles() throws Exception
 	{
-		setup(10, 10 * 1024, true);
+		setup(2, 10 * 1024, true);
 		createJournal();
 		startJournal();
 		load();
 		
 		List<String> files1 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(10, files1.size());
+		assertEquals(2, files1.size());
 		
 		assertEquals(0, journal.getDataFilesCount());
-		assertEquals(9, journal.getFreeFilesCount());
+		assertEquals(1, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-				
+		
 		//Fill all the files
 		
-		for (int i = 0; i < 90; i++)
+		for (int i = 0; i < 91; i++)
 		{
 			add(i);
 		}
 		
-		assertEquals(9, journal.getDataFilesCount());
+		int numberOfFiles = calculateNumberOfFiles(10*1024, journal.getAlignment(), 91, JournalImpl.SIZE_ADD_RECORD + this.recordLength);
+		
+		assertEquals(numberOfFiles, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(90, journal.getIDMapSize());
-				
+		assertEquals(91, journal.getIDMapSize());
+		
 		List<String> files2 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(10, files2.size());
-				
+		assertEquals(numberOfFiles + 1, files2.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files2.contains(file));
@@ -357,14 +452,16 @@
 			add(i);
 		}
 		
-		assertEquals(10, journal.getDataFilesCount());
+		numberOfFiles = calculateNumberOfFiles(10*1024,journal.getAlignment(), 95, JournalImpl.SIZE_ADD_RECORD + this.recordLength);
+		
+		assertEquals(numberOfFiles, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(95, journal.getIDMapSize());
 		
 		List<String> files3 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(11, files3.size());
-				
+		assertEquals(numberOfFiles + 1, files3.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files3.contains(file));
@@ -377,22 +474,38 @@
 			add(i);
 		}
 		
-		assertEquals(22, journal.getDataFilesCount());
+		numberOfFiles = calculateNumberOfFiles(10*1024,journal.getAlignment(), 200, JournalImpl.SIZE_ADD_RECORD + this.recordLength);
+		
+		assertEquals(numberOfFiles, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(200, journal.getIDMapSize());
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(23, files4.size());
-				
+		assertEquals(numberOfFiles + 1, files4.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files4.contains(file));
 		}
-						
-		stopJournal();	
+		
+		stopJournal(); 
 	}
 	
+	// Validate the methods that are used on assertions
+	public void testCalculations() throws Exception
+	{
+		
+		assertEquals(0,calculateNumberOfFiles(10*1024, 1, 1, 10, 2, 20));
+		assertEquals(0,calculateNumberOfFiles(10*1024, 512, 1, 1));
+		assertEquals(0,calculateNumberOfFiles(10*1024, 512, 19, 10));
+		assertEquals(1,calculateNumberOfFiles(10*1024, 512, 20, 10));
+		assertEquals(0,calculateNumberOfFiles(3000, 500, 2, 1000, 1, 500));
+		assertEquals(1,calculateNumberOfFiles(3000, 500, 2, 1000, 1, 1000));
+		assertEquals(9,calculateNumberOfFiles(10240, 1, 90, 1038, 45, 10));      
+		assertEquals(11,calculateNumberOfFiles(10*1024, 512, 60, 14 + 1024, 30, 14));
+	}
+	
 	public void testReclaim() throws Exception
 	{
 		setup(10, 10 * 1024, true);
@@ -407,20 +520,27 @@
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(9, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-				
-		for (int i = 0; i < 100; i++)
+		
+		
+		int addRecordsPerFile = calculateRecordsPerFile(10*1024, journal.getAlignment(), JournalImpl.SIZE_ADD_RECORD + this.recordLength);
+		
+		
+		// Fills exactly 10 files
+		int initialNumberOfAddRecords = addRecordsPerFile * 10;
+		for (int i = 0; i < initialNumberOfAddRecords; i++)
 		{
 			add(i);
 		}
 		
-		assertEquals(11, journal.getDataFilesCount());
+		// We have already 10 files, but since we have the last file on exact size, the counter will be numberOfUsedFiles -1
+		assertEquals(9, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(100, journal.getIDMapSize());
+		assertEquals(initialNumberOfAddRecords, journal.getIDMapSize());
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(12, files4.size());
-				
+		assertEquals(10, files4.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files4.contains(file));
@@ -428,34 +548,54 @@
 		
 		//Now delete half of them
 		
-		for (int i = 0; i < 50; i++)
+		int deleteRecordsPerFile = calculateRecordsPerFile(10*1024, journal.getAlignment(), JournalImpl.SIZE_DELETE_RECORD);
+		
+		for (int i = 0; i < initialNumberOfAddRecords / 2; i++)
 		{
 			delete(i);
 		}
 		
-		assertEquals(11, journal.getDataFilesCount());
+		
+		
+		int numberOfFiles = calculateNumberOfFiles(10*1024, journal.getAlignment(), initialNumberOfAddRecords, JournalImpl.SIZE_ADD_RECORD + this.recordLength, 
+				initialNumberOfAddRecords/2, JournalImpl.SIZE_DELETE_RECORD);
+		
+		
+		if ((initialNumberOfAddRecords / 2) % deleteRecordsPerFile == 0)
+		{
+			// The file is already full, next add would fix it
+			numberOfFiles --;
+		}
+		
+		assertEquals(numberOfFiles, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(50, journal.getIDMapSize());
+		assertEquals(initialNumberOfAddRecords/2, journal.getIDMapSize());
 		
 		//Make sure the deletes aren't in the current file
 		
-		for (int i = 100; i < 110; i++)
+		for (int i = 0; i < 10; i++)
 		{
-			add(i);
+			add(initialNumberOfAddRecords + i);
 		}
 		
-		assertEquals(12, journal.getDataFilesCount());
+		numberOfFiles = calculateNumberOfFiles(10*1024, journal.getAlignment(), 
+				initialNumberOfAddRecords, JournalImpl.SIZE_ADD_RECORD + this.recordLength, 
+				initialNumberOfAddRecords / 2, JournalImpl.SIZE_DELETE_RECORD,
+				10, JournalImpl.SIZE_ADD_RECORD + this.recordLength);
+		
+		
+		assertEquals(numberOfFiles, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(60, journal.getIDMapSize());
+		assertEquals(initialNumberOfAddRecords/2 + 10, 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());
+		assertEquals(journal.getAlignment()==1?6:7, journal.getDataFilesCount());
+		assertEquals(journal.getAlignment()==1?3:2, journal.getFreeFilesCount());
+		assertEquals(initialNumberOfAddRecords /2 + 10, journal.getIDMapSize());
 		
 		List<String> files5 = fileFactory.listFiles(fileExtension);
 		
@@ -463,7 +603,7 @@
 		
 		//Now delete the rest
 		
-		for (int i = 50; i < 110; i++)
+		for (int i = initialNumberOfAddRecords /2; i < initialNumberOfAddRecords + 10; i++)
 		{
 			delete(i);
 		}
@@ -485,13 +625,13 @@
 		List<String> files6 = fileFactory.listFiles(fileExtension);
 		
 		assertEquals(10, files6.size());
-										
-		stopJournal();	
+		
+		stopJournal(); 
 	}
-			
+	
 	public void testReclaimAddUpdateDeleteDifferentFiles1() throws Exception
 	{
-		setup(2, 1046, true); //Make sure there is one record per file
+		setup(2, calculateRecordSize(8, getAlignment()) +  calculateRecordSize(JournalImpl.SIZE_ADD_RECORD + recordLength, getAlignment()), true); //Make sure there is one record per file
 		createJournal();
 		startJournal();
 		load();
@@ -525,7 +665,7 @@
 	
 	public void testReclaimAddUpdateDeleteDifferentFiles2() throws Exception
 	{
-		setup(2, 1046, true); //Make sure there is one record per file
+		setup(2, calculateRecordSize(8, getAlignment()) +  calculateRecordSize(JournalImpl.SIZE_ADD_RECORD + recordLength, getAlignment()), true); //Make sure there is one record per file
 		createJournal();
 		startJournal();
 		load();
@@ -582,20 +722,20 @@
 		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(calculateNumberOfFiles(fileSize , journal.getAlignment(), 100, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		List<String> files2 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(12, files2.size());
-				
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 100, recordLength) + 1, files2.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files2.contains(file));
@@ -605,14 +745,14 @@
 		
 		//Make sure nothing reclaimed
 		
-		assertEquals(11, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 100, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		List<String> files3 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(12, files3.size());
-				
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 100, recordLength) + 1, files3.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files3.contains(file));
@@ -625,14 +765,14 @@
 			updateTx(1, i);
 		}
 		
-		assertEquals(22, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(23, files4.size());
-				
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength) + 1, files4.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files4.contains(file));
@@ -642,34 +782,36 @@
 		
 		//Make sure nothing reclaimed
 		
-		assertEquals(22, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength) , 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(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX), journal.getDataFilesCount());
+		
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		List<String> files7 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(23, files7.size());
-				
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX) + 1, files7.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files7.contains(file));
@@ -677,14 +819,14 @@
 		
 		journal.checkAndReclaimFiles();
 		
-		assertEquals(22, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		List<String> files8 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(23, files8.size());
-				
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX) + 1, files8.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files8.contains(file));
@@ -701,6 +843,10 @@
 			rollback(1);
 		}
 		
+		// If this change, we need to consider commit or rollback size on the test
+		assertEquals(JournalImpl.SIZE_ROLLBACK_RECORD, JournalImpl.SIZE_COMMIT_RECORD);
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 200, recordLength, 200, JournalImpl.SIZE_DELETE_RECORD_TX, 1, JournalImpl.SIZE_COMMIT_RECORD), journal.getDataFilesCount());
+		
 		//Add more records to make sure we get to the next file
 		
 		for (int i = 200; i < 210; i++)
@@ -708,14 +854,24 @@
 			add(i);
 		}
 		
-		assertEquals(23, journal.getDataFilesCount());
+		
+		
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 
+				200, recordLength, 
+				200, JournalImpl.SIZE_DELETE_RECORD_TX, 
+				1, JournalImpl.SIZE_COMMIT_RECORD,
+				10, JournalImpl.SIZE_ADD_RECORD + recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(10, journal.getIDMapSize());
 		
 		List<String> files9 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(24, files9.size());
-				
+		assertEquals(calculateNumberOfFiles(fileSize , journal.getAlignment(), 
+				200, recordLength, 
+				200, JournalImpl.SIZE_DELETE_RECORD_TX, 
+				1, JournalImpl.SIZE_COMMIT_RECORD,
+				10, JournalImpl.SIZE_ADD_RECORD + recordLength) + 1, files9.size());
+		
 		for (String file: files1)
 		{
 			assertTrue(files9.contains(file));
@@ -724,19 +880,20 @@
 		journal.checkAndReclaimFiles();
 		
 		//Most Should now be reclaimed - leaving 10 left in total
-
-		assertEquals(1, journal.getDataFilesCount());
-		assertEquals(8, journal.getFreeFilesCount());
+		
+		assertEquals(journal.getAlignment()==1?1:2, journal.getDataFilesCount());
+		assertEquals(journal.getAlignment()==1?8:7, journal.getFreeFilesCount());
 		assertEquals(10, journal.getIDMapSize());
 		
 		List<String> files10 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(10, files10.size());	
+		assertEquals(10, files10.size());   
 	}
 	
 	public void testReclaimTransactionalSimple() throws Exception
 	{
-		setup(2, 1054, true);
+		setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + 
+				calculateRecordSize(recordLength, getAlignment()), true);
 		createJournal();
 		startJournal();
 		load();
@@ -748,7 +905,7 @@
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(1, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-					
+		
 		addTx(1, 1);           // in file 0
 		
 		deleteTx(1, 1);        // in file 1
@@ -763,7 +920,7 @@
 		
 		//Make sure we move on to the next file
 		
-		add(2);                // in file 2
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 2);                // in file 2
 		
 		List<String> files3 = fileFactory.listFiles(fileExtension);
 		
@@ -785,7 +942,7 @@
 		
 		//Make sure we move on to the next file
 		
-		add(3);                // in file 4
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 3);                // in file 4
 		
 		List<String> files5 = fileFactory.listFiles(fileExtension);
 		
@@ -805,8 +962,9 @@
 		
 		assertEquals(1, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(2, journal.getIDMapSize());		
+		assertEquals(2, journal.getIDMapSize());     
 		
+		Thread.sleep(1000);
 		//Now restart
 		
 		stopJournal();
@@ -818,7 +976,7 @@
 		
 		assertEquals(1, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(2, journal.getIDMapSize());		
+		assertEquals(2, journal.getIDMapSize());     
 	}
 	
 	public void testAddDeleteCommitTXIDMap1() throws Exception
@@ -852,7 +1010,7 @@
 		
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(9, journal.getFreeFilesCount());
-		assertEquals(0, journal.getIDMapSize());				
+		assertEquals(0, journal.getIDMapSize());           
 	}
 	
 	public void testAddCommitTXIDMap1() throws Exception
@@ -875,12 +1033,12 @@
 		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());				
+		assertEquals(1, journal.getIDMapSize());           
 	}
 	
 	public void testAddDeleteCommitTXIDMap2() throws Exception
@@ -914,10 +1072,10 @@
 		
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(9, journal.getFreeFilesCount());
-		assertEquals(0, journal.getIDMapSize());				
+		assertEquals(0, journal.getIDMapSize());           
 	}
 	
-				
+	
 	public void testAddDeleteRollbackTXIDMap1() throws Exception
 	{
 		setup(10, 10 * 1024, true);
@@ -949,7 +1107,7 @@
 		
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(9, journal.getFreeFilesCount());
-		assertEquals(0, journal.getIDMapSize());				
+		assertEquals(0, journal.getIDMapSize());           
 	}
 	
 	public void testAddRollbackTXIDMap1() throws Exception
@@ -972,12 +1130,12 @@
 		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());				
+		assertEquals(0, journal.getIDMapSize());           
 	}
 	
 	public void testAddDeleteRollbackTXIDMap2() throws Exception
@@ -1011,7 +1169,7 @@
 		
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(9, journal.getFreeFilesCount());
-		assertEquals(1, journal.getIDMapSize());				
+		assertEquals(1, journal.getIDMapSize());           
 	}
 	
 	public void testAddDeleteIDMap() throws Exception
@@ -1045,7 +1203,7 @@
 	
 	public void testCommitRecordsInFileReclaim() throws Exception
 	{
-		setup(2, 1054, true);
+		setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()), true);
 		createJournal();
 		startJournal();
 		load();
@@ -1057,7 +1215,7 @@
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(1, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-					
+		
 		addTx(1, 1);
 		
 		List<String> files2 = fileFactory.listFiles(fileExtension);
@@ -1067,7 +1225,7 @@
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(1, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-						
+		
 		//Make sure we move on to the next file
 		
 		commit(1);
@@ -1080,7 +1238,7 @@
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
-		add(2);
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 2);
 		
 		//Move on to another file
 		
@@ -1102,17 +1260,17 @@
 		
 		assertEquals(2, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(2, journal.getIDMapSize());		
+		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);
+		setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) + 512, true);
 		createJournal();
 		startJournal();
 		load();
@@ -1124,18 +1282,18 @@
 		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
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 2);               // in file 1
 		
-    	List<String> files2 = fileFactory.listFiles(fileExtension);
+		List<String> files2 = fileFactory.listFiles(fileExtension);
 		
 		assertEquals(2, files2.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 2, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
@@ -1143,9 +1301,13 @@
 		
 		List<String> files3 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files3.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_COMMIT_RECORD) +1, files3.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_COMMIT_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(2, journal.getIDMapSize());
 		
@@ -1153,15 +1315,21 @@
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files4.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_COMMIT_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD)+1, files4.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_COMMIT_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
 		//Move on to another file
 		
-		add(3);               // in file 2
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 3);               // in file 2
 		
 		List<String> files5 = fileFactory.listFiles(fileExtension);
 		
@@ -1170,7 +1338,7 @@
 		assertEquals(2, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(2, journal.getIDMapSize());
-				
+		
 		journal.checkAndReclaimFiles();
 		
 		List<String> files6 = fileFactory.listFiles(fileExtension);
@@ -1179,7 +1347,7 @@
 		
 		assertEquals(2, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
-		assertEquals(2, journal.getIDMapSize());	
+		assertEquals(2, journal.getIDMapSize());  
 		
 		//Restart
 		
@@ -1199,7 +1367,7 @@
 	
 	public void testRollbackRecordsInFileNoReclaim() throws Exception
 	{
-		setup(2, 1300, true);
+		setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) + 512, true);
 		createJournal();
 		startJournal();
 		load();
@@ -1211,14 +1379,14 @@
 		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
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD ,2);               // in file 1
 		
-    	List<String> files2 = fileFactory.listFiles(fileExtension);
+		List<String> files2 = fileFactory.listFiles(fileExtension);
 		
 		assertEquals(2, files2.size());
 		
@@ -1230,9 +1398,13 @@
 		
 		List<String> files3 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files3.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_ROLLBACK_RECORD) +1, files3.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_ROLLBACK_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
@@ -1240,24 +1412,38 @@
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files4.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_ROLLBACK_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD)+1, files4.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_ROLLBACK_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		//Move on to another file
 		
-		add(3);                // in file 2 (current file)
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD,3);                // in file 2 (current file)
 		
 		List<String> files5 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(3, files5.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_ROLLBACK_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD,
+				1, recordLength)+1, files5.size());
 		
-		assertEquals(2, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_ROLLBACK_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD,
+				1, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
-				
+		
 		journal.checkAndReclaimFiles();
 		
 		List<String> files6 = fileFactory.listFiles(fileExtension);
@@ -1268,7 +1454,7 @@
 		
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(1, journal.getFreeFilesCount());
-		assertEquals(1, journal.getIDMapSize());	
+		assertEquals(1, journal.getIDMapSize());  
 		
 		//Restart
 		
@@ -1288,7 +1474,7 @@
 	
 	public void testPrepareNoReclaim() throws Exception
 	{
-		setup(2, 1300, true);
+		setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) + 512, true);
 		createJournal();
 		startJournal();
 		load();
@@ -1300,18 +1486,18 @@
 		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
+		addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD,2);               // in file 1
 		
-    	List<String> files2 = fileFactory.listFiles(fileExtension);
+		List<String> files2 = fileFactory.listFiles(fileExtension);
 		
 		assertEquals(2, files2.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 2, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
@@ -1321,7 +1507,9 @@
 		
 		assertEquals(2, files3.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
@@ -1329,24 +1517,39 @@
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files4.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD) + 1, files4.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		//Move on to another file
 		
-		add(3);                // in file 2
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 3);                // in file 2
 		
 		List<String> files5 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(3, files5.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD,
+				1, recordLength) + 1, files5.size());
 		
-		assertEquals(2, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD,
+				1, recordLength), journal.getDataFilesCount());
+		
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
-				
+		
 		journal.checkAndReclaimFiles();
 		
 		List<String> files6 = fileFactory.listFiles(fileExtension);
@@ -1357,7 +1560,7 @@
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
-		add(4);		// in file 3
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 4);    // in file 3
 		
 		List<String> files7 = fileFactory.listFiles(fileExtension);
 		
@@ -1383,12 +1586,12 @@
 		createJournal();
 		startJournal();
 		loadAndCheck();
-	
+		
 	}
 	
 	public void testPrepareReclaim() throws Exception
 	{
-		setup(2, 1300, true);
+		setup(2, calculateRecordSize(JournalImpl.SIZE_HEADER, getAlignment()) + calculateRecordSize(recordLength, getAlignment()) + 512, true);
 		createJournal();
 		startJournal();
 		load();
@@ -1400,26 +1603,26 @@
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(1, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-					
+		
 		addTx(1, 1);          // in file 0
 		
-	   files1 = fileFactory.listFiles(fileExtension);
+		files1 = fileFactory.listFiles(fileExtension);
 		
 		assertEquals(2, files1.size());
 		
 		assertEquals(0, journal.getDataFilesCount());
 		assertEquals(1, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
-						
+		
 		//Make sure we move on to the next file
 		
-		add(2);               // in file 1
+		addWithSize(recordLength - JournalImpl.SIZE_ADD_RECORD, 2);               // in file 1
 		
-    	List<String> files2 = fileFactory.listFiles(fileExtension);
+		List<String> files2 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files2.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 2, recordLength) , journal.getDataFilesCount());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 2, recordLength), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
@@ -1437,18 +1640,24 @@
 		
 		List<String> files4 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(2, files4.size());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD) + 1 , files4.size());
 		
-		assertEquals(1, journal.getDataFilesCount());
+		assertEquals(calculateNumberOfFiles(fileSize, journal.getAlignment(), 
+				2, recordLength,
+				1, JournalImpl.SIZE_PREPARE_RECORD,
+				1, JournalImpl.SIZE_DELETE_RECORD), journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(0, journal.getIDMapSize());
 		
 		//Move on to another file
 		
-		add(3);                // in file 2
+		addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD,3);                // in file 2
 		
 		journal.checkAndReclaimFiles();
-				
+		
 		List<String> files5 = fileFactory.listFiles(fileExtension);
 		
 		assertEquals(3, files5.size());
@@ -1456,7 +1665,7 @@
 		assertEquals(2, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
-				
+		
 		journal.checkAndReclaimFiles();
 		
 		List<String> files6 = fileFactory.listFiles(fileExtension);
@@ -1467,7 +1676,7 @@
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(1, journal.getIDMapSize());
 		
-		add(4);		// in file 3
+		addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD,4);    // in file 3
 		
 		List<String> files7 = fileFactory.listFiles(fileExtension);
 		
@@ -1491,9 +1700,9 @@
 		
 		List<String> files9 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(4, files9.size());
+		assertEquals(journal.getAlignment()==1?4:5, files9.size());
 		
-		assertEquals(3, journal.getDataFilesCount());
+		assertEquals(journal.getAlignment()==1?3:4, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(2, journal.getIDMapSize());
 		
@@ -1501,19 +1710,19 @@
 		
 		List<String> files10 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(4, files10.size());
+		assertEquals(journal.getAlignment()==1?4:3, files10.size());
 		
-		assertEquals(3, journal.getDataFilesCount());
+		assertEquals(journal.getAlignment()==1?3:2, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(2, journal.getIDMapSize());
 		
-		add(5);       // in file 4
+		addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD,5);       // in file 4
 		
 		List<String> files11 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(5, files11.size());
+		assertEquals(journal.getAlignment()==1?5:3, files11.size());
 		
-		assertEquals(4, journal.getDataFilesCount());
+		assertEquals(journal.getAlignment()==1?4:2, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(3, journal.getIDMapSize());
 		
@@ -1541,16 +1750,18 @@
 		
 		List<String> files13 = fileFactory.listFiles(fileExtension);
 		
-		assertEquals(3, files13.size());
+		assertEquals(journal.getAlignment()==1?3:4, files13.size());
 		
-		assertEquals(2, journal.getDataFilesCount());
+		assertEquals(journal.getAlignment()==1?2:3, journal.getDataFilesCount());
 		assertEquals(0, journal.getFreeFilesCount());
 		assertEquals(2, journal.getIDMapSize());
 		
-		add(6);
+		addWithSize(1024 - JournalImpl.SIZE_ADD_RECORD,6);
 		
 		List<String> files14 = fileFactory.listFiles(fileExtension);
 		
+		log.info("Debug journal on testPrepareReclaim ->\n" + debugJournal());
+		
 		assertEquals(4, files14.size());
 		
 		assertEquals(3, journal.getDataFilesCount());
@@ -1572,7 +1783,7 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();	
+		loadAndCheck();   
 	}
 	
 	// Non transactional tests
@@ -1584,7 +1795,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1);	
+		add(1);  
 		stopJournal();
 		createJournal();
 		startJournal();
@@ -1597,7 +1808,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,2,3,4,5,6,7,8,9,10);		
+		add(1,2,3,4,5,6,7,8,9,10);    
 		stopJournal();
 		createJournal();
 		startJournal();
@@ -1610,7 +1821,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,3,5,7,10,13,56,100,102,200,201,202,203);		
+		add(1,3,5,7,10,13,56,100,102,200,201,202,203);     
 		stopJournal();
 		createJournal();
 		startJournal();
@@ -1623,7 +1834,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1);		
+		add(1);     
 		update(1);
 		stopJournal();
 		createJournal();
@@ -1637,7 +1848,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,2,3,4,5,6,7,8,9,10);		
+		add(1,2,3,4,5,6,7,8,9,10);    
 		update(1,2,4,7,9,10);
 		stopJournal();
 		createJournal();
@@ -1651,7 +1862,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,2,3,4,5,6,7,8,9,10);		
+		add(1,2,3,4,5,6,7,8,9,10);    
 		update(1,2,3,4,5,6,7,8,9,10);
 		stopJournal();
 		createJournal();
@@ -1665,8 +1876,8 @@
 		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);	
+		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();
@@ -1686,14 +1897,14 @@
 		startJournal();
 		loadAndCheck();
 	}
-		
+	
 	public void testSimpleAddUpdateDelete() throws Exception
 	{
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
 		load();
-		add(1);		
+		add(1);     
 		update(1);
 		delete(1);
 		stopJournal();
@@ -1708,7 +1919,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,2,3,4,5,6,7,8,9,10);		
+		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();
@@ -1723,7 +1934,7 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,2,3,4,5,6,7,8,9,10);		
+		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();
@@ -1738,9 +1949,9 @@
 		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);	
+		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();
@@ -1759,7 +1970,7 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testMultipleAddUpdateDeleteDifferentOrder() throws Exception
@@ -1774,9 +1985,9 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
-		
+	
 	public void testMultipleAddUpdateDeleteDifferentRecordLengths() throws Exception
 	{
 		setup(10, 2048, true);
@@ -1813,7 +2024,7 @@
 		createJournal();
 		startJournal();
 		loadAndCheck();
-		stopJournal();			
+		stopJournal();       
 	}
 	
 	
@@ -1877,17 +2088,17 @@
 	}
 	
 	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 realLength = calculateRecordSize(JournalImpl.SIZE_ADD_RECORD + this.recordLength, getAlignment());
 		
-		int fileSize = numRecords * realLength + 8; //8 for timestamp
-						
+		int fileSize = numRecords * realLength + calculateRecordSize(8, getAlignment()); //8 for timestamp
+		
 		setup(10, fileSize, true);
 		
 		createJournal();
@@ -1913,27 +2124,27 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	// Transactional tests
 	// ===================
-	
-	public void testSimpleTransaction() throws Exception
-	{
+		
+		public void testSimpleTransaction() throws Exception
+		{
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
 		load();
 		addTx(1, 1);
-		updateTx(1, 1);		
-		deleteTx(1, 1);	
+		updateTx(1, 1);      
+		deleteTx(1, 1);   
 		commit(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
-	}
+		loadAndCheck();      
+		}
 	
 	public void testTransactionDontDeleteAll() throws Exception
 	{
@@ -1942,13 +2153,13 @@
 		startJournal();
 		load();
 		addTx(1, 1, 2, 3);
-		updateTx(1, 1, 2);		
-		deleteTx(1, 1);	
+		updateTx(1, 1, 2);      
+		deleteTx(1, 1);   
 		commit(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testTransactionDeleteAll() throws Exception
@@ -1958,13 +2169,13 @@
 		startJournal();
 		load();
 		addTx(1, 1, 2, 3);
-		updateTx(1, 1, 2);		
+		updateTx(1, 1, 2);      
 		deleteTx(1, 1, 2, 3);
 		commit(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testTransactionUpdateFromBeforeTx() throws Exception
@@ -1980,7 +2191,7 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testTransactionDeleteFromBeforeTx() throws Exception
@@ -1996,7 +2207,7 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testTransactionChangesNotVisibleOutsideTX() throws Exception
@@ -2012,7 +2223,7 @@
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testMultipleTransactionsDifferentIDs() throws Exception
@@ -2050,14 +2261,14 @@
 		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);		
+		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);
@@ -2076,18 +2287,18 @@
 		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);		
+		
+		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();
@@ -2102,17 +2313,17 @@
 		createJournal();
 		startJournal();
 		load();
-		add(1,3,5,7,10,13,56,100,102,200,201,202,203);		
+		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);		
+		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();		
+		loadAndCheck();      
 	}
 	
 	public void testTransactionAddDeleteDifferentOrder() throws Exception
@@ -2120,14 +2331,14 @@
 		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);	
+		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();		
+		loadAndCheck();      
 	}
 	
 	public void testAddOutsideTXThenUpdateInsideTX() throws Exception
@@ -2135,7 +2346,7 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3);
 		updateTx(1, 1, 2, 3);
 		commit(1);
@@ -2150,7 +2361,7 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3);
 		deleteTx(1, 1, 2, 3);
 		commit(1);
@@ -2165,7 +2376,7 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3);
 		deleteTx(1, 1, 2, 3);
 		rollback(1);
@@ -2180,7 +2391,7 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3);
 		deleteTx(1, 1, 2, 3);
 		addTx(2, 4, 5, 6);
@@ -2197,9 +2408,9 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();			
-		addTx(1, 1, 2, 3);		
-		deleteTx(1, 1, 2, 3);		
+		load();        
+		addTx(1, 1, 2, 3);      
+		deleteTx(1, 1, 2, 3);      
 		commit(1);
 		stopJournal();
 		createJournal();
@@ -2212,8 +2423,8 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();			
-		addTx(1, 1, 2, 3);		
+		load();        
+		addTx(1, 1, 2, 3);      
 		try
 		{
 			update(1);
@@ -2235,8 +2446,8 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();			
-		addTx(1, 1, 2, 3);		
+		load();        
+		addTx(1, 1, 2, 3);      
 		try
 		{
 			delete(1);
@@ -2256,36 +2467,36 @@
 	
 	// XA tests
 	// ========
-	
-	public void testXASimpleNotPrepared() throws Exception
-	{
+		
+		public void testXASimpleNotPrepared() throws Exception
+		{
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
-		addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);					
+		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);		
+		deleteTx(1, 1, 2, 3, 4, 5);      
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
-	}
+		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);					
+		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);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		prepare(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXASimpleCommit() throws Exception
@@ -2293,16 +2504,16 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
-		addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);					
+		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);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		prepare(1);
 		commit(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXASimpleRollback() throws Exception
@@ -2310,16 +2521,16 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
-		addTx(1, 1, 2, 3, 4, 5, 6, 7, 8, 9);					
+		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);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		prepare(1);
 		rollback(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXAChangesNotVisibleNotPrepared() throws Exception
@@ -2327,15 +2538,15 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3, 4, 5, 6);
-		addTx(1, 7, 8, 9, 10);					
+		addTx(1, 7, 8, 9, 10);              
 		updateTx(1, 1, 2, 3, 7, 8, 9);
-		deleteTx(1, 1, 2, 3, 4, 5);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXAChangesNotVisiblePrepared() throws Exception
@@ -2343,16 +2554,16 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3, 4, 5, 6);
-		addTx(1, 7, 8, 9, 10);					
+		addTx(1, 7, 8, 9, 10);              
 		updateTx(1, 1, 2, 3, 7, 8, 9);
-		deleteTx(1, 1, 2, 3, 4, 5);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		prepare(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXAChangesNotVisibleRollback() throws Exception
@@ -2360,17 +2571,17 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3, 4, 5, 6);
-		addTx(1, 7, 8, 9, 10);					
+		addTx(1, 7, 8, 9, 10);              
 		updateTx(1, 1, 2, 3, 7, 8, 9);
-		deleteTx(1, 1, 2, 3, 4, 5);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		prepare(1);
 		rollback(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXAChangesisibleCommit() throws Exception
@@ -2378,17 +2589,17 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		load();     
 		add(1, 2, 3, 4, 5, 6);
-		addTx(1, 7, 8, 9, 10);					
+		addTx(1, 7, 8, 9, 10);              
 		updateTx(1, 1, 2, 3, 7, 8, 9);
-		deleteTx(1, 1, 2, 3, 4, 5);	
+		deleteTx(1, 1, 2, 3, 4, 5);   
 		prepare(1);
 		commit(1);
 		stopJournal();
 		createJournal();
 		startJournal();
-		loadAndCheck();		
+		loadAndCheck();      
 	}
 	
 	public void testXAMultiple() throws Exception
@@ -2396,7 +2607,7 @@
 		setup(10, 10 * 1024, true);
 		createJournal();
 		startJournal();
-		load();		
+		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);
@@ -2414,30 +2625,39 @@
 		rollback(2);
 		commit(3);
 	}
-
+	
 	public void testTransactionOnDifferentFiles() throws Exception
-   {
-      setup(2, 512 + 2*1024, true);
+	{
+		setup(2, 512 + 2*1024, true);
+		
+		createJournal();
+		startJournal();
+		load();
+		
+		addTx(1, 1, 2, 3, 4, 5, 6);
+		updateTx(1, 1, 3, 5);
+		commit(1);
+		deleteTx(2, 1, 2, 3, 4, 5, 6);
+		commit(2);
+		
+		
+		
+//		// Just to make sure the commit won't be released. The commit will be on the same file as addTx(3);
+addTx(3, 11);
+addTx(4, 31);
+commit(3);
 
-      createJournal();
-      startJournal();
-      load();
+log.info("Debug on Journal before stopJournal - \n" + debugJournal());
 
-      addTx(1, 1, 2, 3, 4, 5, 6);
-      updateTx(1, 1, 3, 5);
-      commit(1);
-      deleteTx(2, 1, 2, 3, 4, 5, 6);
-      commit(2);
-      
-      // Just to make sure the commit won't be released. The commit will be on the same file as addTx(3);
-      addTx(3, 11, 12);
-      
-      stopJournal();
-      createJournal();
-      startJournal();
-      loadAndCheck();
-      
-      
-   }
+stopJournal();
+createJournal();
+startJournal();
+loadAndCheck();
 
+
+	}
+	
+	protected abstract int getAlignment();
+	
+	
 }

Added: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealAIOJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealAIOJournalImplTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealAIOJournalImplTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,69 @@
+/*
+  * 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.tests.unit.core.journal.impl;
+
+import java.io.File;
+
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+import org.jboss.messaging.core.journal.impl.AIOSequentialFileFactory;
+import org.jboss.messaging.core.logging.Logger;
+
+
+/**
+ * 
+ * A RealJournalImplTest
+ * you need to define -Djava.library.path=${project-root}/native/src/.libs when calling the JVM
+ * If you are running this test in eclipse you should do:
+ *   I - Run->Open Run Dialog
+ *   II - Find the class on the list (you will find it if you already tried running this testcase before)  
+ *   III - Add -Djava.library.path=<your project place>/native/src/.libs
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class RealAIOJournalImplTest extends JournalImplTestUnit
+{
+   private static final Logger log = Logger.getLogger(RealAIOJournalImplTest.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 AIOSequentialFileFactory(journalDir);
+   }  
+
+   protected int getAlignment()
+   {
+      return 512;
+   }
+   
+}

Deleted: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealJournalImplTest.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealJournalImplTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -1,56 +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.tests.unit.core.journal.impl;
-
-import java.io.File;
-
-import org.jboss.messaging.core.journal.SequentialFileFactory;
-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);
-	}	
-	
-}

Added: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealNIOJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealNIOJournalImplTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/RealNIOJournalImplTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,65 @@
+/*
+  * 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.tests.unit.core.journal.impl;
+
+import java.io.File;
+
+import org.jboss.messaging.core.journal.SequentialFileFactory;
+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 RealNIOJournalImplTest extends JournalImplTestUnit
+{
+   private static final Logger log = Logger.getLogger(RealNIOJournalImplTest.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);
+   }
+   
+   protected int getAlignment()
+   {
+      return 1;
+   }
+   
+   
+}

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/SequentialFileFactoryTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/SequentialFileFactoryTestBase.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/SequentialFileFactoryTestBase.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -40,287 +40,296 @@
  */
 public abstract class SequentialFileFactoryTestBase extends UnitTestCase
 {
-	private static final Logger log = Logger.getLogger(SequentialFileFactoryTestBase.class);
-	
-	
-	protected void setUp() throws Exception
-	{
-		super.setUp();
-		
-		factory = createFactory();
-	}
-	
-	protected abstract SequentialFileFactory createFactory();
-	
-	private SequentialFileFactory factory;
-		
-	public void testCreateAndListFiles() throws Exception
-	{
-		List<String> expectedFiles = new ArrayList<String>();
-		
-		final int numFiles = 10;
-		
-		for (int i = 0; i < numFiles; i++)
-		{
-			String fileName = UUID.randomUUID().toString() + ".jbm";
-			
-			expectedFiles.add(fileName);
-			
-			SequentialFile sf = factory.createSequentialFile(fileName, false);
-			
-			sf.open();
-			
-			assertEquals(fileName, sf.getFileName());
-		}				
-		
-		//Create a couple with a different extension - they shouldn't be picked up
-		
-		SequentialFile sf1 = factory.createSequentialFile("different.file", false);
-		sf1.open();
-		
-		SequentialFile sf2 = factory.createSequentialFile("different.cheese", false);
-		sf2.open();
-						
-		List<String> fileNames = factory.listFiles("jbm");
-		
-		assertEquals(expectedFiles.size(), fileNames.size());
-		
-		for (String fileName: expectedFiles)
-		{
-			assertTrue(fileNames.contains(fileName));
-		}
-		
-		fileNames = factory.listFiles("file");
-		
-		assertEquals(1, fileNames.size());
-		
-		assertTrue(fileNames.contains("different.file"));	
-		
-		fileNames = factory.listFiles("cheese");
-		
-		assertEquals(1, fileNames.size());
-		
-		assertTrue(fileNames.contains("different.cheese"));	
-	}
-	
-	
-	public void testFill() throws Exception
-	{
-		SequentialFile sf = factory.createSequentialFile("fill.jbm", true);
-		
-		sf.open();
-		
-		checkFill(sf, 0, 100, (byte)'X');
-		
-		checkFill(sf, 13, 300, (byte)'Y');
-		
-		checkFill(sf, 0, 1, (byte)'Z');
-		
-		checkFill(sf, 100, 1, (byte)'A');
-		
-		checkFill(sf, 1000, 10000, (byte)'B');
-	}
-	
-	public void testDelete() throws Exception
-	{
-		SequentialFile sf = factory.createSequentialFile("delete-me.jbm", true);
-		
-		sf.open();
-		
-		SequentialFile sf2 = factory.createSequentialFile("delete-me2.jbm", true);
-		
-		sf2.open();
-		
-		List<String> fileNames = factory.listFiles("jbm");
-		
-		assertEquals(2, fileNames.size());
-		
-		assertTrue(fileNames.contains("delete-me.jbm"));
-		
-		assertTrue(fileNames.contains("delete-me2.jbm"));
-		
-		sf.delete();
-		
-		fileNames = factory.listFiles("jbm");
-		
-		assertEquals(1, fileNames.size());
-		
-		assertTrue(fileNames.contains("delete-me2.jbm"));
-		
-	}
-	
-	public void testWriteandRead() throws Exception
-	{
-		SequentialFile sf = factory.createSequentialFile("write.jbm", true);
-		
-		sf.open();
-		
-		String s1 = "aardvark";
-		byte[] bytes1 = s1.getBytes("UTF-8");
-		ByteBuffer bb1 = ByteBuffer.wrap(bytes1);
-		
-		String s2 = "hippopotamus";
-		byte[] bytes2 = s2.getBytes("UTF-8");
-		ByteBuffer bb2 = ByteBuffer.wrap(bytes2);
-		
-		String s3 = "echidna";
-		byte[] bytes3 = s3.getBytes("UTF-8");
-		ByteBuffer bb3 = ByteBuffer.wrap(bytes3);
-		
-		int bytesWritten = sf.write(bb1, true);
-		
-		assertEquals(bytes1.length, bytesWritten);
-		
-		bytesWritten = sf.write(bb2, true);
-		
-		assertEquals(bytes2.length, bytesWritten);
-		
-		bytesWritten = sf.write(bb3, true);
-		
-		assertEquals(bytes3.length, bytesWritten);
-		
-		sf.position(0);
-		
-		byte[] rbytes1 = new byte[bytes1.length];
-		
-		byte[] rbytes2 = new byte[bytes2.length];
-		
-		byte[] rbytes3 = new byte[bytes3.length];
-		
-		ByteBuffer rb1 = ByteBuffer.wrap(rbytes1);
-		ByteBuffer rb2 = ByteBuffer.wrap(rbytes2);
-		ByteBuffer rb3 = ByteBuffer.wrap(rbytes3);
+   private static final Logger log = Logger.getLogger(SequentialFileFactoryTestBase.class);
+   
+   
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      factory = createFactory();
+   }
+   
+   protected abstract SequentialFileFactory createFactory();
+   
+   protected SequentialFileFactory factory;
+      
+   public void testCreateAndListFiles() throws Exception
+   {
+      List<String> expectedFiles = new ArrayList<String>();
+      
+      final int numFiles = 10;
+      
+      for (int i = 0; i < numFiles; i++)
+      {
+         String fileName = UUID.randomUUID().toString() + ".jbm";
+         
+         expectedFiles.add(fileName);
+         
+         SequentialFile sf = factory.createSequentialFile(fileName, false);
+         
+         sf.open();
+         
+         assertEquals(fileName, sf.getFileName());
+      }           
+      
+      //Create a couple with a different extension - they shouldn't be picked up
+      
+      SequentialFile sf1 = factory.createSequentialFile("different.file", false);
+      sf1.open();
+      
+      SequentialFile sf2 = factory.createSequentialFile("different.cheese", false);
+      sf2.open();
+                  
+      List<String> fileNames = factory.listFiles("jbm");
+      
+      assertEquals(expectedFiles.size(), fileNames.size());
+      
+      for (String fileName: expectedFiles)
+      {
+         assertTrue(fileNames.contains(fileName));
+      }
+      
+      fileNames = factory.listFiles("file");
+      
+      assertEquals(1, fileNames.size());
+      
+      assertTrue(fileNames.contains("different.file"));  
+      
+      fileNames = factory.listFiles("cheese");
+      
+      assertEquals(1, fileNames.size());
+      
+      assertTrue(fileNames.contains("different.cheese"));   
+   }
+   
+   
+   public void testFill() throws Exception
+   {
+      SequentialFile sf = factory.createSequentialFile("fill.jbm", true);
+      
+      sf.open();
+      
+      checkFill(sf, 0, 2048, (byte)'X');
+      
+      checkFill(sf, 512, 512, (byte)'Y');
+      
+      checkFill(sf, 0, 1, (byte)'Z');
+      
+      checkFill(sf, 512, 1, (byte)'A');
+      
+      checkFill(sf, 1024, 512*4, (byte)'B');
+   }
+   
+   public void testDelete() throws Exception
+   {
+      SequentialFile sf = factory.createSequentialFile("delete-me.jbm", true);
+      
+      sf.open();
+      
+      SequentialFile sf2 = factory.createSequentialFile("delete-me2.jbm", true);
+      
+      sf2.open();
+      
+      List<String> fileNames = factory.listFiles("jbm");
+      
+      assertEquals(2, fileNames.size());
+      
+      assertTrue(fileNames.contains("delete-me.jbm"));
+      
+      assertTrue(fileNames.contains("delete-me2.jbm"));
+      
+      sf.delete();
+      
+      fileNames = factory.listFiles("jbm");
+      
+      assertEquals(1, fileNames.size());
+      
+      assertTrue(fileNames.contains("delete-me2.jbm"));
+      
+   }
+   
+   public void testWriteandRead() throws Exception
+   {
+      SequentialFile sf = factory.createSequentialFile("write.jbm", true);
+      
+      sf.open();
+      
+      String s1 = "aardvark";
+      byte[] bytes1 = s1.getBytes("UTF-8");
+      ByteBuffer bb1 = sf.wrapBuffer(bytes1);
+      
+      String s2 = "hippopotamus";
+      byte[] bytes2 = s2.getBytes("UTF-8");
+      ByteBuffer bb2 = sf.wrapBuffer(bytes2);
+      
+      String s3 = "echidna";
+      byte[] bytes3 = s3.getBytes("UTF-8");
+      ByteBuffer bb3 = sf.wrapBuffer(bytes3);
+      
+      int bytesWritten = sf.write(bb1, true);
+      
+      assertEquals(calculateRecordSize(bytes1.length, sf.getAlignment()), bytesWritten);
+      
+      bytesWritten = sf.write(bb2, true);
+      
+      assertEquals(calculateRecordSize(bytes2.length, sf.getAlignment()), bytesWritten);
+      
+      bytesWritten = sf.write(bb3, true);
+      
+      assertEquals(calculateRecordSize(bytes3.length, sf.getAlignment()), bytesWritten);
+      
+      sf.position(0);
+      
+      ByteBuffer rb1 = sf.newBuffer(bytes1.length);
+      ByteBuffer rb2 = sf.newBuffer(bytes2.length);
+      ByteBuffer rb3 = sf.newBuffer(bytes3.length);
 
-		int bytesRead = sf.read(rb1);
-		assertEquals(rbytes1.length, bytesRead);		
-		assertByteArraysEquivalent(bytes1, rbytes1);
-		
-		bytesRead = sf.read(rb2);
-		assertEquals(rbytes2.length, bytesRead);		
-		assertByteArraysEquivalent(bytes2, rbytes2);
-		
-		bytesRead = sf.read(rb3);
-		assertEquals(rbytes3.length, bytesRead);		
-		assertByteArraysEquivalent(bytes3, rbytes3);				
-	}
-	
-	public void testPosition() throws Exception
-	{
-		SequentialFile sf = factory.createSequentialFile("position.jbm", true);
-		
-		sf.open();
-		
-		String s1 = "orange";
-		byte[] bytes1 = s1.getBytes("UTF-8");
-		ByteBuffer bb1 = ByteBuffer.wrap(bytes1);
-		
-		String s2 = "grapefruit";
-		byte[] bytes2 = s2.getBytes("UTF-8");
-		ByteBuffer bb2 = ByteBuffer.wrap(bytes2);
-		
-		String s3 = "lemon";
-		byte[] bytes3 = s3.getBytes("UTF-8");
-		ByteBuffer bb3 = ByteBuffer.wrap(bytes3);
-		
-		int bytesWritten = sf.write(bb1, true);
-		
-		assertEquals(bytes1.length, bytesWritten);
-		
-		bytesWritten = sf.write(bb2, true);
-		
-		assertEquals(bytes2.length, bytesWritten);
-		
-		bytesWritten = sf.write(bb3, true);
-		
-		assertEquals(bytes3.length, bytesWritten);
-		
-		byte[] rbytes1 = new byte[bytes1.length];
-		
-		byte[] rbytes2 = new byte[bytes2.length];
-		
-		byte[] rbytes3 = new byte[bytes3.length];
-		
-		ByteBuffer rb1 = ByteBuffer.wrap(rbytes1);
-		ByteBuffer rb2 = ByteBuffer.wrap(rbytes2);
-		ByteBuffer rb3 = ByteBuffer.wrap(rbytes3);
-		
-		sf.position(bytes1.length + bytes2.length);
-		
-		int bytesRead = sf.read(rb3);
-		assertEquals(rbytes3.length, bytesRead);		
-		assertByteArraysEquivalent(bytes3, rbytes3);		
-		
-		sf.position(bytes1.length);
-		
-		bytesRead = sf.read(rb2);
-		assertEquals(rbytes2.length, bytesRead);		
-		assertByteArraysEquivalent(bytes2, rbytes2);
-		
-		sf.position(0);
-		
-		bytesRead = sf.read(rb1);
-		assertEquals(rbytes1.length, bytesRead);		
-		assertByteArraysEquivalent(bytes1, rbytes1);		
-	}
-	
-	public void testOpenClose() throws Exception
-	{
-		SequentialFile sf = factory.createSequentialFile("openclose.jbm", true);
-		
-		sf.open();
-		
-		String s1 = "cheesecake";
-		byte[] bytes1 = s1.getBytes("UTF-8");
-		ByteBuffer bb1 = ByteBuffer.wrap(bytes1);
-		
-		int bytesWritten = sf.write(bb1, true);
-		
-		assertEquals(bytes1.length, bytesWritten);
-		
-		sf.close();
-		
-		try
-		{
-			sf.write(bb1, true);
-			
-			fail("Should throw exception");
-		}
-		catch (Exception e)
-		{
-			//OK
-		}
-		
-		sf.open();
-		
-		sf.write(bb1, true);
-	}
-	
-	// Private ---------------------------------
-	
-	private void checkFill(SequentialFile file, int pos, int size, byte fillChar) throws Exception
-	{
-		file.fill(pos, size, fillChar);
-		
-		file.close();
-		
-		file.open();
-		
-		file.position(pos);
-		
-		byte[] bytes = new byte[size];
-		
-		ByteBuffer bb = ByteBuffer.wrap(bytes);
-		
-		int bytesRead = file.read(bb);
-		
-		assertEquals(size, bytesRead);
-		
-		for (int i = 0; i < size; i++)
-		{
-			//log.info(" i is " + i);
-			assertEquals(fillChar, bytes[i]);
-		}
-				
-	}
-	
+      int bytesRead = sf.read(rb1);
+      assertEquals(calculateRecordSize(bytes1.length, sf.getAlignment()), bytesRead);     
+
+      for (int i=0; i<bytes1.length; i++)
+      {
+      	assertEquals(bytes1[i], rb1.get(i));
+      }
+      
+      bytesRead = sf.read(rb2);
+      assertEquals(calculateRecordSize(bytes2.length, sf.getAlignment()), bytesRead);     
+      for (int i=0; i<bytes2.length; i++)
+      {
+      	assertEquals(bytes2[i], rb2.get(i));
+      }
+      
+      
+      bytesRead = sf.read(rb3);
+      assertEquals(calculateRecordSize(bytes3.length, sf.getAlignment()), bytesRead);     
+      for (int i=0; i<bytes3.length; i++)
+      {
+      	assertEquals(bytes3[i], rb3.get(i));
+      }
+      
+   }
+   
+   public void testPosition() throws Exception
+   {
+      SequentialFile sf = factory.createSequentialFile("position.jbm", true);
+      
+      sf.open();
+      
+      String s1 = "orange";
+      byte[] bytes1 = s1.getBytes("UTF-8");
+      ByteBuffer bb1 = sf.wrapBuffer(bytes1); 
+      
+      String s2 = "grapefruit";
+      byte[] bytes2 = s2.getBytes("UTF-8");
+      ByteBuffer bb2 = sf.wrapBuffer(bytes2);
+      
+      String s3 = "lemon";
+      byte[] bytes3 = s3.getBytes("UTF-8");
+      ByteBuffer bb3 = sf.wrapBuffer(bytes3);
+      
+      int bytesWritten = sf.write(bb1, true);
+      
+      assertEquals(bb1.limit(), bytesWritten);
+      
+      bytesWritten = sf.write(bb2, true);
+      
+      assertEquals(bb2.limit(), bytesWritten);
+      
+      bytesWritten = sf.write(bb3, true);
+      
+      assertEquals(bb3.limit(), bytesWritten);
+      
+      byte[] rbytes1 = new byte[bytes1.length];
+      
+      byte[] rbytes2 = new byte[bytes2.length];
+      
+      byte[] rbytes3 = new byte[bytes3.length];
+      
+      ByteBuffer rb1 = sf.newBuffer(rbytes1.length);
+      ByteBuffer rb2 = sf.newBuffer(rbytes2.length);
+      ByteBuffer rb3 = sf.newBuffer(rbytes3.length);
+      
+      sf.position(bb1.limit() + bb2.limit());
+      
+      int bytesRead = sf.read(rb3);
+      assertEquals(rb3.limit(), bytesRead);
+      rb3.rewind();
+      rb3.get(rbytes3);
+      assertByteArraysEquivalent(bytes3, rbytes3);    
+      
+      sf.position(rb1.limit());
+      
+      bytesRead = sf.read(rb2);
+      assertEquals(rb2.limit(), bytesRead);
+      rb2.get(rbytes2);
+      assertByteArraysEquivalent(bytes2, rbytes2);
+      
+      sf.position(0);
+      
+      bytesRead = sf.read(rb1);
+      assertEquals(rb1.limit(), bytesRead);
+      rb1.get(rbytes1);
+      
+      assertByteArraysEquivalent(bytes1, rbytes1);    
+   }
+    
+   public void testOpenClose() throws Exception
+   {
+      SequentialFile sf = factory.createSequentialFile("openclose.jbm", true);
+      
+      sf.open();
+      
+      String s1 = "cheesecake";
+      byte[] bytes1 = s1.getBytes("UTF-8");
+      ByteBuffer bb1 = sf.wrapBuffer(bytes1);
+      
+      int bytesWritten = sf.write(bb1, true);
+      
+      assertEquals(bb1.limit(), bytesWritten);
+      
+      sf.close();
+      
+      try
+      {
+         sf.write(bb1, true);
+         
+         fail("Should throw exception");
+      }
+      catch (Exception e)
+      {
+         //OK
+      }
+      
+      sf.open();
+      
+      sf.write(bb1, true);
+   }
+   
+   // Private ---------------------------------
+   
+   protected void checkFill(SequentialFile file, int pos, int size, byte fillChar) throws Exception
+   {
+      file.fill(pos, size, fillChar);
+      
+      file.close();
+      
+      file.open();
+      
+      file.position(pos);
+      
+      ByteBuffer bb = file.newBuffer(size);
+      
+      int bytesRead = file.read(bb);
+      
+      assertEquals(calculateRecordSize(size, file.getAlignment()), bytesRead);
+      
+      for (int i = 0; i < size; i++)
+      {
+         //log.info(" i is " + i);
+         assertEquals(fillChar, bb.get(i));
+      }
+            
+   }
+   
 }

Deleted: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFile.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFile.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFile.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -1,6 +0,0 @@
-package org.jboss.messaging.tests.unit.core.journal.impl.fakes;
-
-public class FakeSequentialFile
-{
-
-}

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFileFactory.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFileFactory.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/fakes/FakeSequentialFileFactory.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -27,6 +27,7 @@
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.jboss.messaging.core.journal.IOCallback;
 import org.jboss.messaging.core.journal.SequentialFile;
 import org.jboss.messaging.core.journal.SequentialFileFactory;
 import org.jboss.messaging.core.logging.Logger;
@@ -40,212 +41,250 @@
  */
 public class FakeSequentialFileFactory implements SequentialFileFactory
 {
-	private static final Logger log = Logger.getLogger(FakeSequentialFileFactory.class);
-		
-	private Map<String, FakeSequentialFile> fileMap = new ConcurrentHashMap<String, FakeSequentialFile>();
-	
-	public SequentialFile createSequentialFile(final String fileName, final boolean sync) throws Exception
-	{
-		FakeSequentialFile sf = fileMap.get(fileName);
-		
-		if (sf == null)
-		{						
-		   sf = new FakeSequentialFile(fileName, sync);
-		   
-		   fileMap.put(fileName, sf);
-		}
-		else
-		{		
-			sf.data.position(0);
-			
-			//log.info("positioning data to 0");
-		}
-						
-		return sf;
-	}
-	
-	public List<String> listFiles(final String extension)
-	{
-		List<String> files = new ArrayList<String>();
-		
-		for (String s: fileMap.keySet())
-		{
-			if (s.endsWith("." + extension))
-			{
-				files.add(s);
-			}
-		}
-		
-		return files;
-	}
-	
-	public Map<String, FakeSequentialFile> getFileMap()
-	{
-		return fileMap;
-	}
-	
-	public void clear()
-	{
-		fileMap.clear();
-	}
-	
-	public class FakeSequentialFile implements SequentialFile
-	{
-		private volatile boolean open;
-		
-		private final String fileName;
-		
-		private final boolean sync;
-		
-		private volatile ByteBuffer data;
-		
-		public ByteBuffer getData()
-		{
-			return data;
-		}
-		
-		public boolean isSync()
-		{
-			return sync;
-		}
-		
-		public boolean isOpen()
-		{
-			//log.info("is open" + System.identityHashCode(this) +" open is now " + open);
-			return open;
-		}
-		
-		public FakeSequentialFile(final String fileName, final boolean sync)
-		{
-			this.fileName = fileName;
-			
-			this.sync = sync;		
-		}
+   private static final Logger log = Logger.getLogger(FakeSequentialFileFactory.class);
+      
+   private Map<String, FakeSequentialFile> fileMap = new ConcurrentHashMap<String, FakeSequentialFile>();
+   
+   public SequentialFile createSequentialFile(final String fileName, final boolean sync) throws Exception
+   {
+      FakeSequentialFile sf = fileMap.get(fileName);
+      
+      if (sf == null)
+      {                 
+         sf = new FakeSequentialFile(fileName, sync);
+         
+         fileMap.put(fileName, sf);
+      }
+      else
+      {     
+         sf.data.position(0);
+         
+         //log.info("positioning data to 0");
+      }
+                  
+      return sf;
+   }
+   
+   public List<String> listFiles(final String extension)
+   {
+      List<String> files = new ArrayList<String>();
+      
+      for (String s: fileMap.keySet())
+      {
+         if (s.endsWith("." + extension))
+         {
+            files.add(s);
+         }
+      }
+      
+      return files;
+   }
+   
+   public Map<String, FakeSequentialFile> getFileMap()
+   {
+      return fileMap;
+   }
+   
+   public void clear()
+   {
+      fileMap.clear();
+   }
+   
+   public class FakeSequentialFile implements SequentialFile
+   {
+      private volatile boolean open;
+      
+      private final String fileName;
+      
+      private final boolean sync;
+      
+      private volatile ByteBuffer data;
+      
+      public ByteBuffer getData()
+      {
+         return data;
+      }
+      
+      public boolean isSync()
+      {
+         return sync;
+      }
+      
+      public boolean isOpen()
+      {
+         //log.info("is open" + System.identityHashCode(this) +" open is now " + open);
+         return open;
+      }
+      
+      public FakeSequentialFile(final String fileName, final boolean sync)
+      {
+         this.fileName = fileName;
+         
+         this.sync = sync;    
+      }
 
-		public void close() throws Exception
-		{
-			open = false;
-			
-			if (data != null)
-			{
-				data.position(0);
-			}
-		}
+      public void close() throws Exception
+      {
+         open = false;
+         
+         if (data != null)
+         {
+            data.position(0);
+         }
+      }
 
-		public void delete() throws Exception
-		{
-			if (!open)
-			{
-				throw new IllegalStateException("Is closed");
-			}
-			close();
-			
-			fileMap.remove(fileName);
-		}
+      public void delete() throws Exception
+      {
+         if (!open)
+         {
+            throw new IllegalStateException("Is closed");
+         }
+         close();
+         
+         fileMap.remove(fileName);
+      }
 
-		public String getFileName()
-		{
-			if (!open)
-			{
-				throw new IllegalStateException("Is closed");
-			}
-			return fileName;
-		}
-		
-		public void open() throws Exception
-		{
-			open = true;
-		}
+      public String getFileName()
+      {
+         return fileName;
+      }
+      
+      public void open() throws Exception
+      {
+         open = true;
+      }
 
-		public void fill(int pos, int size, byte fillCharacter) throws Exception
-		{		
-			if (!open)
-			{
-				throw new IllegalStateException("Is closed");
-			}
-			
-			checkAndResize(pos + size);
-			
-			//log.info("size is " + size + " pos is " + pos);
-			
-			for (int i = pos; i < size + pos; i++)
-			{
-				data.array()[i] = fillCharacter;
-				
-				//log.info("Filling " + pos + " with char " + fillCharacter);
-			}						
-		}
-		
-		public int read(ByteBuffer bytes) throws Exception
-		{
-			if (!open)
-			{
-				throw new IllegalStateException("Is closed");
-			}
-			
-			//log.info("read called " + bytes.array().length);
-			
-			byte[] bytesRead = new byte[bytes.array().length];
-			
-			//log.info("reading, data pos is " + data.position() + " data size is " + data.array().length);
-			
-			data.get(bytesRead);
-			
-			bytes.put(bytesRead);
-			
-			return bytesRead.length;
-		}
+      public void fill(int pos, int size, byte fillCharacter) throws Exception
+      {     
+         if (!open)
+         {
+            throw new IllegalStateException("Is closed");
+         }
+         
+         checkAndResize(pos + size);
+         
+         //log.info("size is " + size + " pos is " + pos);
+         
+         for (int i = pos; i < size + pos; i++)
+         {
+            data.array()[i] = fillCharacter;
+            
+            //log.info("Filling " + pos + " with char " + fillCharacter);
+         }                 
+      }
+      
+      public int read(ByteBuffer bytes) throws Exception
+      {
+         return read(bytes, null);
+      }
+      
+      public int read(ByteBuffer bytes, IOCallback callback) throws Exception
+      {
+         if (!open)
+         {
+            throw new IllegalStateException("Is closed");
+         }
+         
+         //log.info("read called " + bytes.array().length);
+         
+         byte[] bytesRead = new byte[bytes.array().length];
+         
+         //log.info("reading, data pos is " + data.position() + " data size is " + data.array().length);
+         
+         data.get(bytesRead);
+         
+         bytes.put(bytesRead);
+         
+         bytes.rewind();
+         
+         if (callback != null) callback.done();
+         
+         return bytesRead.length;
+      }
 
-		public void position(int pos) throws Exception
-		{
-			if (!open)
-			{
-				throw new IllegalStateException("Is closed");
-			}
-			
-			//log.info("reset called");
-			
-			data.position(pos);
-		}
+      public void position(int pos) throws Exception
+      {
+         if (!open)
+         {
+            throw new IllegalStateException("Is closed");
+         }
+         
+         //log.info("reset called");
+         
+         data.position(pos);
+      }
 
-		public int write(ByteBuffer bytes, boolean sync) throws Exception
-		{
-			if (!open)
-			{
-				throw new IllegalStateException("Is closed");
-			}
-			
-			int position = data == null ? 0 : data.position();
-			
-			checkAndResize(bytes.capacity() + position);
-			
-			//log.info("write called, position is " + data.position() + " bytes is " + bytes.array().length);
-			
-			data.put(bytes);
-			
-			return bytes.array().length;
-		}
-		
-		private void checkAndResize(int size)
-		{
-			int oldpos = data == null ? 0 : data.position();
-			
-			if (data == null || data.array().length < size)
-			{
-				byte[] newBytes = new byte[size];
-				
-				if (data != null)
-				{
-					System.arraycopy(data.array(), 0, newBytes, 0, data.array().length);
-				}
-				
-				data = ByteBuffer.wrap(newBytes);
-				
-				data.position(oldpos);
-			}
-		}
+      public int write(ByteBuffer bytes, boolean sync, IOCallback callback) throws Exception
+      {
+         if (!open)
+         {
+            throw new IllegalStateException("Is closed");
+         }
+         
+         int position = data == null ? 0 : data.position();
+         
+         checkAndResize(bytes.capacity() + position);
+         
+         //log.info("write called, position is " + data.position() + " bytes is " + bytes.array().length);
+         
+         data.put(bytes);
+         
+         if (callback!=null) callback.done();
+         
+         return bytes.array().length;
+         
+      }
+      
+      public int write(ByteBuffer bytes, boolean sync) throws Exception
+      {
+         return write(bytes, sync, null);
+      }
+      
+      private void checkAndResize(int size)
+      {
+         int oldpos = data == null ? 0 : data.position();
+         
+         if (data == null || data.array().length < size)
+         {
+            byte[] newBytes = new byte[size];
+            
+            if (data != null)
+            {
+               System.arraycopy(data.array(), 0, newBytes, 0, data.array().length);
+            }
+            
+            data = ByteBuffer.wrap(newBytes);
+            
+            data.position(oldpos);
+         }
+      }
 
+      public ByteBuffer newBuffer(int size)
+      {
+         return ByteBuffer.allocate(size);
+      }
 
-	}
+      public ByteBuffer wrapBuffer(byte[] bytes)
+      {
+         return ByteBuffer.wrap(bytes);
+      }
 
+      public int getAlignment() throws Exception
+      {
+         return 1;
+      }
+
+      public int calculateBlockStart(int position) throws Exception
+      {
+         return position;
+      }
+      
+      public String toString()
+      {
+         return "FakeSequentialFile:" + this.fileName;
+      }
+
+
+   }
+
 }

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/JournalImplTestUnit.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/JournalImplTestUnit.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/JournalImplTestUnit.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -21,7 +21,11 @@
   */
 package org.jboss.messaging.tests.unit.core.journal.impl.timing;
 
+import java.util.ArrayList;
+
 import org.jboss.messaging.tests.unit.core.journal.impl.JournalImplTestBase;
+import org.jboss.messaging.core.journal.PreparedTransactionInfo;
+import org.jboss.messaging.core.journal.RecordInfo;
 import org.jboss.messaging.core.logging.Logger;
 
 /**
@@ -33,138 +37,143 @@
  */
 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();
-	}
-	
+   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(2, 10 * 1024 * 1024, false);
+      createJournal();
+      startJournal();
+      load();
+      
+      journal.startReclaimer();
+      
+      long start = System.currentTimeMillis();
+      
+                  
+      byte[] record = generateRecord(recordLength);
+
+      for (int count = 0; count < 100000; count++)
+      {
+         journal.appendAddRecord(count, record);
+         
+         if (count >= 5000)
+         {
+            journal.appendDeleteRecord(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");
+      
+      log.info("Reclaim status = " + debugJournal());
+               
+      stopJournal();
+      createJournal();
+      startJournal();
+      journal.load(new ArrayList<RecordInfo>(), new ArrayList<PreparedTransactionInfo>());
+      
+      assertEquals(5000, journal.getIDMapSize());
+      
+      stopJournal();
+   }
+   
 }
 
 

Added: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplAIOTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplAIOTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplAIOTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -0,0 +1,210 @@
+/*
+  * 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.tests.unit.core.journal.impl.timing;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.jboss.messaging.core.asyncio.AIOCallback;
+import org.jboss.messaging.core.journal.IOCallback;
+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.AIOSequentialFileFactory;
+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 RealJournalImplAIOTest extends JournalImplTestUnit
+{
+   private static final Logger log = Logger.getLogger(RealJournalImplAIOTest.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
+   {
+      for (int i=0;i<20;i++)
+      {
+         this.setUp();
+         System.gc(); Thread.sleep(500);
+         internaltestSpeedNonTransactional();
+         this.tearDown();
+      }
+   }
+   
+   public void internaltestSpeedNonTransactional() throws Exception
+   {
+      
+      final long numMessages = 100000;
+      
+      int numFiles =  (int)(((numMessages * 1024 + 512) / (10 * 1024 * 1024)) * 1.3);
+      
+      if (numFiles<2) numFiles = 2;
+      
+      log.info("num Files=" + numFiles);
+
+      Journal journal =
+         new JournalImpl(10 * 1024 * 1024,  numFiles, true, new AIOSequentialFileFactory(journalDir),
+               5000, "jbm-data", "jbm");
+      
+      journal.start();
+      
+      journal.load(new ArrayList<RecordInfo>(), null);
+      
+
+      final CountDownLatch latch = new CountDownLatch((int)numMessages);
+      
+      
+      class LocalCallback implements IOCallback
+      {
+
+         int i=0;
+         String message = null;
+         boolean done = false;
+         CountDownLatch latch;
+         
+         public LocalCallback(int i, CountDownLatch latch)
+         {
+            this.i = i;
+            this.latch = latch;
+         }
+         public void done()
+         {
+            synchronized (this)
+            {
+               if (done)
+               {
+                  message = "done received in duplicate";
+               }
+               done = true;
+               this.latch.countDown();
+            }
+         }
+
+         public void onError(int errorCode, String errorMessage)
+         {
+            synchronized (this)
+            {
+               System.out.println("********************** Error = " + (i++));
+               message = errorMessage;
+               latch.countDown();
+            }
+         }
+         
+      }
+      
+      
+      log.info("Adding data");
+      byte[] data = new byte[700];
+      
+      long start = System.currentTimeMillis();
+      
+      LocalCallback callback = new LocalCallback(1, latch);
+      for (int i = 0; i < numMessages; i++)
+      {
+         journal.appendAddRecord(i, data, callback);
+      }
+      
+      latch.await(10, TimeUnit.SECONDS);
+      
+      // Validates if the test has completed 
+      assertEquals(0, latch.getCount());
+      
+      long end = System.currentTimeMillis();
+      
+      double rate = 1000 * (double)numMessages / (end - start);
+      
+      boolean failed = false;
+      
+      // If this fails it is probably because JournalImpl it is closing the files without waiting all the completes to arrive first
+      assertFalse(failed);
+      
+      
+      log.info("Rate " + rate + " records/sec");
+
+      journal.stop();
+      
+      journal =
+         new JournalImpl(10 * 1024 * 1024,  numFiles, true, new AIOSequentialFileFactory(journalDir),
+               5000, "jbm-data", "jbm");
+      
+      journal.start();
+      journal.load(new ArrayList<RecordInfo>(), null);
+      journal.stop();
+      
+   }
+   
+   public void testSpeedTransactional() throws Exception
+   {
+      Journal journal =
+         new JournalImpl(10 * 1024 * 1024, 10, true, new AIOSequentialFileFactory(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");
+
+   }
+}
+

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplTest.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/core/journal/impl/timing/RealJournalImplTest.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -27,6 +27,7 @@
 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.AIOSequentialFileFactory;
 import org.jboss.messaging.core.journal.impl.JournalImpl;
 import org.jboss.messaging.core.journal.impl.NIOSequentialFileFactory;
 import org.jboss.messaging.core.logging.Logger;
@@ -57,6 +58,7 @@
 		return new NIOSequentialFileFactory(journalDir);
 	}
 	
+	
 	public void testSpeedNonTransactional() throws Exception
 	{
 		Journal journal =
@@ -83,6 +85,16 @@
 		double rate = 1000 * (double)numMessages / (end - start);
 		
 		log.info("Rate " + rate + " records/sec");
+		
+      journal.stop();
+      
+      journal =
+         new JournalImpl(10 * 1024 * 1024,  10, true, new NIOSequentialFileFactory(journalDir),
+               5000, "jbm-data", "jbm");
+      
+      journal.start();
+      journal.load(new ArrayList<RecordInfo>(), null);
+		
 
 	}
 	

Modified: trunk/tests/src/org/jboss/messaging/tests/util/UnitTestCase.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/util/UnitTestCase.java	2008-04-30 22:35:42 UTC (rev 4142)
+++ trunk/tests/src/org/jboss/messaging/tests/util/UnitTestCase.java	2008-05-05 21:55:56 UTC (rev 4143)
@@ -265,6 +265,11 @@
       }
    }
 
+	protected int calculateRecordSize(int size, int alignment)
+   {
+      return ((size / alignment) + (size % alignment != 0 ? 1 : 0)) * alignment;
+   }
+
    
 
 }




More information about the jboss-cvs-commits mailing list