[hornetq-commits] JBoss hornetq SVN: r8116 - in trunk: src/main/org/hornetq/core/client/impl and 26 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Thu Oct 15 12:41:43 EDT 2009


Author: clebert.suconic at jboss.com
Date: 2009-10-15 12:41:41 -0400 (Thu, 15 Oct 2009)
New Revision: 8116

Added:
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/CreateReplicationSessionMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddTXMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationCommitMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteTXMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageBeingMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageWriteMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargemessageEndMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageEventMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageWriteMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPrepareMessage.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationResponseMessage.java
   trunk/src/main/org/hornetq/core/replication/
   trunk/src/main/org/hornetq/core/replication/ReplicationContext.java
   trunk/src/main/org/hornetq/core/replication/ReplicationEndpoint.java
   trunk/src/main/org/hornetq/core/replication/ReplicationManager.java
   trunk/src/main/org/hornetq/core/replication/impl/
   trunk/src/main/org/hornetq/core/replication/impl/ReplicatedJournal.java
   trunk/src/main/org/hornetq/core/replication/impl/ReplicationContextImpl.java
   trunk/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java
   trunk/src/main/org/hornetq/core/replication/impl/ReplicationManagerImpl.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/LargeMessageFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyReplicatedFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/PagingFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedAsynchronousFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedLargeMessageFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedNettyAsynchronousFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedPagingFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/replication/
   trunk/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java
Modified:
   trunk/src/main/org/hornetq/core/client/impl/FailoverManager.java
   trunk/src/main/org/hornetq/core/journal/Journal.java
   trunk/src/main/org/hornetq/core/journal/TestableJournal.java
   trunk/src/main/org/hornetq/core/journal/TransactionFailureCallback.java
   trunk/src/main/org/hornetq/core/journal/impl/JournalImpl.java
   trunk/src/main/org/hornetq/core/paging/PagingStore.java
   trunk/src/main/org/hornetq/core/paging/impl/PageImpl.java
   trunk/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
   trunk/src/main/org/hornetq/core/persistence/StorageManager.java
   trunk/src/main/org/hornetq/core/persistence/impl/journal/BatchingIDGenerator.java
   trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalLargeServerMessage.java
   trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java
   trunk/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java
   trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java
   trunk/src/main/org/hornetq/core/remoting/impl/PacketDecoder.java
   trunk/src/main/org/hornetq/core/remoting/impl/wireformat/PacketImpl.java
   trunk/src/main/org/hornetq/core/remoting/server/impl/RemotingServiceImpl.java
   trunk/src/main/org/hornetq/core/server/HornetQServer.java
   trunk/src/main/org/hornetq/core/server/cluster/impl/Redistributor.java
   trunk/src/main/org/hornetq/core/server/impl/HornetQPacketHandler.java
   trunk/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java
   trunk/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java
   trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java
   trunk/tests/src/org/hornetq/tests/integration/client/PagingTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/AsynchronousFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTestBase.java
   trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyAsynchronousFailoverTest.java
   trunk/tests/src/org/hornetq/tests/integration/largemessage/mock/MockConnectorFactory.java
   trunk/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java
   trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java
   trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java
   trunk/tests/src/org/hornetq/tests/unit/core/persistence/impl/BatchIDGeneratorUnitTest.java
   trunk/tests/src/org/hornetq/tests/util/ServiceTestBase.java
   trunk/tests/src/org/hornetq/tests/util/UnitTestCase.java
Log:
https://jira.jboss.org/jira/browse/HORNETQ-125 - Adding replicated Journal, paging and large message

Modified: trunk/src/main/org/hornetq/core/client/impl/FailoverManager.java
===================================================================
--- trunk/src/main/org/hornetq/core/client/impl/FailoverManager.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/client/impl/FailoverManager.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -48,7 +48,9 @@
                                final boolean blockOnPersistentSend) throws HornetQException;
 
    void removeSession(final ClientSessionInternal session);
-
+   
+   public RemotingConnection getConnection();
+   
    int numConnections();
 
    int numSessions();

Modified: trunk/src/main/org/hornetq/core/journal/Journal.java
===================================================================
--- trunk/src/main/org/hornetq/core/journal/Journal.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/journal/Journal.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -71,32 +71,20 @@
     */
    void appendPrepareRecord(long txID, EncodingSupport transactionData, boolean sync) throws Exception;
 
+   void appendPrepareRecord(long txID, byte[] transactionData, boolean sync) throws Exception;
+
    void appendRollbackRecord(long txID, boolean sync) throws Exception;
 
    // Load
+   
+   long load(LoaderCallback reloadManager) throws Exception;
 
+
    long load(List<RecordInfo> committedRecords, List<PreparedTransactionInfo> preparedTransactions, TransactionFailureCallback transactionFailure) throws Exception;
 
    int getAlignment() throws Exception;
 
    void perfBlast(int pages) throws Exception;
 
-   /** This method is called automatically when a new file is opened.
-    * @return true if it needs to re-check due to cleanup or other factors  */
-   boolean checkReclaimStatus() throws Exception;
 
-   /** This method check for the need of compacting based on the minCompactPercentage 
-    * This method is usually called automatically when new files are opened
-   */
-   void checkCompact() throws Exception;
-
-   /**
-    * Eliminate deleted records of the journal.
-    * @throws Exception 
-    */
-   void compact() throws Exception;
-   
-   
-   JournalFile[] getDataFiles();
-
 }

Modified: trunk/src/main/org/hornetq/core/journal/TestableJournal.java
===================================================================
--- trunk/src/main/org/hornetq/core/journal/TestableJournal.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/journal/TestableJournal.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -13,6 +13,7 @@
 
 package org.hornetq.core.journal;
 
+import org.hornetq.core.journal.impl.JournalFile;
 
 /**
  * 
@@ -46,17 +47,20 @@
 
    int getMaxAIO();
 
-   /** This method could be promoted to {@link Journal} interface when we decide to use the loadManager 
-    *  instead of load(List,List)
-    */
-   long load(LoaderCallback reloadManager) throws Exception;
-
    void forceMoveNextFile() throws Exception;
 
    void setAutoReclaim(boolean autoReclaim);
 
    boolean isAutoReclaim();
 
+   void compact() throws Exception;
    
+   /** This method is called automatically when a new file is opened.
+    * @return true if it needs to re-check due to cleanup or other factors  */
+   boolean checkReclaimStatus() throws Exception;
 
+   
+   JournalFile[] getDataFiles();
+   
+
 }

Modified: trunk/src/main/org/hornetq/core/journal/TransactionFailureCallback.java
===================================================================
--- trunk/src/main/org/hornetq/core/journal/TransactionFailureCallback.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/journal/TransactionFailureCallback.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -16,7 +16,7 @@
 import java.util.List;
 
 /**
- * A TransactionFailureCallback
+ * A Callback to receive information about bad transactions for extra cleanup required for broken transactions such as large messages.
  *
  * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
  *

Modified: trunk/src/main/org/hornetq/core/journal/impl/JournalImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/journal/impl/JournalImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/journal/impl/JournalImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -1163,7 +1163,17 @@
    {
       appendDeleteRecordTransactional(txID, id, NullEncoding.instance);
    }
+   
+   /* (non-Javadoc)
+    * @see org.hornetq.core.journal.Journal#appendPrepareRecord(long, byte[], boolean)
+    */
+   public void appendPrepareRecord(long txID, byte[] transactionData, boolean sync) throws Exception
+   {
+      appendPrepareRecord(txID, new ByteArrayEncoding(transactionData), sync);
+   }
 
+
+
    /** 
     * 
     * <p>If the system crashed after a prepare was called, it should store information that is required to bring the transaction 
@@ -2148,7 +2158,7 @@
       return (compactMinFiles * compactPercentage);
    }
 
-   public synchronized void cleanUp(final JournalFile file) throws Exception
+   private synchronized void cleanUp(final JournalFile file) throws Exception
    {
       if (state != STATE_LOADED)
       {
@@ -2225,7 +2235,7 @@
 
    }
 
-   public void checkCompact() throws Exception
+   private void checkCompact() throws Exception
    {
       if (compactMinFiles == 0)
       {
@@ -3344,7 +3354,12 @@
    private static class NullEncoding implements EncodingSupport
    {
 
-      static NullEncoding instance = new NullEncoding();
+      private static NullEncoding instance = new NullEncoding();
+      
+      public static NullEncoding getInstance()
+      {
+         return instance;
+      }
 
       public void decode(final HornetQBuffer buffer)
       {

Modified: trunk/src/main/org/hornetq/core/paging/PagingStore.java
===================================================================
--- trunk/src/main/org/hornetq/core/paging/PagingStore.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/paging/PagingStore.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -54,6 +54,8 @@
    public boolean readPage() throws Exception;
    
    Page getCurrentPage();
+   
+   Page createPage(final int page) throws Exception;
 
    /**
     * 

Modified: trunk/src/main/org/hornetq/core/paging/impl/PageImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/paging/impl/PageImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/paging/impl/PageImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -28,6 +28,8 @@
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.paging.Page;
 import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.persistence.StorageManager;
+import org.hornetq.utils.SimpleString;
 
 /**
  * 
@@ -59,16 +61,22 @@
    private final SequentialFileFactory fileFactory;
 
    private final AtomicInteger size = new AtomicInteger(0);
+   
+   private final StorageManager storageManager;
+   
+   private final SimpleString storeName;
 
    // Static --------------------------------------------------------
 
    // Constructors --------------------------------------------------
 
-   public PageImpl(final SequentialFileFactory factory, final SequentialFile file, final int pageId) throws Exception
+   public PageImpl(final SimpleString storeName, final StorageManager storageManager, final SequentialFileFactory factory, final SequentialFile file, final int pageId) throws Exception
    {
       this.pageId = pageId;
       this.file = file;
-      fileFactory = factory;
+      this.fileFactory = factory;
+      this.storageManager = storageManager;
+      this.storeName = storeName;
    }
 
    // Public --------------------------------------------------------
@@ -154,9 +162,11 @@
       numberOfMessages.incrementAndGet();
       size.addAndGet(buffer.limit());
       
+      storageManager.pageWrite(message, pageId);
+      
       if (message.getMessage(null).isLargeMessage())
       {
-         // If we don't sync on large messages we could have the risk of files unnatended files on disk
+         // If we don't sync on large messages we could have the risk of unattended files on disk
          sync();
       }
    }
@@ -175,11 +185,20 @@
 
    public void close() throws Exception
    {
+      if (storageManager != null)
+      {
+         storageManager.pageClosed(storeName, pageId);
+      }
       file.close();
    }
 
    public void delete() throws Exception
    {
+      if (storageManager != null)
+      {
+         storageManager.pageDeleted(storeName, pageId);
+      }
+      
       if (suspiciousRecords)
       {
          log.warn("File " + file.getFileName() +

Modified: trunk/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -610,6 +610,35 @@
       return currentPage;
    }
 
+   
+   public Page createPage(final int page) throws Exception
+   {
+      String fileName = createFileName(page);
+
+      if (fileFactory == null)
+      {
+         fileFactory = storeFactory.newFileFactory(getStoreName());
+      }
+
+      SequentialFile file = fileFactory.createSequentialFile(fileName, 1000);
+
+      file.open();
+
+      long size = file.size();
+
+      if (fileFactory.isSupportsCallbacks() && size < pageSize)
+      {
+         file.fill((int)size, (int)(pageSize - size), (byte)0);
+      }
+
+      file.position(0);
+
+      file.close();
+
+      return new PageImpl(this.storeName, storageManager, fileFactory, file, page);
+   }
+
+   
    // TestSupportPageStore ------------------------------------------
 
    public void forceAnotherPage() throws Exception
@@ -703,36 +732,6 @@
 
    // Protected -----------------------------------------------------
 
-   // In order to test failures, we need to be able to extend this class
-   // and replace the Page for another Page that will fail before the file is removed
-   // That's why createPage is not a private method
-   protected Page createPage(final int page) throws Exception
-   {
-      String fileName = createFileName(page);
-
-      if (fileFactory == null)
-      {
-         fileFactory = storeFactory.newFileFactory(getStoreName());
-      }
-
-      SequentialFile file = fileFactory.createSequentialFile(fileName, 1000);
-
-      file.open();
-
-      long size = file.size();
-
-      if (fileFactory.isSupportsCallbacks() && size < pageSize)
-      {
-         file.fill((int)size, (int)(pageSize - size), (byte)0);
-      }
-
-      file.position(0);
-
-      file.close();
-
-      return new PageImpl(fileFactory, file, page);
-   }
-
    // Private -------------------------------------------------------
 
    /**
@@ -753,6 +752,7 @@
          // nothing to be done on this case.
          return true;
       }
+      
 
       // Depage has to be done atomically, in case of failure it should be
       // back to where it was
@@ -931,8 +931,9 @@
          {
             currentPage.close();
          }
-
+         
          currentPage = createPage(currentPageId);
+         
 
          currentPageSize.set(0);
 

Modified: trunk/src/main/org/hornetq/core/persistence/StorageManager.java
===================================================================
--- trunk/src/main/org/hornetq/core/persistence/StorageManager.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/persistence/StorageManager.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -19,6 +19,7 @@
 import javax.transaction.xa.Xid;
 
 import org.hornetq.core.paging.PageTransactionInfo;
+import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.postoffice.Binding;
 import org.hornetq.core.postoffice.PostOffice;
@@ -45,6 +46,18 @@
 {
    // Message related operations
    
+   void pageClosed(SimpleString storeName, int pageNumber);
+   
+   void pageDeleted(SimpleString storeName, int pageNumber);
+   
+   void pageWrite(PagedMessage message, int pageNumber);
+   
+   boolean isReplicated();
+   
+   void afterReplicated(Runnable run);
+   
+   void completeReplication();
+   
    UUID getPersistentID();
    
    void setPersistentID(UUID id) throws Exception;
@@ -87,6 +100,8 @@
 
    LargeServerMessage createLargeMessage();
 
+   LargeServerMessage createLargeMessage(long id, byte [] header);
+
    void prepare(long txID, Xid xid) throws Exception;
 
    void commit(long txID) throws Exception;
@@ -97,15 +112,21 @@
 
    void deletePageTransactional(long txID, long recordID) throws Exception;
 
+   /** This method is only useful at the backup side. We only load internal structures making the journals ready for
+    *  append mode on the backup side. */
+   void loadInternalOnly() throws Exception;
+
+   
+   public void loadMessageJournal(final PostOffice postOffice,
+                                  final PagingManager pagingManager,
+                                  final ResourceManager resourceManager,
+                                  final Map<Long, Queue> queues,
+                                  final Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception;
+
    long storeHeuristicCompletion(Xid xid, boolean isCommit) throws Exception;
    
    void deleteHeuristicCompletion(long id) throws Exception;
    
-   void loadMessageJournal(PostOffice postOffice,
-                           PagingManager pagingManager,
-                           ResourceManager resourceManager,
-                           Map<Long, Queue> queues,
-                           Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception;
 
    // Bindings related operations
 

Modified: trunk/src/main/org/hornetq/core/persistence/impl/journal/BatchingIDGenerator.java
===================================================================
--- trunk/src/main/org/hornetq/core/persistence/impl/journal/BatchingIDGenerator.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/persistence/impl/journal/BatchingIDGenerator.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -38,8 +38,6 @@
    private static final Logger log = Logger.getLogger(BatchingIDGenerator.class);
 
 
-   public static final byte ID_COUNTER_RECORD = 24;
-
    // Attributes ----------------------------------------------------
 
    // Static --------------------------------------------------------
@@ -127,7 +125,7 @@
    {
       try
       {
-         journalStorage.appendAddRecord(journalID, ID_COUNTER_RECORD, new IDCounterEncoding(id), true);
+         journalStorage.appendAddRecord(journalID, JournalStorageManager.ID_COUNTER_RECORD, new IDCounterEncoding(id), true);
       }
       catch (Exception e)
       {

Modified: trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalLargeServerMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalLargeServerMessage.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalLargeServerMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -91,11 +91,9 @@
       {
          file.open();
       }
+      
+      storageManager.addBytesToLargeMessage(file, this.getMessageID(), bytes);
 
-      file.position(file.size());
-
-      file.write(ByteBuffer.wrap(bytes), false);
-
       bodySize += bytes.length;
    }
 
@@ -232,6 +230,7 @@
    public synchronized void deleteFile() throws Exception
    {
       validateFile();
+      releaseResources();
       storageManager.deleteFile(file);
    }
    
@@ -262,10 +261,11 @@
    {
       super.setStored();
       releaseResources();
+      
+      
       if (file != null && linkMessage == null)
       {
-         SequentialFile fileToRename = storageManager.createFileForLargeMessage(getMessageID(), isStored());
-         file.renameTo(fileToRename.getFileName());
+         storageManager.completeLargeMessage(this);
       }
    }
 
@@ -304,6 +304,12 @@
 
       return newMessage;
    }
+   
+   
+   public SequentialFile getFile()
+   {
+      return file;
+   }
 
    // Package protected ---------------------------------------------
 

Modified: trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java
===================================================================
--- trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -18,6 +18,7 @@
 import static org.hornetq.utils.DataConstants.SIZE_LONG;
 
 import java.io.File;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -29,12 +30,14 @@
 
 import javax.transaction.xa.Xid;
 
+import org.hornetq.core.buffers.ChannelBuffer;
 import org.hornetq.core.buffers.ChannelBuffers;
 import org.hornetq.core.config.Configuration;
 import org.hornetq.core.exception.HornetQException;
 import org.hornetq.core.filter.Filter;
 import org.hornetq.core.journal.EncodingSupport;
 import org.hornetq.core.journal.Journal;
+import org.hornetq.core.journal.LoaderCallback;
 import org.hornetq.core.journal.PreparedTransactionInfo;
 import org.hornetq.core.journal.RecordInfo;
 import org.hornetq.core.journal.SequentialFile;
@@ -46,6 +49,7 @@
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.message.impl.MessageImpl;
 import org.hornetq.core.paging.PageTransactionInfo;
+import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.paging.impl.PageTransactionInfoImpl;
 import org.hornetq.core.persistence.QueueBindingInfo;
@@ -54,6 +58,8 @@
 import org.hornetq.core.postoffice.PostOffice;
 import org.hornetq.core.remoting.impl.wireformat.XidCodecSupport;
 import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.core.replication.ReplicationManager;
+import org.hornetq.core.replication.impl.ReplicatedJournal;
 import org.hornetq.core.server.JournalType;
 import org.hornetq.core.server.LargeServerMessage;
 import org.hornetq.core.server.MessageReference;
@@ -92,6 +98,8 @@
 
    public static final byte PERSISTENT_ID_RECORD = 23;
 
+   public static final byte ID_COUNTER_RECORD = 24;
+
    // type + expiration + timestamp + priority
    public static final int SIZE_FIELDS = SIZE_INT + SIZE_LONG + SIZE_LONG + SIZE_BYTE;
 
@@ -119,6 +127,8 @@
 
    private final BatchingIDGenerator idGenerator;
 
+   private final ReplicationManager replicator;
+
    private final Journal messageJournal;
 
    private final Journal bindingsJournal;
@@ -144,11 +154,18 @@
    private final String journalDir;
 
    private final String largeMessagesDirectory;
-   
+
    public JournalStorageManager(final Configuration config, final Executor executor)
    {
+      this(config, executor, null);
+   }
+
+   public JournalStorageManager(final Configuration config, final Executor executor, final ReplicationManager replicator)
+   {
       this.executor = executor;
-      
+
+      this.replicator = replicator;
+
       if (config.getJournalType() != JournalType.NIO && config.getJournalType() != JournalType.ASYNCIO)
       {
          throw new IllegalArgumentException("Only NIO and AsyncIO are supported journals");
@@ -165,6 +182,26 @@
 
       journalDir = config.getJournalDirectory();
 
+      SequentialFileFactory bindingsFF = new NIOSequentialFileFactory(bindingsDir);
+
+      Journal localBindings = new JournalImpl(1024 * 1024,
+                                              2,
+                                              config.getJournalCompactMinFiles(),
+                                              config.getJournalCompactPercentage(),
+                                              bindingsFF,
+                                              "hornetq-bindings",
+                                              "bindings",
+                                              1);
+
+      if (replicator != null)
+      {
+         this.bindingsJournal = new ReplicatedJournal((byte)0, localBindings, replicator);
+      }
+      else
+      {
+         this.bindingsJournal = localBindings;
+      }
+
       if (journalDir == null)
       {
          throw new NullPointerException("journal-dir is null");
@@ -172,17 +209,6 @@
 
       createJournalDir = config.isCreateJournalDir();
 
-      SequentialFileFactory bindingsFF = new NIOSequentialFileFactory(bindingsDir);
-
-      bindingsJournal = new JournalImpl(1024 * 1024,
-                                        2,
-                                        config.getJournalCompactMinFiles(),
-                                        config.getJournalCompactPercentage(),
-                                        bindingsFF,
-                                        "hornetq-bindings",
-                                        "bindings",
-                                        1);
-
       syncNonTransactional = config.isJournalSyncNonTransactional();
 
       syncTransactional = config.isJournalSyncTransactional();
@@ -217,17 +243,33 @@
          throw new IllegalArgumentException("Unsupported journal type " + config.getJournalType());
       }
 
-      this.idGenerator = new BatchingIDGenerator(0, CHECKPOINT_BATCH_SIZE, bindingsJournal);
+      if (config.isBackup())
+      {
+         this.idGenerator = null;
+      }
+      else
+      {
+         this.idGenerator = new BatchingIDGenerator(0, CHECKPOINT_BATCH_SIZE, bindingsJournal);
+      }
 
-      messageJournal = new JournalImpl(config.getJournalFileSize(),
-                                       config.getJournalMinFiles(),
-                                       config.getJournalCompactMinFiles(),
-                                       config.getJournalCompactPercentage(),
-                                       journalFF,
-                                       "hornetq-data",
-                                       "hq",
-                                       config.getJournalMaxAIO());
+      Journal localMessage = new JournalImpl(config.getJournalFileSize(),
+                                             config.getJournalMinFiles(),
+                                             config.getJournalCompactMinFiles(),
+                                             config.getJournalCompactPercentage(),
+                                             journalFF,
+                                             "hornetq-data",
+                                             "hq",
+                                             config.getJournalMaxAIO());
 
+      if (replicator != null)
+      {
+         this.messageJournal = new ReplicatedJournal((byte)1, localMessage, replicator);
+      }
+      else
+      {
+         this.messageJournal = localMessage;
+      }
+
       largeMessagesDirectory = config.getLargeMessagesDirectory();
 
       largeMessagesFactory = new NIOSequentialFileFactory(largeMessagesDirectory);
@@ -235,6 +277,70 @@
       perfBlastPages = config.getJournalPerfBlastPages();
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#completeReplication()
+    */
+   public void completeReplication()
+   {
+      if (replicator != null)
+      {
+         replicator.closeContext();
+      }
+   }
+
+   public boolean isReplicated()
+   {
+      return replicator != null;
+   }
+
+   // TODO: shouldn't those page methods be on the PageManager?
+
+   /* 
+    * 
+    * (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#pageClosed(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageClosed(SimpleString storeName, int pageNumber)
+   {
+      if (isReplicated())
+      {
+         replicator.pageClosed(storeName, pageNumber);
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#pageDeleted(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageDeleted(SimpleString storeName, int pageNumber)
+   {
+      if (isReplicated())
+      {
+         replicator.pageDeleted(storeName, pageNumber);
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#pageWrite(org.hornetq.utils.SimpleString, int, org.hornetq.core.buffers.ChannelBuffer)
+    */
+   public void pageWrite(PagedMessage message, int pageNumber)
+   {
+      if (isReplicated())
+      {
+         replicator.pageWrite(message, pageNumber);
+      }
+   }
+
+   // TODO: shouldn't those page methods be on the PageManager? ^^^^
+
+   public void afterReplicated(Runnable run)
+   {
+      if (replicator == null)
+      {
+         throw new IllegalStateException("StorageManager is not replicated");
+      }
+      replicator.afterReplicated(run);
+   }
+
    public UUID getPersistentID()
    {
       return persistentID;
@@ -251,7 +357,7 @@
 
       this.persistentID = id;
    }
-     
+
    public long generateUniqueID()
    {
       long id = idGenerator.generateID();
@@ -269,6 +375,36 @@
       return new JournalLargeServerMessage(this);
    }
 
+   public void addBytesToLargeMessage(SequentialFile file, long messageId, final byte[] bytes) throws Exception
+   {
+      file.position(file.size());
+
+      file.write(ByteBuffer.wrap(bytes), false);
+
+      if (isReplicated())
+      {
+         this.replicator.largeMessageWrite(messageId, bytes);
+      }
+   }
+
+   public LargeServerMessage createLargeMessage(long id, byte[] header)
+   {
+      if (isReplicated())
+      {
+         replicator.largeMessageBegin(id);
+      }
+
+      JournalLargeServerMessage largeMessage = (JournalLargeServerMessage)createLargeMessage();
+
+      HornetQBuffer headerBuffer = ChannelBuffers.wrappedBuffer(header);
+
+      largeMessage.decodeProperties(headerBuffer);
+      
+      largeMessage.setMessageID(id);
+
+      return largeMessage;
+   }
+
    // Non transactional operations
 
    public void storeMessage(final ServerMessage message) throws Exception
@@ -310,8 +446,8 @@
 
    public void updateScheduledDeliveryTime(final MessageReference ref) throws Exception
    {
-      ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(),
-                                                                         ref.getQueue().getID());
+      ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(), ref.getQueue()
+                                                                                                            .getID());
 
       messageJournal.appendUpdateRecord(ref.getMessage().getMessageID(),
                                         SET_SCHEDULED_DELIVERY_TIME,
@@ -387,12 +523,12 @@
       messageJournal.appendAddRecord(id, HEURISTIC_COMPLETION, new HeuristicCompletionEncoding(xid, isCommit), true);
       return id;
    }
-   
+
    public void deleteHeuristicCompletion(long id) throws Exception
    {
       messageJournal.appendDeleteRecord(id, true);
    }
-   
+
    public void deletePageTransactional(final long txID, final long recordID) throws Exception
    {
       messageJournal.appendDeleteRecordTransactional(txID, recordID);
@@ -400,8 +536,8 @@
 
    public void updateScheduledDeliveryTimeTransactional(final long txID, final MessageReference ref) throws Exception
    {
-      ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(),
-                                                                         ref.getQueue().getID());
+      ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(), ref.getQueue()
+                                                                                                            .getID());
 
       messageJournal.appendUpdateRecordTransactional(txID,
                                                      ref.getMessage().getMessageID(),
@@ -466,6 +602,19 @@
                                         updateInfo,
                                         syncNonTransactional);
    }
+   /**
+    * @param journalLargeServerMessage
+    * @throws Exception 
+    */
+   public void completeLargeMessage(JournalLargeServerMessage message) throws Exception
+   {
+      if (isReplicated())
+      {
+         replicator.largeMessageEnd(message.getMessageID());
+      }
+      SequentialFile fileToRename = createFileForLargeMessage(message.getMessageID(), true);
+      message.getFile().renameTo(fileToRename.getFileName());
+   }
 
    private static final class AddMessageRecord
    {
@@ -480,20 +629,17 @@
 
       int deliveryCount;
    }
-   
-   
+
    private class LargeMessageTXFailureCallback implements TransactionFailureCallback
    {
       private final Map<Long, ServerMessage> messages;
-      
+
       public LargeMessageTXFailureCallback(Map<Long, ServerMessage> messages)
       {
          super();
          this.messages = messages;
       }
 
-
-
       public void failedTransaction(long transactionID, List<RecordInfo> records, List<RecordInfo> recordsToDelete)
       {
          for (RecordInfo record : records)
@@ -516,7 +662,7 @@
             }
          }
       }
-      
+
    }
 
    public void loadMessageJournal(final PostOffice postOffice,
@@ -530,9 +676,9 @@
       List<PreparedTransactionInfo> preparedTransactions = new ArrayList<PreparedTransactionInfo>();
 
       Map<Long, ServerMessage> messages = new HashMap<Long, ServerMessage>();
-      
+
       messageJournal.load(records, preparedTransactions, new LargeMessageTXFailureCallback(messages));
-      
+
       ArrayList<LargeServerMessage> largeMessages = new ArrayList<LargeServerMessage>();
 
       Map<Long, Map<Long, AddMessageRecord>> queueMap = new HashMap<Long, Map<Long, AddMessageRecord>>();
@@ -732,7 +878,7 @@
             {
                record.message.putLongProperty(MessageImpl.HDR_SCHEDULED_DELIVERY_TIME, scheduledDeliveryTime);
             }
-            
+
             MessageReference ref = postOffice.reroute(record.message, queue, null);
 
             ref.setDeliveryCount(record.deliveryCount);
@@ -750,11 +896,12 @@
       {
          if (msg.getRefCount() == 0)
          {
-            log.debug("Large message: " + msg.getMessageID() + " didn't have any associated reference, file will be deleted");
+            log.debug("Large message: " + msg.getMessageID() +
+                      " didn't have any associated reference, file will be deleted");
             msg.decrementRefCount();
          }
       }
-      
+
       if (perfBlastPages != -1)
       {
          messageJournal.perfBlast(perfBlastPages);
@@ -774,14 +921,14 @@
       LargeMessageEncoding messageEncoding = new LargeMessageEncoding(largeMessage);
 
       messageEncoding.decode(buff);
-      
+
       Long originalMessageID = (Long)largeMessage.getProperties().getProperty(MessageImpl.HDR_ORIG_MESSAGE_ID);
-      
+
       // Using the linked file by the original file
       if (originalMessageID != null)
       {
          LargeServerMessage originalMessage = (LargeServerMessage)messages.get(originalMessageID);
-         
+
          if (originalMessage == null)
          {
             // this could happen if the message was deleted but the file still exists as the file still being used
@@ -790,9 +937,9 @@
             originalMessage.setStored();
             messages.put(originalMessageID, originalMessage);
          }
-         
+
          originalMessage.incrementRefCount();
-         
+
          largeMessage.setLinkedMessage(originalMessage);
       }
       return largeMessage;
@@ -835,7 +982,7 @@
                case ADD_LARGE_MESSAGE:
                {
                   messages.put(record.id, parseLargeMessage(messages, buff));
-                  
+
                   break;
                }
                case ADD_MESSAGE:
@@ -1038,7 +1185,7 @@
 
             bindingEncoding.setId(id);
 
-            queueBindingInfos.add(bindingEncoding);          
+            queueBindingInfos.add(bindingEncoding);
          }
          else if (rec == PERSISTENT_ID_RECORD)
          {
@@ -1048,7 +1195,7 @@
 
             persistentID = encoding.uuid;
          }
-         else if (rec == BatchingIDGenerator.ID_COUNTER_RECORD)
+         else if (rec == ID_COUNTER_RECORD)
          {
             idGenerator.loadState(record.id, buffer);
          }
@@ -1092,7 +1239,10 @@
       }
 
       // Must call close to make sure last id is persisted
-      idGenerator.close();
+      if (idGenerator != null)
+      {
+         idGenerator.close();
+      }
 
       bindingsJournal.stop();
 
@@ -1108,6 +1258,39 @@
       return started;
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#loadInternalOnly()
+    */
+   public void loadInternalOnly() throws Exception
+   {
+      LoaderCallback dummyLoader = new LoaderCallback()
+      {
+
+         public void failedTransaction(long transactionID, List<RecordInfo> records, List<RecordInfo> recordsToDelete)
+         {
+         }
+
+         public void updateRecord(RecordInfo info)
+         {
+         }
+
+         public void deleteRecord(long id)
+         {
+         }
+
+         public void addRecord(RecordInfo info)
+         {
+         }
+
+         public void addPreparedTransaction(PreparedTransactionInfo preparedTransaction)
+         {
+         }
+      };
+
+      bindingsJournal.load(dummyLoader);
+      messageJournal.load(dummyLoader);
+   }
+
    // Public -----------------------------------------------------------------------------------
 
    public Journal getMessageJournal()
@@ -1125,7 +1308,7 @@
    // This should be accessed from this package only
    void deleteFile(final SequentialFile file)
    {
-      executor.execute(new Runnable()
+      Runnable deleteAction = new Runnable()
       {
          public void run()
          {
@@ -1139,7 +1322,16 @@
             }
          }
 
-      });
+      };
+
+      if (executor == null)
+      {
+         deleteAction.run();
+      }
+      else
+      {
+         executor.execute(deleteAction);
+      }
    }
 
    /**
@@ -1228,12 +1420,13 @@
          return XidCodecSupport.getXidEncodeLength(xid);
       }
    }
-   
+
    private static class HeuristicCompletionEncoding implements EncodingSupport
    {
       Xid xid;
+
       boolean isCommit;
-      
+
       HeuristicCompletionEncoding(final Xid xid, final boolean isCommit)
       {
          this.xid = xid;
@@ -1621,4 +1814,5 @@
 
    }
 
+
 }

Modified: trunk/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java
===================================================================
--- trunk/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -19,13 +19,16 @@
 
 import javax.transaction.xa.Xid;
 
+import org.hornetq.core.buffers.ChannelBuffers;
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.paging.PageTransactionInfo;
+import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.persistence.QueueBindingInfo;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.postoffice.Binding;
 import org.hornetq.core.postoffice.PostOffice;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
 import org.hornetq.core.server.LargeServerMessage;
 import org.hornetq.core.server.MessageReference;
 import org.hornetq.core.server.Queue;
@@ -183,6 +186,20 @@
       return new NullStorageLargeServerMessage();
    }
    
+   public LargeServerMessage createLargeMessage(long id, byte[] header)
+   {
+      NullStorageLargeServerMessage largeMessage = new NullStorageLargeServerMessage();
+
+      HornetQBuffer headerBuffer = ChannelBuffers.wrappedBuffer(header);
+
+      largeMessage.decodeProperties(headerBuffer);
+      
+      largeMessage.setMessageID(id);
+      
+      return largeMessage;     
+   }
+   
+   
    public long generateUniqueID()
    {
       long id = idSequence.getAndIncrement();
@@ -249,4 +266,56 @@
    {
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#loadInternalOnly()
+    */
+   public void loadInternalOnly() throws Exception
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#afterReplicated(java.lang.Runnable)
+    */
+   public void afterReplicated(Runnable run)
+   {
+      run.run();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#isReplicated()
+    */
+   public boolean isReplicated()
+   {
+      return false;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#completeReplication()
+    */
+   public void completeReplication()
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#pageClosed(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageClosed(SimpleString storeName, int pageNumber)
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#pageDeleted(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageDeleted(SimpleString storeName, int pageNumber)
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#pageWrite(org.hornetq.core.paging.PagedMessage, int)
+    */
+   public void pageWrite(PagedMessage message, int pageNumber)
+   {
+   }
+
+
 }

Modified: trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -848,7 +848,7 @@
 
    private void processRoute(final ServerMessage message, final RoutingContext context) throws Exception
    {
-      List<MessageReference> refs = new ArrayList<MessageReference>();
+      final List<MessageReference> refs = new ArrayList<MessageReference>();
 
       Transaction tx = context.getTransaction();
       
@@ -924,14 +924,35 @@
          tx.addOperation(new AddOperation(refs));
       }
       else
-      {         
-         for (MessageReference ref : refs)
+      {
+         if (storageManager.isReplicated())
          {
-
-            ref.getQueue().addLast(ref);
+            storageManager.afterReplicated(new Runnable()
+            {
+               public void run()
+               {
+                  deliverReferences(refs);
+               }
+            });
          }
+         else
+         {
+            deliverReferences(refs);
+         }
       }
    }
+
+   /**
+    * @param refs
+    */
+   private void deliverReferences(final List<MessageReference> refs)
+   {
+      for (MessageReference ref : refs)
+      {
+  
+         ref.getQueue().addLast(ref);
+      }
+   }
    
    private synchronized void startExpiryScanner()
    {

Modified: trunk/src/main/org/hornetq/core/remoting/impl/PacketDecoder.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/PacketDecoder.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/remoting/impl/PacketDecoder.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -13,6 +13,19 @@
 
 package org.hornetq.core.remoting.impl;
 
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_LARGE_MESSAGE_BEGIN;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_LARGE_MESSAGE_END;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_LARGE_MESSAGE_WRITE;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_PAGE_EVENT;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_PAGE_WRITE;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_PREPARE;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_DELETE_TX;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_COMMIT_ROLLBACK;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_APPEND_TX;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_DELETE;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_RESPONSE;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_APPEND;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATE_REPLICATION;
 import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATESESSION;
 import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATESESSION_RESP;
 import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATE_QUEUE;
@@ -63,6 +76,7 @@
 
 import org.hornetq.core.remoting.Packet;
 import org.hornetq.core.remoting.impl.wireformat.CreateQueueMessage;
+import org.hornetq.core.remoting.impl.wireformat.CreateReplicationSessionMessage;
 import org.hornetq.core.remoting.impl.wireformat.CreateSessionMessage;
 import org.hornetq.core.remoting.impl.wireformat.CreateSessionResponseMessage;
 import org.hornetq.core.remoting.impl.wireformat.HornetQExceptionMessage;
@@ -72,6 +86,18 @@
 import org.hornetq.core.remoting.impl.wireformat.Ping;
 import org.hornetq.core.remoting.impl.wireformat.ReattachSessionMessage;
 import org.hornetq.core.remoting.impl.wireformat.ReattachSessionResponseMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationAddMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationAddTXMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationCommitMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationDeleteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationDeleteTXMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargeMessageBeingMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargeMessageWriteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargemessageEndMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPageEventMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPageWriteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPrepareMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationResponseMessage;
 import org.hornetq.core.remoting.impl.wireformat.RollbackMessage;
 import org.hornetq.core.remoting.impl.wireformat.SessionAcknowledgeMessage;
 import org.hornetq.core.remoting.impl.wireformat.SessionBindingQueryMessage;
@@ -351,7 +377,72 @@
          {
             packet = new SessionSendContinuationMessage();
             break;
-         }        
+         }
+         case CREATE_REPLICATION:
+         {
+            packet = new CreateReplicationSessionMessage();
+            break;
+         }
+         case REPLICATION_APPEND:
+         {
+            packet = new ReplicationAddMessage();
+            break;
+         }
+         case REPLICATION_APPEND_TX:
+         {
+            packet = new ReplicationAddTXMessage();
+            break;
+         }
+         case REPLICATION_DELETE:
+         {
+            packet = new ReplicationDeleteMessage();
+            break;
+         }
+         case REPLICATION_DELETE_TX:
+         {
+            packet = new ReplicationDeleteTXMessage();
+            break;
+         }
+         case REPLICATION_PREPARE:
+         {
+            packet = new ReplicationPrepareMessage();
+            break;
+         }
+         case REPLICATION_COMMIT_ROLLBACK:
+         {
+            packet = new ReplicationCommitMessage();
+            break;
+         }
+         case REPLICATION_RESPONSE:
+         {
+            packet = new ReplicationResponseMessage();
+            break;
+         }
+         case REPLICATION_PAGE_WRITE:
+         {
+            packet = new ReplicationPageWriteMessage();
+            break;
+         }
+         case REPLICATION_PAGE_EVENT:
+         {
+            packet = new ReplicationPageEventMessage();
+            break;
+         }
+         case REPLICATION_LARGE_MESSAGE_BEGIN:
+         {
+            packet = new ReplicationLargeMessageBeingMessage();
+            break;
+         }
+         case REPLICATION_LARGE_MESSAGE_END:
+         {
+            packet = new ReplicationLargemessageEndMessage();
+            break;
+         }
+         case REPLICATION_LARGE_MESSAGE_WRITE:
+         {
+            packet = new ReplicationLargeMessageWriteMessage();
+            break;
+         }
          case SESS_FORCE_CONSUMER_DELIVERY:
          {
             packet = new SessionForceConsumerDelivery();

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/CreateReplicationSessionMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/CreateReplicationSessionMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/CreateReplicationSessionMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * @author <a href="mailto:tim.fox at jboss.com">Clebert Suconic</a>
+ */
+public class CreateReplicationSessionMessage extends PacketImpl
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long sessionChannelID;
+
+   private int windowSize;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public CreateReplicationSessionMessage(final long sessionChannelID, final int windowSize)
+   {
+      super(CREATE_REPLICATION);
+
+      this.sessionChannelID = sessionChannelID;
+
+      this.windowSize = windowSize;
+   }
+
+   public CreateReplicationSessionMessage()
+   {
+      super(CREATE_REPLICATION);
+   }
+
+   // Public --------------------------------------------------------
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE +
+      // buffer.writeLong(sessionChannelID);
+             DataConstants.SIZE_LONG +
+             // buffer.writeInt(windowSize);
+             DataConstants.SIZE_INT;
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeLong(sessionChannelID);
+      buffer.writeInt(windowSize);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      sessionChannelID = buffer.readLong();
+      windowSize = buffer.readInt();
+   }
+
+   /**
+    * @return the sessionChannelID
+    */
+   public long getSessionChannelID()
+   {
+      return sessionChannelID;
+   }
+
+   /**
+    * @return the windowSize
+    */
+   public int getWindowSize()
+   {
+      return windowSize;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}

Modified: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/PacketImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/PacketImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/PacketImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -28,16 +28,17 @@
    // Constants -------------------------------------------------------------------------
 
    private static final Logger log = Logger.getLogger(PacketImpl.class);
-   
+
    // The minimal size for all the packets, Common data for all the packets (look at PacketImpl.encode)
-   protected static final int BASIC_PACKET_SIZE = DataConstants.SIZE_INT + DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
+   protected static final int BASIC_PACKET_SIZE = DataConstants.SIZE_INT + DataConstants.SIZE_BYTE +
+                                                  DataConstants.SIZE_LONG;
 
    private long channelID;
 
    private final byte type;
-   
+
    private int size;
-   
+
    // The packet types
    // -----------------------------------------------------------------------------------
 
@@ -65,12 +66,13 @@
 
    public static final byte DELETE_QUEUE = 35;
 
+   public static final byte CREATE_REPLICATION = 36;
 
    // Session
    public static final byte SESS_CREATECONSUMER = 40;
 
    public static final byte SESS_ACKNOWLEDGE = 41;
-   
+
    public static final byte SESS_EXPIRED = 42;
 
    public static final byte SESS_COMMIT = 43;
@@ -126,7 +128,7 @@
    public static final byte SESS_FLOWTOKEN = 70;
 
    public static final byte SESS_SEND = 71;
-   
+
    public static final byte SESS_SEND_LARGE = 72;
 
    public static final byte SESS_SEND_CONTINUATION = 73;
@@ -139,6 +141,31 @@
 
    public static final byte SESS_FORCE_CONSUMER_DELIVERY = 77;
 
+   // Replication
+
+   public static final byte REPLICATION_RESPONSE = 80;
+
+   public static final byte REPLICATION_APPEND = 81;
+
+   public static final byte REPLICATION_APPEND_TX = 82;
+
+   public static final byte REPLICATION_DELETE = 83;
+
+   public static final byte REPLICATION_DELETE_TX = 84;
+   
+   public static final byte REPLICATION_PREPARE = 85;
+   
+   public static final byte REPLICATION_COMMIT_ROLLBACK = 86;
+   
+   public static final byte REPLICATION_PAGE_WRITE = 87;
+
+   public static final byte REPLICATION_PAGE_EVENT = 88;
+   
+   public static final byte REPLICATION_LARGE_MESSAGE_BEGIN = 89;
+   
+   public static final byte REPLICATION_LARGE_MESSAGE_END = 90;
+   
+   public static final byte REPLICATION_LARGE_MESSAGE_WRITE = 91;
    // Static --------------------------------------------------------
 
    public PacketImpl(final byte type)
@@ -148,7 +175,6 @@
 
    // Public --------------------------------------------------------
 
-
    public byte getType()
    {
       return type;
@@ -163,40 +189,40 @@
    {
       this.channelID = channelID;
    }
-   
+
    public int encode(final HornetQBuffer buffer)
    {
       // The standard header fields
       buffer.writeInt(0); // The length gets filled in at the end
       buffer.writeByte(type);
       buffer.writeLong(channelID);
-      
+
       encodeBody(buffer);
 
       size = buffer.writerIndex();
-      
+
       // The length doesn't include the actual length byte
       int len = size - DataConstants.SIZE_INT;
 
       buffer.setInt(0, len);
-      
+
       return size;
    }
 
    public void decode(final HornetQBuffer buffer)
    {
       channelID = buffer.readLong();
-      
+
       decodeBody(buffer);
-      
+
       size = buffer.readerIndex();
    }
-   
+
    public final int getPacketSize()
    {
       return size;
    }
-   
+
    public int getRequiredBufferSize()
    {
       return BASIC_PACKET_SIZE;
@@ -252,7 +278,7 @@
    {
       return DataConstants.SIZE_INT + str.length() * 2;
    }
-   
+
    protected int nullableStringEncodeSize(String str)
    {
       return DataConstants.SIZE_BOOLEAN + (str != null ? stringEncodeSize(str) : 0);

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationAddMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationAddMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long id;
+
+   /** 0 - Bindings, 1 - MessagesJournal */
+   private byte journalID;
+
+   private boolean isUpdate;
+
+   private byte recordType;
+
+   private EncodingSupport encodingData;
+
+   private byte[] recordData;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationAddMessage()
+   {
+      super(REPLICATION_APPEND);
+   }
+
+   public ReplicationAddMessage(final byte journalID,
+                                final boolean isUpdate,
+                                final long id,
+                                final byte recordType,
+                                final EncodingSupport encodingData)
+   {
+      this();
+      this.journalID = journalID;
+      this.isUpdate = isUpdate;
+      this.id = id;
+      this.recordType = recordType;
+      this.encodingData = encodingData;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_BYTE +
+             DataConstants.SIZE_BOOLEAN +
+             DataConstants.SIZE_LONG +
+             DataConstants.SIZE_BYTE +
+             DataConstants.SIZE_INT +
+             (encodingData != null ? encodingData.getEncodeSize() : recordData.length);
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeByte(journalID);
+      buffer.writeBoolean(isUpdate);
+      buffer.writeLong(id);
+      buffer.writeByte(recordType);
+      buffer.writeInt(encodingData.getEncodeSize());
+      encodingData.encode(buffer);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      journalID = buffer.readByte();
+      isUpdate = buffer.readBoolean();
+      id = buffer.readLong();
+      recordType = buffer.readByte();
+      int size = buffer.readInt();
+      recordData = new byte[size];
+      buffer.readBytes(recordData);
+   }
+
+   /**
+    * @return the id
+    */
+   public long getId()
+   {
+      return id;
+   }
+
+   /**
+    * @return the journalID
+    */
+   public byte getJournalID()
+   {
+      return journalID;
+   }
+
+   public boolean isUpdate()
+   {
+      return isUpdate;
+   }
+
+   /**
+    * @return the recordType
+    */
+   public byte getRecordType()
+   {
+      return recordType;
+   }
+
+   /**
+    * @return the recordData
+    */
+   public byte[] getRecordData()
+   {
+      return recordData;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddTXMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddTXMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationAddTXMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationAddMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationAddTXMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long txId;
+
+   private long id;
+
+   /** 0 - Bindings, 1 - MessagesJournal */
+   private byte journalID;
+
+   private boolean isUpdate;
+
+   private byte recordType;
+
+   private EncodingSupport encodingData;
+
+   private byte[] recordData;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationAddTXMessage()
+   {
+      super(REPLICATION_APPEND_TX);
+   }
+
+   public ReplicationAddTXMessage(final byte journalID,
+                                  final boolean isUpdate,
+                                  final long txId,
+                                  final long id,
+                                  final byte recordType,
+                                  final EncodingSupport encodingData)
+   {
+      this();
+      this.journalID = journalID;
+      this.isUpdate = isUpdate;
+      this.txId = txId;
+      this.id = id;
+      this.recordType = recordType;
+      this.encodingData = encodingData;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_BYTE +
+             DataConstants.SIZE_BOOLEAN +
+             DataConstants.SIZE_LONG +
+             DataConstants.SIZE_LONG +
+             DataConstants.SIZE_BYTE +
+             DataConstants.SIZE_INT +
+             (encodingData != null ? encodingData.getEncodeSize() : recordData.length);
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeByte(journalID);
+      buffer.writeBoolean(isUpdate);
+      buffer.writeLong(txId);
+      buffer.writeLong(id);
+      buffer.writeByte(recordType);
+      buffer.writeInt(encodingData.getEncodeSize());
+      encodingData.encode(buffer);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      journalID = buffer.readByte();
+      isUpdate = buffer.readBoolean();
+      txId = buffer.readLong();
+      id = buffer.readLong();
+      recordType = buffer.readByte();
+      int size = buffer.readInt();
+      recordData = new byte[size];
+      buffer.readBytes(recordData);
+   }
+
+   /**
+    * @return the id
+    */
+   public long getId()
+   {
+      return id;
+   }
+
+   public long getTxId()
+   {
+      return txId;
+   }
+
+   /**
+    * @return the journalID
+    */
+   public byte getJournalID()
+   {
+      return journalID;
+   }
+
+   public boolean isUpdate()
+   {
+      return isUpdate;
+   }
+
+   /**
+    * @return the recordType
+    */
+   public byte getRecordType()
+   {
+      return recordType;
+   }
+
+   /**
+    * @return the recordData
+    */
+   public byte[] getRecordData()
+   {
+      return recordData;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationCommitMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationCommitMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationCommitMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationAddMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationCommitMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   /** 0 - Bindings, 1 - MessagesJournal */
+   private byte journalID;
+
+   private boolean rollback;
+
+   private long txId;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationCommitMessage()
+   {
+      super(REPLICATION_COMMIT_ROLLBACK);
+   }
+
+   public ReplicationCommitMessage(final byte journalID, final boolean rollback, final long txId)
+   {
+      this();
+      this.journalID = journalID;
+      this.rollback = rollback;
+      this.txId = txId;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_BYTE + DataConstants.SIZE_BOOLEAN + DataConstants.SIZE_LONG;
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeByte(journalID);
+      buffer.writeBoolean(rollback);
+      buffer.writeLong(txId);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      journalID = buffer.readByte();
+      rollback = buffer.readBoolean();
+      txId = buffer.readLong();
+   }
+
+   public boolean isRollback()
+   {
+      return rollback;
+   }
+
+   public long getTxId()
+   {
+      return txId;
+   }
+
+   /**
+    * @return the journalID
+    */
+   public byte getJournalID()
+   {
+      return journalID;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationAddMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationDeleteMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long id;
+
+   /** 0 - Bindings, 1 - MessagesJournal */
+   private byte journalID;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationDeleteMessage()
+   {
+      super(REPLICATION_DELETE);
+   }
+
+   public ReplicationDeleteMessage(final byte journalID, final long id)
+   {
+      this();
+      this.journalID = journalID;
+      this.id = id;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeByte(journalID);
+      buffer.writeLong(id);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      journalID = buffer.readByte();
+      id = buffer.readLong();
+   }
+
+   /**
+    * @return the id
+    */
+   public long getId()
+   {
+      return id;
+   }
+
+   /**
+    * @return the journalID
+    */
+   public byte getJournalID()
+   {
+      return journalID;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteTXMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteTXMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationDeleteTXMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationAddMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationDeleteTXMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long txId;
+
+   private long id;
+
+   /** 0 - Bindings, 1 - MessagesJournal */
+   private byte journalID;
+
+   private EncodingSupport encodingData;
+
+   private byte[] recordData;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationDeleteTXMessage()
+   {
+      super(REPLICATION_DELETE_TX);
+   }
+
+   public ReplicationDeleteTXMessage(final byte journalID,
+                                     final long txId,
+                                     final long id,
+                                     final EncodingSupport encodingData)
+   {
+      this();
+      this.journalID = journalID;
+      this.txId = txId;
+      this.id = id;
+      this.encodingData = encodingData;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_BYTE +
+             DataConstants.SIZE_LONG +
+             DataConstants.SIZE_LONG +
+             DataConstants.SIZE_INT +
+             (encodingData != null ? encodingData.getEncodeSize() : recordData.length);
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeByte(journalID);
+      buffer.writeLong(txId);
+      buffer.writeLong(id);
+      buffer.writeInt(encodingData.getEncodeSize());
+      encodingData.encode(buffer);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      journalID = buffer.readByte();
+      txId = buffer.readLong();
+      id = buffer.readLong();
+      int size = buffer.readInt();
+      recordData = new byte[size];
+      buffer.readBytes(recordData);
+   }
+
+   /**
+    * @return the id
+    */
+   public long getId()
+   {
+      return id;
+   }
+
+   public long getTxId()
+   {
+      return txId;
+   }
+
+   /**
+    * @return the journalID
+    */
+   public byte getJournalID()
+   {
+      return journalID;
+   }
+
+   /**
+    * @return the recordData
+    */
+   public byte[] getRecordData()
+   {
+      return recordData;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageBeingMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageBeingMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageBeingMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationLargeMessageBeingMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationLargeMessageBeingMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   long messageId;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationLargeMessageBeingMessage(final long messageId)
+   {
+      this();
+      this.messageId = messageId;
+   }
+
+   public ReplicationLargeMessageBeingMessage()
+   {
+      super(REPLICATION_LARGE_MESSAGE_BEGIN);
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_LONG;
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeLong(messageId);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      this.messageId = buffer.readLong();
+   }
+
+   /**
+    * @return the messageId
+    */
+   public long getMessageId()
+   {
+      return messageId;
+   }
+
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageWriteMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageWriteMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargeMessageWriteMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationLargeMessageWriteMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationLargeMessageWriteMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long messageId;
+
+   private byte body[];
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+   public ReplicationLargeMessageWriteMessage()
+   {
+      super(REPLICATION_LARGE_MESSAGE_WRITE);
+   }
+
+   /**
+    * @param messageId
+    * @param body
+    */
+   public ReplicationLargeMessageWriteMessage(final long messageId, final byte[] body)
+   {
+      this();
+
+      this.messageId = messageId;
+      this.body = body;
+   }
+
+   // Public --------------------------------------------------------
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_LONG + DataConstants.SIZE_INT + body.length;
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeLong(messageId);
+      buffer.writeInt(body.length);
+      buffer.writeBytes(body);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      messageId = buffer.readLong();
+      int size = buffer.readInt();
+      body = new byte[size];
+      buffer.readBytes(body);
+   }
+
+   /**
+    * @return the messageId
+    */
+   public long getMessageId()
+   {
+      return messageId;
+   }
+
+   /**
+    * @return the body
+    */
+   public byte[] getBody()
+   {
+      return body;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargemessageEndMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargemessageEndMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationLargemessageEndMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationLargemessageEndMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationLargemessageEndMessage extends PacketImpl
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   long messageId;
+
+   boolean isDelete;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationLargemessageEndMessage()
+   {
+      super(REPLICATION_LARGE_MESSAGE_END);
+   }
+
+   public ReplicationLargemessageEndMessage(final long messageId, final boolean isDelete)
+   {
+      this();
+      this.messageId = messageId;
+      this.isDelete = isDelete;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_LONG + DataConstants.SIZE_BOOLEAN;
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeLong(messageId);
+      buffer.writeBoolean(isDelete);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      messageId = buffer.readLong();
+      isDelete = buffer.readBoolean();
+   }
+
+   /**
+    * @return the messageId
+    */
+   public long getMessageId()
+   {
+      return messageId;
+   }
+
+   /**
+    * @return the isDelete
+    */
+   public boolean isDelete()
+   {
+      return isDelete;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageEventMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageEventMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageEventMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+import org.hornetq.utils.SimpleString;
+
+/**
+ * A ReplicationPageWrite
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationPageEventMessage extends PacketImpl
+{
+
+   private int pageNumber;
+
+   private SimpleString storeName;
+
+   /**
+    * True = delete page, False = close page
+    */
+   private boolean isDelete;
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationPageEventMessage()
+   {
+      super(REPLICATION_PAGE_EVENT);
+   }
+
+   public ReplicationPageEventMessage(final SimpleString storeName, final int pageNumber, final boolean isDelete)
+   {
+      this();
+      this.pageNumber = pageNumber;
+      this.isDelete = isDelete;
+      this.storeName = storeName;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_INT + storeName.sizeof() + DataConstants.SIZE_BOOLEAN;
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeSimpleString(storeName);
+      buffer.writeInt(pageNumber);
+      buffer.writeBoolean(isDelete);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      storeName = buffer.readSimpleString();
+      pageNumber = buffer.readInt();
+      isDelete = buffer.readBoolean();
+   }
+
+   /**
+    * @return the pageNumber
+    */
+   public int getPageNumber()
+   {
+      return pageNumber;
+   }
+
+   /**
+    * @return the storeName
+    */
+   public SimpleString getStoreName()
+   {
+      return storeName;
+   }
+
+   /**
+    * @return the isDelete
+    */
+   public boolean isDelete()
+   {
+      return isDelete;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageWriteMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageWriteMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPageWriteMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.impl.PagedMessageImpl;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationPageWrite
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationPageWriteMessage extends PacketImpl
+{
+
+   int pageNumber;
+
+   PagedMessage pagedMessage;
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationPageWriteMessage()
+   {
+      super(REPLICATION_PAGE_WRITE);
+   }
+
+   public ReplicationPageWriteMessage(final PagedMessage pagedMessage, final int pageNumber)
+   {
+      this();
+      this.pageNumber = pageNumber;
+      this.pagedMessage = pagedMessage;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_INT + pagedMessage.getEncodeSize();
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeInt(pageNumber);
+      pagedMessage.encode(buffer);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      pageNumber = buffer.readInt();
+      pagedMessage = new PagedMessageImpl();
+      pagedMessage.decode(buffer);
+   }
+
+   /**
+    * @return the pageNumber
+    */
+   public int getPageNumber()
+   {
+      return pageNumber;
+   }
+
+   /**
+    * @return the pagedMessage
+    */
+   public PagedMessage getPagedMessage()
+   {
+      return pagedMessage;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPrepareMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPrepareMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationPrepareMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.utils.DataConstants;
+
+/**
+ * A ReplicationAddMessage
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationPrepareMessage extends PacketImpl
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private long txId;
+
+   /** 0 - Bindings, 1 - MessagesJournal */
+   private byte journalID;
+
+   private EncodingSupport encodingData;
+
+   private byte[] recordData;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationPrepareMessage()
+   {
+      super(REPLICATION_PREPARE);
+   }
+
+   public ReplicationPrepareMessage(final byte journalID, final long txId, final EncodingSupport encodingData)
+   {
+      this();
+      this.journalID = journalID;
+      this.txId = txId;
+      this.encodingData = encodingData;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_BYTE +
+             DataConstants.SIZE_LONG +
+             DataConstants.SIZE_INT +
+             (encodingData != null ? encodingData.getEncodeSize() : recordData.length);
+
+   }
+
+   @Override
+   public void encodeBody(final HornetQBuffer buffer)
+   {
+      buffer.writeByte(journalID);
+      buffer.writeLong(txId);
+      buffer.writeInt(encodingData.getEncodeSize());
+      encodingData.encode(buffer);
+   }
+
+   @Override
+   public void decodeBody(final HornetQBuffer buffer)
+   {
+      journalID = buffer.readByte();
+      txId = buffer.readLong();
+      int size = buffer.readInt();
+      recordData = new byte[size];
+      buffer.readBytes(recordData);
+   }
+
+   public long getTxId()
+   {
+      return txId;
+   }
+
+   /**
+    * @return the journalID
+    */
+   public byte getJournalID()
+   {
+      return journalID;
+   }
+
+   /**
+    * @return the recordData
+    */
+   public byte[] getRecordData()
+   {
+      return recordData;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationResponseMessage.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationResponseMessage.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/remoting/impl/wireformat/ReplicationResponseMessage.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.remoting.impl.wireformat;
+
+/**
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision$</tt>
+ */
+public class ReplicationResponseMessage extends PacketImpl
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationResponseMessage()
+   {
+      super(REPLICATION_RESPONSE);
+   }
+
+   // Public --------------------------------------------------------
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.remoting.Packet#getRequiredBufferSize()
+    */
+   @Override
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}

Modified: trunk/src/main/org/hornetq/core/remoting/server/impl/RemotingServiceImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/remoting/server/impl/RemotingServiceImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/remoting/server/impl/RemotingServiceImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -83,7 +83,7 @@
 
    private final Configuration config;
 
-   private volatile HornetQServer server;
+   private final HornetQServer server;
 
    private ManagementService managementService;
 
@@ -107,6 +107,8 @@
    {
       transportConfigs = config.getAcceptorConfigurations();
 
+      this.server = server;
+
       ClassLoader loader = Thread.currentThread().getContextClassLoader();
       for (String interceptorClass : config.getInterceptorClassNames())
       {
@@ -122,7 +124,6 @@
       }
 
       this.config = config;
-      this.server = server;
       this.managementService = managementService;
       this.threadPool = threadPool;
       this.scheduledThreadPool = scheduledThreadPool;
@@ -240,7 +241,10 @@
 
       connections.clear();
 
-      managementService.unregisterAcceptors();
+      if (managementService != null)
+      {
+         managementService.unregisterAcceptors();
+      }
 
       started = false;
    }
@@ -297,11 +301,14 @@
                                                                                                                       : null);
 
       Channel channel1 = rc.getChannel(1, -1, false);
+      
+      ChannelHandler handler = createHandler(rc, channel1); 
 
-      ChannelHandler handler = new HornetQPacketHandler(server, channel1, rc);
-
       channel1.setHandler(handler);
 
+
+      
+
       long ttl = ClientSessionFactoryImpl.DEFAULT_CONNECTION_TTL;
       if (config.getConnectionTTLOverride() != -1)
       {
@@ -386,6 +393,14 @@
 
    // Protected -----------------------------------------------------
 
+   /**
+    * Subclasses (on tests) may use this to create a different channel.
+    */
+   protected ChannelHandler createHandler(final RemotingConnection rc, Channel channel)
+   {
+      return new HornetQPacketHandler(server, channel, rc);
+   }
+
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------

Added: trunk/src/main/org/hornetq/core/replication/ReplicationContext.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/ReplicationContext.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/ReplicationContext.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication;
+
+
+/**
+ * This represents a set of operations done as part of replication. 
+ * When the entire set is done a group of Runnables can be executed.
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public interface ReplicationContext
+{
+   /** To be called by the replication manager, when new replication is added to the queue */
+   void linedUp();
+
+   /** To be called by the replication manager, when data is confirmed on the channel */
+   void replicated();
+   
+   void addReplicationAction(Runnable runnable);
+   
+   /** To be called when there are no more operations pending */
+   void complete();
+
+}

Added: trunk/src/main/org/hornetq/core/replication/ReplicationEndpoint.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/ReplicationEndpoint.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/ReplicationEndpoint.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication;
+
+import org.hornetq.core.remoting.Channel;
+import org.hornetq.core.remoting.ChannelHandler;
+import org.hornetq.core.server.HornetQComponent;
+
+/**
+ * A ReplicationEndpoint
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public interface ReplicationEndpoint extends ChannelHandler, HornetQComponent
+{
+
+   void setChannel(Channel channel);
+
+   Channel getChannel();
+
+}

Added: trunk/src/main/org/hornetq/core/replication/ReplicationManager.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/ReplicationManager.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/ReplicationManager.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication;
+
+import java.util.Set;
+
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.server.HornetQComponent;
+import org.hornetq.utils.SimpleString;
+
+/**
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public interface ReplicationManager extends HornetQComponent
+{
+   void appendAddRecord(byte journalID, long id, byte recordType, EncodingSupport record) throws Exception;
+
+   void appendUpdateRecord(byte journalID, long id, byte recordType, EncodingSupport record) throws Exception;
+
+   void appendDeleteRecord(byte journalID, long id) throws Exception;
+
+   void appendAddRecordTransactional(byte journalID, long txID, long id, byte recordType, EncodingSupport record) throws Exception;
+
+   void appendUpdateRecordTransactional(byte journalID, long txID, long id, byte recordType, EncodingSupport record) throws Exception;
+
+   void appendDeleteRecordTransactional(byte journalID, long txID, long id, EncodingSupport record) throws Exception;
+
+   void appendDeleteRecordTransactional(byte journalID, long txID, long id) throws Exception;
+
+   void appendCommitRecord(byte journalID, long txID) throws Exception;
+
+   void appendPrepareRecord(byte journalID, long txID, EncodingSupport transactionData) throws Exception;
+
+   void appendRollbackRecord(byte journalID, long txID) throws Exception;
+   
+   /** Add an action to be executed after the pending replications */
+   void afterReplicated(Runnable runnable);
+   
+   void closeContext();
+   
+   /** A list of tokens that are still waiting for replications to be completed */
+   Set<ReplicationContext> getActiveTokens();
+
+   /**
+    * @param storeName
+    * @param pageNumber
+    */
+   void pageClosed(SimpleString storeName, int pageNumber);
+
+   /**
+    * @param storeName
+    * @param pageNumber
+    */
+   void pageDeleted(SimpleString storeName, int pageNumber);
+
+
+   /**
+    * @param storeName
+    * @param pageNumber
+    */
+   void pageWrite(PagedMessage message, int pageNumber);
+   
+   void largeMessageBegin(long messageId);
+   
+   void largeMessageWrite(long messageId, byte [] body);
+   
+   void largeMessageEnd(long messageId);
+   
+   void largeMessageDelete(long messageId);
+
+}

Added: trunk/src/main/org/hornetq/core/replication/impl/ReplicatedJournal.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/impl/ReplicatedJournal.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/impl/ReplicatedJournal.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication.impl;
+
+import java.util.List;
+
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.journal.Journal;
+import org.hornetq.core.journal.LoaderCallback;
+import org.hornetq.core.journal.PreparedTransactionInfo;
+import org.hornetq.core.journal.RecordInfo;
+import org.hornetq.core.journal.TransactionFailureCallback;
+import org.hornetq.core.journal.impl.JournalImpl.ByteArrayEncoding;
+import org.hornetq.core.logging.Logger;
+import org.hornetq.core.persistence.impl.journal.JournalStorageManager;
+import org.hornetq.core.replication.ReplicationManager;
+
+
+/**
+ * Used by the {@link JournalStorageManager} to replicate journal calls. 
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ * @see JournalStorageManager
+ *
+ */
+public class ReplicatedJournal implements Journal
+{
+
+   // Constants -----------------------------------------------------
+
+   private static final Logger log = Logger.getLogger(ReplicatedJournal.class);
+
+   // Attributes ----------------------------------------------------
+
+   private static final boolean trace = log.isTraceEnabled();
+
+   private final ReplicationManager replicationManager;
+
+   private final Journal replicatedJournal;
+
+   private final byte journalID;
+
+   public ReplicatedJournal(final byte journaID,
+                                final Journal replicatedJournal,
+                                final ReplicationManager replicationManager)
+   {
+      super();
+      journalID = journaID;
+      this.replicatedJournal = replicatedJournal;
+      this.replicationManager = replicationManager;
+   }
+
+   // Static --------------------------------------------------------
+   
+   private static void trace(String message)
+   {
+      log.trace(message);
+   }
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+   /**
+    * @param id
+    * @param recordType
+    * @param record
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendAddRecord(long, byte, byte[], boolean)
+    */
+   public void appendAddRecord(final long id, final byte recordType, final byte[] record, final boolean sync) throws Exception
+   {
+      this.appendAddRecord(id, recordType, new ByteArrayEncoding(record), sync);
+   }
+
+   /**
+    * @param id
+    * @param recordType
+    * @param record
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendAddRecord(long, byte, org.hornetq.core.journal.EncodingSupport, boolean)
+    */
+   public void appendAddRecord(final long id, final byte recordType, final EncodingSupport record, final boolean sync) throws Exception
+   {
+      if (trace)
+      {
+         trace("Append record id = " + id + " recordType = " + recordType);
+      }
+      replicationManager.appendAddRecord(journalID, id, recordType, record);
+      replicatedJournal.appendAddRecord(id, recordType, record, sync);
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @param recordType
+    * @param record
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendAddRecordTransactional(long, long, byte, byte[])
+    */
+   public void appendAddRecordTransactional(final long txID, final long id, final byte recordType, final byte[] record) throws Exception
+   {
+      this.appendAddRecordTransactional(txID, id, recordType, new ByteArrayEncoding(record));
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @param recordType
+    * @param record
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendAddRecordTransactional(long, long, byte, org.hornetq.core.journal.EncodingSupport)
+    */
+   public void appendAddRecordTransactional(final long txID,
+                                            final long id,
+                                            final byte recordType,
+                                            final EncodingSupport record) throws Exception
+   {
+      if (trace)
+      {
+         trace("Append record TXid = " + id + " recordType = " + recordType);
+      }
+      replicationManager.appendAddRecordTransactional(journalID, txID, id, recordType, record);
+      replicatedJournal.appendAddRecordTransactional(txID, id, recordType, record);
+   }
+
+   /**
+    * @param txID
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendCommitRecord(long, boolean)
+    */
+   public void appendCommitRecord(final long txID, final boolean sync) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendCommit " + txID);
+      }
+      replicationManager.appendCommitRecord(journalID, txID);
+      replicatedJournal.appendCommitRecord(txID, sync);
+   }
+
+   /**
+    * @param id
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendDeleteRecord(long, boolean)
+    */
+   public void appendDeleteRecord(final long id, final boolean sync) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendDelete " + id);
+      }
+      replicationManager.appendDeleteRecord(journalID, id);
+      replicatedJournal.appendDeleteRecord(id, sync);
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @param record
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendDeleteRecordTransactional(long, long, byte[])
+    */
+   public void appendDeleteRecordTransactional(final long txID, final long id, final byte[] record) throws Exception
+   {
+      this.appendDeleteRecordTransactional(txID, id, new ByteArrayEncoding(record));
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @param record
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendDeleteRecordTransactional(long, long, org.hornetq.core.journal.EncodingSupport)
+    */
+   public void appendDeleteRecordTransactional(final long txID, final long id, final EncodingSupport record) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendDelete txID=" + txID + " id=" + id);
+      }
+      replicationManager.appendDeleteRecordTransactional(journalID, txID, id, record);
+      replicatedJournal.appendDeleteRecordTransactional(txID, id, record);
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendDeleteRecordTransactional(long, long)
+    */
+   public void appendDeleteRecordTransactional(final long txID, final long id) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendDelete (noencoding) txID=" + txID + " id=" + id);
+      }
+      replicationManager.appendDeleteRecordTransactional(journalID, txID, id);
+      replicatedJournal.appendDeleteRecordTransactional(txID, id);
+   }
+
+   /**
+    * @param txID
+    * @param transactionData
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendPrepareRecord(long, byte[], boolean)
+    */
+   public void appendPrepareRecord(final long txID, final byte[] transactionData, final boolean sync) throws Exception
+   {
+      this.appendPrepareRecord(txID, new ByteArrayEncoding(transactionData), sync);
+   }
+
+   /**
+    * @param txID
+    * @param transactionData
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendPrepareRecord(long, org.hornetq.core.journal.EncodingSupport, boolean)
+    */
+   public void appendPrepareRecord(final long txID, final EncodingSupport transactionData, final boolean sync) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendPrepare txID=" + txID);
+      }
+      replicationManager.appendPrepareRecord(journalID, txID, transactionData);
+      replicatedJournal.appendPrepareRecord(txID, transactionData, sync);
+   }
+
+   /**
+    * @param txID
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendRollbackRecord(long, boolean)
+    */
+   public void appendRollbackRecord(final long txID, final boolean sync) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendRollback " + txID);
+      }
+      replicationManager.appendRollbackRecord(journalID, txID);
+      replicatedJournal.appendRollbackRecord(txID, sync);
+   }
+
+   /**
+    * @param id
+    * @param recordType
+    * @param record
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendUpdateRecord(long, byte, byte[], boolean)
+    */
+   public void appendUpdateRecord(final long id, final byte recordType, final byte[] record, final boolean sync) throws Exception
+   {
+      this.appendUpdateRecord(id, recordType, new ByteArrayEncoding(record), sync);
+   }
+
+   /**
+    * @param id
+    * @param recordType
+    * @param record
+    * @param sync
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendUpdateRecord(long, byte, org.hornetq.core.journal.EncodingSupport, boolean)
+    */
+   public void appendUpdateRecord(final long id, final byte recordType, final EncodingSupport record, final boolean sync) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendUpdateRecord id = " + id + " , recordType = " + recordType);
+      }
+      replicationManager.appendUpdateRecord(journalID, id, recordType, record);
+      replicatedJournal.appendUpdateRecord(id, recordType, record, sync);
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @param recordType
+    * @param record
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendUpdateRecordTransactional(long, long, byte, byte[])
+    */
+   public void appendUpdateRecordTransactional(final long txID,
+                                               final long id,
+                                               final byte recordType,
+                                               final byte[] record) throws Exception
+   {
+      this.appendUpdateRecordTransactional(txID, id, recordType, new ByteArrayEncoding(record));
+   }
+
+   /**
+    * @param txID
+    * @param id
+    * @param recordType
+    * @param record
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#appendUpdateRecordTransactional(long, long, byte, org.hornetq.core.journal.EncodingSupport)
+    */
+   public void appendUpdateRecordTransactional(final long txID,
+                                               final long id,
+                                               final byte recordType,
+                                               final EncodingSupport record) throws Exception
+   {
+      if (trace)
+      {
+         trace("AppendUpdateRecord txid=" + txID + " id = " + id + " , recordType = " + recordType);
+      }
+      replicationManager.appendUpdateRecordTransactional(journalID, txID, id, recordType, record);
+      replicatedJournal.appendUpdateRecordTransactional(txID, id, recordType, record);
+   }
+
+   /**
+    * @param committedRecords
+    * @param preparedTransactions
+    * @param transactionFailure
+    * @return
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#load(java.util.List, java.util.List, org.hornetq.core.journal.TransactionFailureCallback)
+    */
+   public long load(final List<RecordInfo> committedRecords,
+                    final List<PreparedTransactionInfo> preparedTransactions,
+                    final TransactionFailureCallback transactionFailure) throws Exception
+   {
+      return replicatedJournal.load(committedRecords, preparedTransactions, transactionFailure);
+   }
+
+   /**
+    * @param reloadManager
+    * @return
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#load(org.hornetq.core.journal.LoaderCallback)
+    */
+   public long load(final LoaderCallback reloadManager) throws Exception
+   {
+      return replicatedJournal.load(reloadManager);
+   }
+
+   /**
+    * @param pages
+    * @throws Exception
+    * @see org.hornetq.core.journal.Journal#perfBlast(int)
+    */
+   public void perfBlast(final int pages) throws Exception
+   {
+      replicatedJournal.perfBlast(pages);
+   }
+
+   /**
+    * @throws Exception
+    * @see org.hornetq.core.server.HornetQComponent#start()
+    */
+   public void start() throws Exception
+   {
+      replicatedJournal.start();
+   }
+
+   /**
+    * @throws Exception
+    * @see org.hornetq.core.server.HornetQComponent#stop()
+    */
+   public void stop() throws Exception
+   {
+      replicatedJournal.stop();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.journal.Journal#getAlignment()
+    */
+   public int getAlignment() throws Exception
+   {
+      return replicatedJournal.getAlignment();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#isStarted()
+    */
+   public boolean isStarted()
+   {
+      return replicatedJournal.isStarted();
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/replication/impl/ReplicationContextImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/impl/ReplicationContextImpl.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/impl/ReplicationContextImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication.impl;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+
+import org.hornetq.core.replication.ReplicationContext;
+
+/**
+ * A ReplicationToken
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationContextImpl implements ReplicationContext
+{
+   final Executor executor;
+   
+   private ArrayList<Runnable> tasks;
+   
+   private volatile int pendings;
+   
+   /**
+    * @param executor
+    */
+   public ReplicationContextImpl(Executor executor)
+   {
+      super();
+      this.executor = executor;
+   }
+
+   /** To be called by the replication manager, when new replication is added to the queue */
+   public synchronized void linedUp()
+   {
+      pendings++;
+   }
+
+   /** To be called by the replication manager, when data is confirmed on the channel */
+   public synchronized void replicated()
+   {
+      if (--pendings == 0)
+      {
+         if (tasks != null)
+         {
+            for (Runnable run : tasks)
+            {
+               executor.execute(run);
+            }
+            tasks.clear();
+         }
+      }
+   }
+   
+   /** You may have several actions to be done after a replication operation is completed. */
+   public synchronized void addReplicationAction(Runnable runnable)
+   {
+      if (pendings == 0)
+      {
+         executor.execute(runnable);
+      }
+      else
+      {
+         if (tasks == null)
+         {
+            tasks = new ArrayList<Runnable>();
+         }
+         
+         tasks.add(runnable);
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationToken#complete()
+    */
+   public void complete()
+   {
+      // TODO Auto-generated method stub
+      
+   }
+}

Added: trunk/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication.impl;
+
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_LARGE_MESSAGE_BEGIN;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_LARGE_MESSAGE_END;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REPLICATION_LARGE_MESSAGE_WRITE;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.hornetq.core.config.Configuration;
+import org.hornetq.core.journal.Journal;
+import org.hornetq.core.logging.Logger;
+import org.hornetq.core.paging.Page;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.impl.PagingManagerImpl;
+import org.hornetq.core.paging.impl.PagingStoreFactoryNIO;
+import org.hornetq.core.persistence.impl.journal.JournalStorageManager;
+import org.hornetq.core.remoting.Channel;
+import org.hornetq.core.remoting.Packet;
+import org.hornetq.core.remoting.impl.wireformat.PacketImpl;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationAddMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationAddTXMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationCommitMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationDeleteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationDeleteTXMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargeMessageBeingMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargeMessageWriteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargemessageEndMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPageEventMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPageWriteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPrepareMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationResponseMessage;
+import org.hornetq.core.replication.ReplicationEndpoint;
+import org.hornetq.core.server.HornetQServer;
+import org.hornetq.core.server.LargeServerMessage;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.utils.SimpleString;
+
+/**
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationEndpointImpl implements ReplicationEndpoint
+{
+
+   // Constants -----------------------------------------------------
+
+   private static final Logger log = Logger.getLogger(ReplicationEndpointImpl.class);
+
+   // Attributes ----------------------------------------------------
+
+   private static final boolean trace = log.isTraceEnabled();
+   
+   private static void trace(String msg)
+   {
+      log.trace(msg);
+   }
+
+   private final HornetQServer server;
+
+   private Channel channel;
+
+   private Journal bindingsJournal;
+
+   private Journal messagingJournal;
+
+   private JournalStorageManager storage;
+
+   private PagingManager pageManager;
+
+   private final ConcurrentMap<SimpleString, ConcurrentMap<Integer, Page>> pageIndex = new ConcurrentHashMap<SimpleString, ConcurrentMap<Integer, Page>>();
+   
+   private final ConcurrentMap<Long, LargeServerMessage> largeMessages = new ConcurrentHashMap<Long, LargeServerMessage>();
+
+   // Constructors --------------------------------------------------
+   public ReplicationEndpointImpl(final HornetQServer server)
+   {
+      this.server = server;
+   }
+
+   // Public --------------------------------------------------------
+   /* 
+    * (non-Javadoc)
+    * @see org.hornetq.core.remoting.ChannelHandler#handlePacket(org.hornetq.core.remoting.Packet)
+    */
+   public void handlePacket(final Packet packet)
+   {
+      try
+      {
+         if (packet.getType() == PacketImpl.REPLICATION_APPEND)
+         {
+            handleAppendAddRecord((ReplicationAddMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_APPEND_TX)
+         {
+            handleAppendAddTXRecord((ReplicationAddTXMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_DELETE)
+         {
+            handleAppendDelete((ReplicationDeleteMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_DELETE_TX)
+         {
+            handleAppendDeleteTX((ReplicationDeleteTXMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_PREPARE)
+         {
+            handlePrepare((ReplicationPrepareMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_COMMIT_ROLLBACK)
+         {
+            handleCommitRollback((ReplicationCommitMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_PAGE_WRITE)
+         {
+            handlePageWrite((ReplicationPageWriteMessage)packet);
+         }
+         else if (packet.getType() == PacketImpl.REPLICATION_PAGE_EVENT)
+         {
+            handlePageEvent((ReplicationPageEventMessage)packet);
+         }
+         else if (packet.getType() == REPLICATION_LARGE_MESSAGE_BEGIN)
+         {
+            handleLargeMessageBegin((ReplicationLargeMessageBeingMessage)packet);
+         }
+         else if (packet.getType() == REPLICATION_LARGE_MESSAGE_WRITE)
+         {
+            handleLargeMessageWrite((ReplicationLargeMessageWriteMessage)packet);
+         }
+         else if (packet.getType() == REPLICATION_LARGE_MESSAGE_END)
+         {
+            handleLargeMessageEnd((ReplicationLargemessageEndMessage)packet);
+         }
+         else
+         {
+            log.warn("Packet " + packet + " can't be processed by the ReplicationEndpoint");
+         }
+      }
+      catch (Exception e)
+      {
+         // TODO: what to do when the IO fails on the backup side? should we shutdown the backup?
+         log.warn(e.getMessage(), e);
+      }
+      channel.send(new ReplicationResponseMessage());
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#isStarted()
+    */
+   public boolean isStarted()
+   {
+      return true;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#start()
+    */
+   public void start() throws Exception
+   {
+      Configuration config = server.getConfiguration();
+
+      storage = new JournalStorageManager(config, server.getExecutorFactory().getExecutor());
+      storage.start();
+
+      bindingsJournal = storage.getBindingsJournal();
+      messagingJournal = storage.getMessageJournal();
+
+      // We only need to load internal structures on the backup...
+      storage.loadInternalOnly();
+
+      pageManager = new PagingManagerImpl(new PagingStoreFactoryNIO(config.getPagingDirectory(),
+                                                                    server.getExecutorFactory()),
+                                          storage,
+                                          server.getAddressSettingsRepository(),
+                                          false);
+
+      pageManager.start();
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#stop()
+    */
+   public void stop() throws Exception
+   {
+      channel.close();
+      storage.stop();
+      
+      for (ConcurrentMap<Integer, Page> map : pageIndex.values())
+      {
+         for (Page page : map.values())
+         {
+            try
+            {
+               page.close();
+            }
+            catch (Exception e)
+            {
+               log.warn("Error while closing the page on backup", e);
+            }
+         }
+      }
+      
+      pageIndex.clear();
+      
+      
+      for (LargeServerMessage largeMessage : largeMessages.values())
+      {
+         largeMessage.releaseResources();
+      }
+      
+      largeMessages.clear();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationEndpoint#getChannel()
+    */
+   public Channel getChannel()
+   {
+      return channel;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationEndpoint#setChannel(org.hornetq.core.remoting.Channel)
+    */
+   public void setChannel(final Channel channel)
+   {
+      this.channel = channel;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+   /**
+    * @param packet
+    */
+   private void handleLargeMessageEnd(ReplicationLargemessageEndMessage packet)
+   {
+      LargeServerMessage message = lookupLargeMessage(packet.getMessageId(), packet.isDelete());
+      if (message != null)
+      {
+         if (packet.isDelete())
+         {
+            try
+            {
+               message.deleteFile();
+            }
+            catch (Exception e)
+            {
+               log.warn("Error deleting large message ID = " + packet.getMessageId(), e);
+            }
+         }
+         else
+         {
+            try
+            {
+               message.setStored();
+            }
+            catch (Exception e)
+            {
+               log.warn("Error deleting large message ID = " + packet.getMessageId(), e);
+            }
+         }
+      }
+   }
+
+   /**
+    * @param packet
+    */
+   private void handleLargeMessageWrite(ReplicationLargeMessageWriteMessage packet) throws Exception
+   {
+      LargeServerMessage message = lookupLargeMessage(packet.getMessageId(), false);
+      if (message != null)
+      {
+         message.addBytes(packet.getBody());
+      }
+   }
+   
+   
+   private LargeServerMessage lookupLargeMessage(long messageId, boolean isDelete)
+   {
+      LargeServerMessage message;
+      
+      if (isDelete)
+      {
+         message = largeMessages.remove(messageId);
+      }
+      else
+      {
+         message = largeMessages.get(messageId);
+      }
+      
+      if (message == null)
+      {
+         log.warn("Large MessageID " + messageId + "  is not available on backup server. Ignoring replication message");
+      }
+      
+      return message;
+
+   }
+
+   /**
+    * @param packet
+    */
+   private void handleLargeMessageBegin(ReplicationLargeMessageBeingMessage packet)
+   {
+      LargeServerMessage largeMessage = storage.createLargeMessage();
+      largeMessage.setMessageID(packet.getMessageId());
+      trace("Receiving Large Message " + largeMessage.getMessageID() + " on backup");
+      this.largeMessages.put(largeMessage.getMessageID(), largeMessage);
+   }
+
+
+   /**
+    * @param packet
+    */
+   private void handleCommitRollback(final ReplicationCommitMessage packet) throws Exception
+   {
+      Journal journalToUse = getJournal(packet.getJournalID());
+
+      if (packet.isRollback())
+      {
+         journalToUse.appendRollbackRecord(packet.getTxId(), false);
+      }
+      else
+      {
+         journalToUse.appendCommitRecord(packet.getTxId(), false);
+      }
+   }
+
+   /**
+    * @param packet
+    */
+   private void handlePrepare(final ReplicationPrepareMessage packet) throws Exception
+   {
+      Journal journalToUse = getJournal(packet.getJournalID());
+
+      journalToUse.appendPrepareRecord(packet.getTxId(), packet.getRecordData(), false);
+   }
+
+   /**
+    * @param packet
+    */
+   private void handleAppendDeleteTX(final ReplicationDeleteTXMessage packet) throws Exception
+   {
+      Journal journalToUse = getJournal(packet.getJournalID());
+
+      journalToUse.appendDeleteRecordTransactional(packet.getTxId(), packet.getId(), packet.getRecordData());
+   }
+
+   /**
+    * @param packet
+    */
+   private void handleAppendDelete(final ReplicationDeleteMessage packet) throws Exception
+   {
+      Journal journalToUse = getJournal(packet.getJournalID());
+
+      journalToUse.appendDeleteRecord(packet.getId(), false);
+   }
+
+   /**
+    * @param packet
+    */
+   private void handleAppendAddTXRecord(final ReplicationAddTXMessage packet) throws Exception
+   {
+      Journal journalToUse = getJournal(packet.getJournalID());
+
+      if (packet.isUpdate())
+      {
+         journalToUse.appendUpdateRecordTransactional(packet.getTxId(),
+                                                      packet.getId(),
+                                                      packet.getRecordType(),
+                                                      packet.getRecordData());
+      }
+      else
+      {
+         journalToUse.appendAddRecordTransactional(packet.getTxId(),
+                                                   packet.getId(),
+                                                   packet.getRecordType(),
+                                                   packet.getRecordData());
+      }
+   }
+
+   /**
+    * @param packet
+    * @throws Exception
+    */
+   private void handleAppendAddRecord(final ReplicationAddMessage packet) throws Exception
+   {
+      Journal journalToUse = getJournal(packet.getJournalID());
+
+      if (packet.isUpdate())
+      {
+         if (trace)
+         {
+            trace("Endpoint appendUpdate id = " + packet.getId());
+         }
+         journalToUse.appendUpdateRecord(packet.getId(), packet.getRecordType(), packet.getRecordData(), false);
+      }
+      else
+      {
+         if (trace)
+         {
+            trace("Endpoint append id = " + packet.getId());
+         }
+         journalToUse.appendAddRecord(packet.getId(), packet.getRecordType(), packet.getRecordData(), false);
+      }
+   }
+
+   /**
+    * @param packet
+    */
+   private void handlePageEvent(final ReplicationPageEventMessage packet) throws Exception
+   {
+      ConcurrentMap<Integer, Page> pages = getPageMap(packet.getStoreName());
+
+      Page page = pages.remove(packet.getPageNumber());
+      
+      if (page == null)
+      {
+         page = getPage(packet.getStoreName(), packet.getPageNumber());
+      }
+      
+
+      if (page != null)
+      {
+         if (packet.isDelete())
+         {
+            page.delete();
+         }
+         else
+         {
+            page.close();
+         }
+      }
+
+   }
+
+   /**
+    * @param packet
+    */
+   private void handlePageWrite(final ReplicationPageWriteMessage packet) throws Exception
+   {
+      PagedMessage pgdMessage = packet.getPagedMessage();
+      ServerMessage msg = pgdMessage.getMessage(storage);
+      Page page = getPage(msg.getDestination(), packet.getPageNumber());
+      page.write(pgdMessage);
+   }
+
+   private ConcurrentMap<Integer, Page> getPageMap(final SimpleString storeName)
+   {
+      ConcurrentMap<Integer, Page> resultIndex = pageIndex.get(storeName);
+
+      if (resultIndex == null)
+      {
+         resultIndex = new ConcurrentHashMap<Integer, Page>();
+         ConcurrentMap<Integer, Page> mapResult = pageIndex.putIfAbsent(storeName, resultIndex);
+         if (mapResult != null)
+         {
+            resultIndex = mapResult;
+         }
+      }
+
+      return resultIndex;
+   }
+
+   private Page getPage(final SimpleString storeName, final int pageId) throws Exception
+   {
+      ConcurrentMap<Integer, Page> map = getPageMap(storeName);
+
+      Page page = map.get(pageId);
+
+      if (page == null)
+      {
+         page = newPage(pageId, storeName, map);
+      }
+
+      return page;
+   }
+
+   /**
+    * @param pageId
+    * @param map
+    * @return
+    */
+   private synchronized Page newPage(final int pageId,
+                                     final SimpleString storeName,
+                                     final ConcurrentMap<Integer, Page> map) throws Exception
+   {
+      Page page = map.get(pageId);
+
+      if (page == null)
+      {
+         page = pageManager.getPageStore(storeName).createPage(pageId);
+         page.open();
+         map.put(pageId, page);
+      }
+
+      return page;
+   }
+
+   /**
+    * @param journalID
+    * @return
+    */
+   private Journal getJournal(final byte journalID)
+   {
+      Journal journalToUse;
+      if (journalID == (byte)0)
+      {
+         journalToUse = bindingsJournal;
+      }
+      else
+      {
+         journalToUse = messagingJournal;
+      }
+      return journalToUse;
+   }
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/src/main/org/hornetq/core/replication/impl/ReplicationManagerImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/replication/impl/ReplicationManagerImpl.java	                        (rev 0)
+++ trunk/src/main/org/hornetq/core/replication/impl/ReplicationManagerImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,495 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.replication.impl;
+
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
+
+import org.hornetq.core.client.impl.FailoverManager;
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.logging.Logger;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.remoting.Channel;
+import org.hornetq.core.remoting.ChannelHandler;
+import org.hornetq.core.remoting.Packet;
+import org.hornetq.core.remoting.RemotingConnection;
+import org.hornetq.core.remoting.impl.wireformat.CreateReplicationSessionMessage;
+import org.hornetq.core.remoting.impl.wireformat.PacketImpl;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationAddMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationAddTXMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationCommitMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationDeleteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationDeleteTXMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargeMessageBeingMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargeMessageWriteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationLargemessageEndMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPageEventMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPageWriteMessage;
+import org.hornetq.core.remoting.impl.wireformat.ReplicationPrepareMessage;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.core.replication.ReplicationManager;
+import org.hornetq.core.replication.ReplicationContext;
+import org.hornetq.utils.ConcurrentHashSet;
+import org.hornetq.utils.SimpleString;
+
+/**
+ * A RepplicationManagerImpl
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationManagerImpl implements ReplicationManager
+{
+
+   // Constants -----------------------------------------------------
+   private static final Logger log = Logger.getLogger(ReplicationManagerImpl.class);
+
+   // Attributes ----------------------------------------------------
+
+   // TODO: where should this be configured?
+   private static final int WINDOW_SIZE = 1024 * 1024;
+
+   private final ResponseHandler responseHandler = new ResponseHandler();
+
+   private final FailoverManager failoverManager;
+
+   private RemotingConnection connection;
+
+   private Channel replicatingChannel;
+
+   private boolean started;
+
+   private volatile boolean enabled;
+
+   private final Object replicationLock = new Object();
+
+   private final Executor executor;
+
+   private final ThreadLocal<ReplicationContext> repliToken = new ThreadLocal<ReplicationContext>();
+
+   private final Queue<ReplicationContext> pendingTokens = new ConcurrentLinkedQueue<ReplicationContext>();
+
+   private final ConcurrentHashSet<ReplicationContext> activeTokens = new ConcurrentHashSet<ReplicationContext>();
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   /**
+    * @param replicationConnectionManager
+    */
+   public ReplicationManagerImpl(final FailoverManager failoverManager, final Executor executor)
+   {
+      super();
+      this.failoverManager = failoverManager;
+      this.executor = executor;
+   }
+
+   // Public --------------------------------------------------------
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#replicate(byte[], org.hornetq.core.replication.ReplicationToken)
+    */
+
+   public void appendAddRecord(final byte journalID, final long id, final byte recordType, final EncodingSupport record)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationAddMessage(journalID, false, id, recordType, record));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendUpdateRecord(byte, long, byte, org.hornetq.core.journal.EncodingSupport, boolean)
+    */
+   public void appendUpdateRecord(final byte journalID,
+                                  final long id,
+                                  final byte recordType,
+                                  final EncodingSupport record) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationAddMessage(journalID, true, id, recordType, record));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendDeleteRecord(byte, long, boolean)
+    */
+   public void appendDeleteRecord(final byte journalID, final long id) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationDeleteMessage(journalID, id));
+      }
+   }
+
+   public void appendAddRecordTransactional(final byte journalID,
+                                            final long txID,
+                                            final long id,
+                                            final byte recordType,
+                                            final EncodingSupport record) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationAddTXMessage(journalID, false, txID, id, recordType, record));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendUpdateRecordTransactional(byte, long, long, byte, org.hornetq.core.journal.EncodingSupport)
+    */
+   public void appendUpdateRecordTransactional(final byte journalID,
+                                               final long txID,
+                                               final long id,
+                                               final byte recordType,
+                                               final EncodingSupport record) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationAddTXMessage(journalID, true, txID, id, recordType, record));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendCommitRecord(byte, long, boolean)
+    */
+   public void appendCommitRecord(final byte journalID, final long txID) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationCommitMessage(journalID, false, txID));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendDeleteRecordTransactional(byte, long, long, org.hornetq.core.journal.EncodingSupport)
+    */
+   public void appendDeleteRecordTransactional(final byte journalID,
+                                               final long txID,
+                                               final long id,
+                                               final EncodingSupport record) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationDeleteTXMessage(journalID, txID, id, record));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendDeleteRecordTransactional(byte, long, long)
+    */
+   public void appendDeleteRecordTransactional(final byte journalID, final long txID, final long id) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationDeleteTXMessage(journalID, txID, id, NullEncoding.instance));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendPrepareRecord(byte, long, org.hornetq.core.journal.EncodingSupport, boolean)
+    */
+   public void appendPrepareRecord(final byte journalID, final long txID, final EncodingSupport transactionData) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationPrepareMessage(journalID, txID, transactionData));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#appendRollbackRecord(byte, long, boolean)
+    */
+   public void appendRollbackRecord(final byte journalID, final long txID) throws Exception
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationCommitMessage(journalID, false, txID));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#pageClosed(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageClosed(final SimpleString storeName, final int pageNumber)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationPageEventMessage(storeName, pageNumber, false));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#pageDeleted(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageDeleted(final SimpleString storeName, final int pageNumber)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationPageEventMessage(storeName, pageNumber, true));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#pageWrite(org.hornetq.utils.SimpleString, int)
+    */
+   public void pageWrite(final PagedMessage message, final int pageNumber)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationPageWriteMessage(message, pageNumber));
+      }
+   }
+   
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#largeMessageBegin(byte[])
+    */
+   public void largeMessageBegin(long messageId)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationLargeMessageBeingMessage(messageId));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#largeMessageDelete(long)
+    */
+   public void largeMessageDelete(long messageId)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationLargemessageEndMessage(messageId, true));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#largeMessageEnd(long)
+    */
+   public void largeMessageEnd(long messageId)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationLargemessageEndMessage(messageId, false));
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#largeMessageWrite(long, byte[])
+    */
+   public void largeMessageWrite(long messageId, byte[] body)
+   {
+      if (enabled)
+      {
+         sendReplicatePacket(new ReplicationLargeMessageWriteMessage(messageId, body));
+      }
+   }
+
+   
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#isStarted()
+    */
+   public synchronized boolean isStarted()
+   {
+      return started;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#start()
+    */
+   public synchronized void start() throws Exception
+   {
+      connection = failoverManager.getConnection();
+
+      long channelID = connection.generateChannelID();
+
+      Channel mainChannel = connection.getChannel(1, -1, false);
+
+      replicatingChannel = connection.getChannel(channelID, WINDOW_SIZE, false);
+
+      replicatingChannel.setHandler(responseHandler);
+
+      CreateReplicationSessionMessage replicationStartPackage = new CreateReplicationSessionMessage(channelID,
+                                                                                                    WINDOW_SIZE);
+
+      mainChannel.sendBlocking(replicationStartPackage);
+
+      started = true;
+
+      enabled = true;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.HornetQComponent#stop()
+    */
+   public void stop() throws Exception
+   {
+      if (replicatingChannel != null)
+      {
+         replicatingChannel.close();
+      }
+
+      started = false;
+
+      if (connection != null)
+      {
+         connection.destroy();
+      }
+
+      connection = null;
+   }
+
+   public ReplicationContext getContext()
+   {
+      ReplicationContext token = repliToken.get();
+      if (token == null)
+      {
+         token = new ReplicationContextImpl(executor);
+         activeTokens.add(token);
+         repliToken.set(token);
+      }
+      return token;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#addReplicationAction(java.lang.Runnable)
+    */
+   public void afterReplicated(final Runnable runnable)
+   {
+      getContext().addReplicationAction(runnable);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#completeToken()
+    */
+   public void closeContext()
+   {
+      final ReplicationContext token = repliToken.get();
+      if (token != null)
+      {
+         // Disassociate thread local
+         repliToken.set(null);
+         // Remove from pending tokens as soon as this is complete
+         token.addReplicationAction(new Runnable()
+         {
+            public void run()
+            {
+               activeTokens.remove(token);
+            }
+         });
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.replication.ReplicationManager#getPendingTokens()
+    */
+   public Set<ReplicationContext> getActiveTokens()
+   {
+      return activeTokens;
+   }
+
+   private void sendReplicatePacket(final Packet packet)
+   {
+      boolean runItNow = false;
+
+      ReplicationContext repliToken = getContext();
+      repliToken.linedUp();
+
+      synchronized (replicationLock)
+      {
+         if (!enabled)
+         {
+            // Already replicating channel failed, so just play the action now
+
+            runItNow = true;
+         }
+         else
+         {
+            pendingTokens.add(repliToken);
+
+            replicatingChannel.send(packet);
+         }
+      }
+
+      // Execute outside lock
+
+      if (runItNow)
+      {
+         repliToken.replicated();
+      }
+   }
+
+   private void replicated()
+   {
+      ReplicationContext tokenPolled = pendingTokens.poll();
+      if (tokenPolled == null)
+      {
+         // We should debug the logs if this happens
+         log.warn("Missing replication token on the stack. There is a bug on the ReplicatoinManager since this was not supposed to happen");
+      }
+      else
+      {
+         tokenPolled.replicated();
+      }
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+   protected class ResponseHandler implements ChannelHandler
+   {
+      /* (non-Javadoc)
+       * @see org.hornetq.core.remoting.ChannelHandler#handlePacket(org.hornetq.core.remoting.Packet)
+       */
+      public void handlePacket(final Packet packet)
+      {
+         if (packet.getType() == PacketImpl.REPLICATION_RESPONSE)
+         {
+            replicated();
+         }
+      }
+
+   }
+
+   private static class NullEncoding implements EncodingSupport
+   {
+
+      static NullEncoding instance = new NullEncoding();
+
+      public void decode(final HornetQBuffer buffer)
+      {
+      }
+
+      public void encode(final HornetQBuffer buffer)
+      {
+      }
+
+      public int getEncodeSize()
+      {
+         return 0;
+      }
+
+   }
+
+}

Modified: trunk/src/main/org/hornetq/core/server/HornetQServer.java
===================================================================
--- trunk/src/main/org/hornetq/core/server/HornetQServer.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/server/HornetQServer.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -19,14 +19,17 @@
 import javax.management.MBeanServer;
 
 import org.hornetq.core.config.Configuration;
+import org.hornetq.core.exception.HornetQException;
 import org.hornetq.core.management.ManagementService;
 import org.hornetq.core.management.impl.HornetQServerControlImpl;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.postoffice.PostOffice;
+import org.hornetq.core.remoting.Channel;
 import org.hornetq.core.remoting.RemotingConnection;
 import org.hornetq.core.remoting.impl.wireformat.CreateSessionResponseMessage;
 import org.hornetq.core.remoting.impl.wireformat.ReattachSessionResponseMessage;
 import org.hornetq.core.remoting.server.RemotingService;
+import org.hornetq.core.replication.ReplicationEndpoint;
 import org.hornetq.core.security.HornetQSecurityManager;
 import org.hornetq.core.security.Role;
 import org.hornetq.core.server.cluster.ClusterManager;
@@ -36,7 +39,6 @@
 import org.hornetq.core.version.Version;
 import org.hornetq.utils.ExecutorFactory;
 import org.hornetq.utils.SimpleString;
-import org.hornetq.utils.UUID;
 
 /**
  * This interface defines the internal interface of the HornetQ Server exposed to other components of the server. The
@@ -69,6 +71,8 @@
    void unregisterActivateCallback(ActivateCallback callback);
 
    ReattachSessionResponseMessage reattachSession(RemotingConnection connection, String name, int lastReceivedCommandID) throws Exception;
+   
+   ReplicationEndpoint createReplicationEndpoint(Channel channel) throws Exception;
 
    CreateSessionResponseMessage createSession(String name,
                                               long channelID,                                              

Modified: trunk/src/main/org/hornetq/core/server/cluster/impl/Redistributor.java
===================================================================
--- trunk/src/main/org/hornetq/core/server/cluster/impl/Redistributor.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/server/cluster/impl/Redistributor.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -145,18 +145,38 @@
 
       tx.commit();
 
-      count++;
-
-      if (count == batchSize)
+      
+      Runnable action = new Runnable()
       {
-         // We continue the next batch on a different thread, so as not to keep the delivery thread busy for a very
-         // long time in the case there are many messages in the queue
-         active = false;
-
-         executor.execute(new Prompter());
-
-         count = 0;
+         public void run()
+         {
+            
+            count++;
+      
+            if (count == batchSize)
+            {
+               // We continue the next batch on a different thread, so as not to keep the delivery thread busy for a very
+               // long time in the case there are many messages in the queue
+               active = false;
+      
+               
+               executor.execute(new Prompter());
+      
+               count = 0;
+            }
+            
+         }
+      };
+      
+      if (storageManager.isReplicated())
+      {
+         storageManager.afterReplicated(action);
+         storageManager.completeReplication();
       }
+      else
+      {
+         action.run();
+      }
    }
 
    private class Prompter implements Runnable

Modified: trunk/src/main/org/hornetq/core/server/impl/HornetQPacketHandler.java
===================================================================
--- trunk/src/main/org/hornetq/core/server/impl/HornetQPacketHandler.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/server/impl/HornetQPacketHandler.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -16,6 +16,7 @@
 import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATESESSION;
 import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATE_QUEUE;
 import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.REATTACH_SESSION;
+import static org.hornetq.core.remoting.impl.wireformat.PacketImpl.CREATE_REPLICATION;
 
 import org.hornetq.core.exception.HornetQException;
 import org.hornetq.core.logging.Logger;
@@ -24,9 +25,12 @@
 import org.hornetq.core.remoting.Packet;
 import org.hornetq.core.remoting.RemotingConnection;
 import org.hornetq.core.remoting.impl.wireformat.CreateQueueMessage;
+import org.hornetq.core.remoting.impl.wireformat.CreateReplicationSessionMessage;
 import org.hornetq.core.remoting.impl.wireformat.CreateSessionMessage;
 import org.hornetq.core.remoting.impl.wireformat.HornetQExceptionMessage;
+import org.hornetq.core.remoting.impl.wireformat.NullResponseMessage;
 import org.hornetq.core.remoting.impl.wireformat.ReattachSessionMessage;
+import org.hornetq.core.replication.ReplicationEndpoint;
 import org.hornetq.core.server.HornetQServer;
 
 /**
@@ -91,6 +95,16 @@
 
             break;
          }         
+         case CREATE_REPLICATION:
+         {
+            // Create queue can also be fielded here in the case of a replicated store and forward queue creation
+
+            CreateReplicationSessionMessage request = (CreateReplicationSessionMessage)packet;
+            
+            handleCreateReplication(request);
+
+            break;
+         }         
          default:
          {
             log.error("Invalid packet " + packet);
@@ -174,6 +188,38 @@
          log.error("Failed to handle create queue", e);
       }
    }
+   
+   private void handleCreateReplication(CreateReplicationSessionMessage request)
+   {
+      Packet response;
 
+      try
+      {
+         Channel channel = connection.getChannel(request.getSessionChannelID(), request.getWindowSize(), false);
+         ReplicationEndpoint endpoint = server.createReplicationEndpoint(channel);
+         channel.setHandler(endpoint);
+         response = new NullResponseMessage();
+
+      }
+      catch  (Exception e)
+      {
+         log.warn(e.getMessage(), e);
+         
+         if (e instanceof HornetQException)
+         {
+            response = new HornetQExceptionMessage((HornetQException)e);
+         }
+         else
+         {
+            response = new HornetQExceptionMessage(new HornetQException(HornetQException.INTERNAL_ERROR));
+         }
+      }
+
+      channel1.send(response);
+   }
    
+   
+
+
+   
 }
\ No newline at end of file

Modified: trunk/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -31,8 +31,12 @@
 
 import javax.management.MBeanServer;
 
+import org.hornetq.core.client.ClientSessionFactory;
+import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
 import org.hornetq.core.client.impl.FailoverManager;
+import org.hornetq.core.client.impl.FailoverManagerImpl;
 import org.hornetq.core.config.Configuration;
+import org.hornetq.core.config.TransportConfiguration;
 import org.hornetq.core.config.cluster.DivertConfiguration;
 import org.hornetq.core.config.cluster.QueueConfiguration;
 import org.hornetq.core.config.impl.ConfigurationImpl;
@@ -65,11 +69,16 @@
 import org.hornetq.core.postoffice.impl.LocalQueueBinding;
 import org.hornetq.core.postoffice.impl.PostOfficeImpl;
 import org.hornetq.core.remoting.Channel;
+import org.hornetq.core.remoting.Interceptor;
 import org.hornetq.core.remoting.RemotingConnection;
 import org.hornetq.core.remoting.impl.wireformat.CreateSessionResponseMessage;
 import org.hornetq.core.remoting.impl.wireformat.ReattachSessionResponseMessage;
 import org.hornetq.core.remoting.server.RemotingService;
 import org.hornetq.core.remoting.server.impl.RemotingServiceImpl;
+import org.hornetq.core.replication.ReplicationEndpoint;
+import org.hornetq.core.replication.ReplicationManager;
+import org.hornetq.core.replication.impl.ReplicationEndpointImpl;
+import org.hornetq.core.replication.impl.ReplicationManagerImpl;
 import org.hornetq.core.security.CheckType;
 import org.hornetq.core.security.HornetQSecurityManager;
 import org.hornetq.core.security.Role;
@@ -182,7 +191,11 @@
 
    private boolean initialised;
 
-   private FailoverManager replicatingFailoverManager;
+   private FailoverManager replicationFailoverManager;
+   
+   private ReplicationManager replicationManager;
+   
+   private ReplicationEndpoint replicationEndpoint;
 
    private final Set<ActivateCallback> activateCallbacks = new HashSet<ActivateCallback>();
 
@@ -338,6 +351,12 @@
       {
          storageManager.stop();
       }
+      
+      if (replicationEndpoint != null)
+      {
+         replicationEndpoint.stop();
+         replicationEndpoint = null;
+      }
 
       if (securityManager != null)
       {
@@ -584,6 +603,24 @@
 
       return new CreateSessionResponseMessage(version.getIncrementingVersion());
    }
+   
+   public synchronized ReplicationEndpoint createReplicationEndpoint(final Channel channel) throws Exception
+   {
+      if (!configuration.isBackup())
+      {
+         throw new HornetQException(HornetQException.ILLEGAL_STATE, "Connected server is not a backup server");
+      }
+      
+      if (replicationEndpoint == null)
+      {
+         replicationEndpoint = new ReplicationEndpointImpl(this);
+         replicationEndpoint.setChannel(channel);
+         replicationEndpoint.start();
+      }
+      
+      
+      return replicationEndpoint;
+   }
 
    public void removeSession(final String name) throws Exception
    {
@@ -659,83 +696,45 @@
    // }
    // }
 
-   // private boolean setupReplicatingConnection() throws Exception
-   // {
-   // String backupConnectorName = configuration.getBackupConnectorName();
-   //
-   // if (backupConnectorName != null)
-   // {
-   // TransportConfiguration backupConnector = configuration.getConnectorConfigurations().get(backupConnectorName);
-   //
-   // if (backupConnector == null)
-   // {
-   // log.warn("connector with name '" + backupConnectorName + "' is not defined in the configuration.");
-   // }
-   // else
-   // {
-   // replicatingConnectionManager = new ConnectionManagerImpl(null,
-   // backupConnector,
-   // null,
-   // false,
-   // 1,
-   // ClientSessionFactoryImpl.DEFAULT_CALL_TIMEOUT,
-   // ClientSessionFactoryImpl.DEFAULT_CLIENT_FAILURE_CHECK_PERIOD,
-   // ClientSessionFactoryImpl.DEFAULT_CONNECTION_TTL,
-   // 0,
-   // 1.0d,
-   // 0,
-   // threadPool,
-   // scheduledPool);
-   //
-   // replicatingConnection = replicatingConnectionManager.getConnection(1);
-   //
-   // if (replicatingConnection != null)
-   // {
-   // replicatingChannel = replicatingConnection.getChannel(2, -1, false);
-   //
-   // replicatingConnection.addFailureListener(new FailureListener()
-   // {
-   // public void connectionFailed(HornetQException me)
-   // {
-   // replicatingChannel.executeOutstandingDelayedResults();
-   // }
-   // });
-   //
-   // // First time we get channel we send a message down it informing the backup of our node id -
-   // // backup and live must have the same node id
-   //
-   // Packet packet = new ReplicateStartupInfoMessage(uuid, storageManager.getCurrentUniqueID());
-   //
-   // final Future future = new Future();
-   //
-   // replicatingChannel.replicatePacket(packet, 1, new Runnable()
-   // {
-   // public void run()
-   // {
-   // future.run();
-   // }
-   // });
-   //
-   // // This may take a while especially if the journal is large
-   // boolean ok = future.await(60000);
-   //
-   // if (!ok)
-   // {
-   // throw new IllegalStateException("Timed out waiting for response from backup for initialisation");
-   // }
-   // }
-   // else
-   // {
-   // log.warn("Backup server MUST be started before live server. Initialisation will not proceed.");
-   //
-   // return false;
-   // }
-   // }
-   // }
-   //
-   // return true;
-   // }
+   private boolean startReplication() throws Exception
+   {
+      String backupConnectorName = configuration.getBackupConnectorName();
 
+      if (backupConnectorName != null)
+      {
+         TransportConfiguration backupConnector = configuration.getConnectorConfigurations().get(backupConnectorName);
+
+         if (backupConnector == null)
+         {
+            log.warn("connector with name '" + backupConnectorName + "' is not defined in the configuration.");
+         }
+         else
+         {
+            
+            replicationFailoverManager = new FailoverManagerImpl((ClientSessionFactory)null,
+                                                          backupConnector,
+                                                          null,
+                                                          false,
+                                                          ClientSessionFactoryImpl.DEFAULT_CALL_TIMEOUT,
+                                                          ClientSessionFactoryImpl.DEFAULT_CLIENT_FAILURE_CHECK_PERIOD,
+                                                          ClientSessionFactoryImpl.DEFAULT_CONNECTION_TTL,
+                                                          0,
+                                                          1.0d,
+                                                          0,
+                                                          1,
+                                                          threadPool,
+                                                          scheduledPool,
+                                                          null);
+  
+            
+            this.replicationManager = new ReplicationManagerImpl(replicationFailoverManager, this.executorFactory.getExecutor());
+            replicationManager.start();
+         }
+      }
+
+      return true;
+   }
+
    public HornetQServerControlImpl getHornetQServerControl()
    {
       return messagingServerControl;
@@ -864,7 +863,7 @@
    {
       if (configuration.isPersistenceEnabled())
       {
-         return new JournalStorageManager(configuration, threadPool);
+         return new JournalStorageManager(configuration, threadPool, replicationManager);
       }
       else
       {
@@ -889,19 +888,24 @@
       {
          // Handle backup server activation
 
-         if (configuration.isSharedStore())
+         if (!configuration.isSharedStore())
          {
-            // Complete the startup procedure
+            if (replicationEndpoint == null)
+            {
+               log.warn("There is no replication endpoint, can't activate this backup server");
+               throw new HornetQException(HornetQException.INTERNAL_ERROR, "Can't activate the server");
+            }
+            
+            replicationEndpoint.stop();
+         }
+         
+         // Complete the startup procedure
 
-            configuration.setBackup(false);
+         log.info("Activating server");
 
-            initialisePart2();
-         }
-         else
-         {
-            // TODO
-            // just load journal
-         }
+         configuration.setBackup(false);
+
+         initialisePart2();
       }
 
       return true;
@@ -960,6 +964,9 @@
          deploymentManager = new FileDeploymentManager(configuration.getFileDeployerScanPeriod());
       }
 
+      
+      startReplication();
+
       this.storageManager = createStorageManager();
 
       securityRepository = new HierarchicalObjectRepository<Set<Role>>();

Modified: trunk/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -161,7 +161,6 @@
    private final SimpleString managementAddress;
 
    // The current currentLargeMessage being processed
-   // In case of replication, currentLargeMessage should only be accessed within the replication callbacks
    private volatile LargeServerMessage currentLargeMessage;
 
    private ServerSessionPacketHandler handler;
@@ -414,9 +413,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleCreateQueue(final CreateQueueMessage packet)
@@ -489,9 +486,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleDeleteQueue(final SessionDeleteQueueMessage packet)
@@ -527,9 +522,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleExecuteQueueQuery(final SessionQueueQueryMessage packet)
@@ -584,9 +577,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleExecuteBindingQuery(final SessionBindingQueryMessage packet)
@@ -630,9 +621,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
    
    public void handleForceConsumerDelivery(SessionForceConsumerDelivery message)
@@ -681,12 +670,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      if (response != null)
-      {
-         channel.send(response);
-      }
+      sendResponse(packet, response, false, false);
    }
 
    public void handleExpired(final SessionExpiredMessage packet)
@@ -705,7 +689,8 @@
          log.error("Failed to acknowledge", e);
       }
 
-      channel.confirm(packet);
+
+      sendResponse(packet, null, false, false);
    }
 
    public void handleCommit(final Packet packet)
@@ -736,9 +721,7 @@
          tx = new TransactionImpl(storageManager);
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleRollback(final RollbackMessage packet)
@@ -765,9 +748,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXACommit(final SessionXACommitMessage packet)
@@ -839,9 +820,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXAEnd(final SessionXAEndMessage packet)
@@ -913,9 +892,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXAForget(final SessionXAForgetMessage packet)
@@ -940,9 +917,7 @@
       
       Packet response = new SessionXAResponseMessage((code != XAResource.XA_OK), code, null);
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXAJoin(final SessionXAJoinMessage packet)
@@ -991,9 +966,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXAResume(final SessionXAResumeMessage packet)
@@ -1053,9 +1026,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXARollback(final SessionXARollbackMessage packet)
@@ -1127,9 +1098,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXAStart(final SessionXAStartMessage packet)
@@ -1178,9 +1147,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXASuspend(final Packet packet)
@@ -1227,9 +1194,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleXAPrepare(final SessionXAPrepareMessage packet)
@@ -1287,9 +1252,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleGetInDoubtXids(final Packet packet)
@@ -1300,34 +1263,28 @@
       indoubtsXids.addAll(resourceManager.getHeuristicRolledbackTransactions());
       Packet response = new SessionXAGetInDoubtXidsResponseMessage(indoubtsXids);
       
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleGetXATimeout(final Packet packet)
    {
       Packet response = new SessionXAGetTimeoutResponseMessage(resourceManager.getTimeoutSeconds());
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleSetXATimeout(final SessionXASetTimeoutMessage packet)
    {
       Packet response = new SessionXASetTimeoutResponseMessage(resourceManager.setTimeoutSeconds(packet.getTimeoutSeconds()));
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleStart(final Packet packet)
    {
       setStarted(true);
 
-      channel.confirm(packet);
+      sendResponse(packet, null, false, false);
    }
 
    public void handleStop(final Packet packet)
@@ -1336,9 +1293,7 @@
 
       setStarted(false);
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleClose(final Packet packet)
@@ -1365,14 +1320,8 @@
          }
       }
 
-      channel.confirm(packet);
+      sendResponse(packet, response, true, true);
 
-      // We flush the confirmations to make sure any send confirmations get handled on the client side
-      channel.flushConfirmations();
-
-      channel.send(response);
-
-      channel.close();
    }
 
    public void handleCloseConsumer(final SessionConsumerCloseMessage packet)
@@ -1408,9 +1357,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      channel.send(response);
+      sendResponse(packet, response, false, false);
    }
 
    public void handleReceiveConsumerCredits(final SessionConsumerFlowCreditMessage packet)
@@ -1432,14 +1379,17 @@
          log.error("Failed to receive credits " + this.server.getConfiguration().isBackup(), e);
       }
 
-      channel.confirm(packet);
+
+      sendResponse(packet, null, false, false);
    }
 
    public void handleSendLargeMessage(final SessionSendLargeMessage packet)
    {
       // need to create the LargeMessage before continue
-      final LargeServerMessage msg = doCreateLargeMessage(packet);
+      long id = storageManager.generateUniqueID();
 
+      final LargeServerMessage msg = doCreateLargeMessage(id, packet);
+
       if (msg == null)
       {
          // packet logged an error, and played with channel.returns... and nothing needs to be done now
@@ -1456,18 +1406,7 @@
 
       currentLargeMessage = msg;
 
-      try
-      {
-         long id = storageManager.generateUniqueID();
-
-         currentLargeMessage.setMessageID(id);
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to send message", e);
-      }
-
-      channel.confirm(packet);
+      sendResponse(packet, null, false, false);
    }
 
    public void handleSend(final SessionSendMessage packet)
@@ -1514,13 +1453,8 @@
             }
          }
       }
-
-      channel.confirm(packet);
-
-      if (response != null)
-      {
-         channel.send(response);
-      }
+      
+      sendResponse(packet, response, false, false);
    }
 
    public void handleSendContinuations(final SessionSendContinuationMessage packet)
@@ -1569,12 +1503,7 @@
          }
       }
 
-      channel.confirm(packet);
-
-      if (response != null)
-      {
-         channel.send(response);
-      }
+      sendResponse(packet, response, false, false);
    }
 
    public int transferConnection(final RemotingConnection newConnection, final int lastReceivedCommandID)
@@ -1682,6 +1611,63 @@
    // Private
    // ----------------------------------------------------------------------------
 
+   /**
+    * Respond to client after replication
+    * @param packet
+    * @param response
+    */
+   private void sendResponse(final Packet confirmPacket, final Packet response, final boolean flush, final boolean closeChannel)
+   {
+      if (storageManager.isReplicated())
+      {
+         storageManager.afterReplicated(new Runnable()
+         {
+            public void run()
+            {
+               doSendResponse(confirmPacket, response, flush, closeChannel);
+            }
+
+         });
+         storageManager.completeReplication();
+      }
+      else
+      {
+         doSendResponse(confirmPacket, response, flush, closeChannel);
+      }
+   }
+   
+   /**
+    * @param confirmPacket
+    * @param response
+    * @param flush
+    * @param closeChannel
+    */
+   private void doSendResponse(final Packet confirmPacket,
+                               final Packet response,
+                               final boolean flush,
+                               final boolean closeChannel)
+   {
+      if (confirmPacket != null)
+      {
+         channel.confirm(confirmPacket);
+         if (flush)
+         {
+            channel.flushConfirmations();
+         }
+      }
+
+      if (response != null)
+      {
+         channel.send(response);
+      }
+      
+      if (closeChannel)
+      {
+         channel.close();
+      }
+   }
+
+
    private void setStarted(final boolean s)
    {
       Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values());
@@ -1700,11 +1686,11 @@
     * @param packet
     * @throws Exception
     */
-   private LargeServerMessage doCreateLargeMessage(final SessionSendLargeMessage packet)
+   private LargeServerMessage doCreateLargeMessage(long id, final SessionSendLargeMessage packet)
    {
       try
       {
-         return createLargeMessageStorage(packet.getLargeMessageHeader());
+         return createLargeMessageStorage(id, packet.getLargeMessageHeader());
       }
       catch (Exception e)
       {
@@ -1747,15 +1733,9 @@
       }
    }
 
-   private LargeServerMessage createLargeMessageStorage(final byte[] header) throws Exception
+   private LargeServerMessage createLargeMessageStorage(final long id, final byte[] header) throws Exception
    {
-      LargeServerMessage largeMessage = storageManager.createLargeMessage();
-
-      HornetQBuffer headerBuffer = ChannelBuffers.wrappedBuffer(header);
-
-      largeMessage.decodeProperties(headerBuffer);
-
-      return largeMessage;
+      return storageManager.createLargeMessage(id, header);
    }
 
    private void doRollback(final boolean lastMessageAsDelived, final Transaction theTx) throws Exception

Modified: trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java
===================================================================
--- trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/src/main/org/hornetq/core/transaction/impl/TransactionImpl.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -206,21 +206,51 @@
                operation.beforeCommit(this);
             }
          }
+         
+         // TODO: Verify Exception handling here with Tim
+         Runnable execAfterCommit = null;
+         
+         if (operations != null)
+         {
+            execAfterCommit = new Runnable()
+            {
+               public void run()
+               {
+                  for (TransactionOperation operation : operations)
+                  {
+                     try
+                     {
+                        operation.afterCommit(TransactionImpl.this);
+                     }
+                     catch (Exception e)
+                     {
+                        log.warn(e.getMessage(), e);
+                     }
+                  }
+               }
+            };
+         }
 
          if ((getProperty(TransactionPropertyIndexes.CONTAINS_PERSISTENT) != null) || (xid != null && state == State.PREPARED))
          {
             storageManager.commit(id);
-         }
-
-         state = State.COMMITTED;
-
-         if (operations != null)
-         {
-            for (TransactionOperation operation : operations)
+            state = State.COMMITTED;
+            if (execAfterCommit != null)
             {
-               operation.afterCommit(this);
+               if (storageManager.isReplicated())
+               {
+                  storageManager.afterReplicated(execAfterCommit);
+               }
+               else
+               {
+                  execAfterCommit.run();
+               }
             }
          }
+         else if (execAfterCommit != null)
+         {
+            execAfterCommit.run();
+         }
       }
    }
 

Modified: trunk/tests/src/org/hornetq/tests/integration/client/PagingTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/client/PagingTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/client/PagingTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -17,6 +17,7 @@
 import java.util.Map;
 
 import junit.framework.AssertionFailedError;
+import junit.framework.TestSuite;
 
 import org.hornetq.core.buffers.ChannelBuffers;
 import org.hornetq.core.client.ClientConsumer;
@@ -46,7 +47,17 @@
  */
 public class PagingTest extends ServiceTestBase
 {
-
+   
+   public PagingTest(String name)
+   {
+      super(name);
+   }
+   
+   public PagingTest()
+   {
+      super();
+   }
+   
    // Constants -----------------------------------------------------
    private static final Logger log = Logger.getLogger(PagingTest.class);
 

Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/AsynchronousFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/AsynchronousFailoverTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/AsynchronousFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -406,35 +406,14 @@
    @Override
    protected TransportConfiguration getAcceptorTransportConfiguration(boolean live)
    {
-      if (live)
-      {
-         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory");
-      }
-      else
-      {
-         Map<String, Object> server1Params = new HashMap<String, Object>();
-
-         server1Params.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
-
-         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory", server1Params);
-      }
+      return getInVMTransportAcceptorConfiguration(live);
    }
 
    @Override
    protected TransportConfiguration getConnectorTransportConfiguration(final boolean live)
    {
-      if (live)
-      {
-         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMConnectorFactory");
-      }
-      else
-      {
-         Map<String, Object> server1Params = new HashMap<String, Object>();
-
-         server1Params.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
-
-         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMConnectorFactory", server1Params);
-      }
+      return getInVMConnectorTransportConfiguration(live);
    }
+   
 
 }

Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -78,6 +78,18 @@
 
    // Public --------------------------------------------------------
 
+   /**
+    * @param name
+    */
+   public FailoverTest(String name)
+   {
+      super(name);
+   }
+   
+   public FailoverTest()
+   {
+   }
+
    public void testNonTransacted() throws Exception
    {
       ClientSessionFactoryInternal sf = getSessionFactory();
@@ -109,23 +121,14 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
          producer.send(message);
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
-
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
+      fail(session, latch);
       
       log.info("got here 1");
 
@@ -143,7 +146,7 @@
 
             assertNotNull(message);
 
-            assertEquals("message" + i, message.getBody().readString());
+            assertMessageBody(i, message);
 
             assertEquals(i, message.getProperty("counter"));
 
@@ -159,6 +162,26 @@
       assertEquals(0, sf.numConnections());
    }
 
+   /**
+    * @param session
+    * @param latch
+    * @throws InterruptedException
+    */
+   private void fail(ClientSession session, final CountDownLatch latch) throws InterruptedException
+   {
+      
+      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+
+      // Simulate failure on connection
+      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
+
+      // Wait to be informed of failure
+
+      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
+
+      assertTrue(ok);
+   }
+
    public void testTransactedMessagesSentSoRollback() throws Exception
    {
       ClientSessionFactoryInternal sf = getSessionFactory();
@@ -190,24 +213,15 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
          producer.send(message);
       }
+      
+      fail(session, latch);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
-
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session.commit();
@@ -265,7 +279,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -274,17 +288,8 @@
 
       session.commit();
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       // committing again should work since didn't send anything since last commit
 
       session.commit();
@@ -303,7 +308,7 @@
 
             assertNotNull(message);
 
-            assertEquals("message" + i, message.getBody().readString());
+            assertMessageBody(i, message);
 
             assertEquals(i, message.getProperty("counter"));
 
@@ -351,7 +356,7 @@
       {
          ClientMessage message = session1.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -372,24 +377,15 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
          message.acknowledge();
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session2).getConnection();
+      fail(session2, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session2.commit();
@@ -441,7 +437,7 @@
       {
          ClientMessage message = session1.createClientMessage(true);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -462,7 +458,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -473,17 +469,8 @@
 
       consumer.close();
 
-      RemotingConnection conn = ((ClientSessionInternal)session2).getConnection();
+      fail(session2, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       consumer = session2.createConsumer(ADDRESS);
 
       for (int i = numMessages / 2; i < numMessages; i++)
@@ -492,7 +479,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -545,24 +532,15 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
          producer.send(message);
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session.end(xid, XAResource.TMSUCCESS);
@@ -624,7 +602,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -633,17 +611,8 @@
 
       session.end(xid, XAResource.TMSUCCESS);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session.prepare(xid);
@@ -706,7 +675,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -717,17 +686,8 @@
 
       session.prepare(xid);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session.commit(xid, true);
@@ -789,7 +749,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -802,17 +762,8 @@
 
       session.commit(xid, false);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       ClientConsumer consumer = session.createConsumer(ADDRESS);
 
       session.start();
@@ -831,7 +782,7 @@
 
             assertNotNull(message);
 
-            assertEquals("message" + i, message.getBody().readString());
+            assertMessageBody(i, message);
 
             assertEquals(i, message.getProperty("counter"));
 
@@ -883,7 +834,7 @@
       {
          ClientMessage message = session1.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -908,24 +859,15 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
          message.acknowledge();
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session2).getConnection();
+      fail(session2, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session2.end(xid, XAResource.TMSUCCESS);
@@ -978,7 +920,7 @@
       {
          ClientMessage message = session1.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1003,7 +945,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -1079,7 +1021,7 @@
       {
          ClientMessage message = session1.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1104,7 +1046,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -1115,17 +1057,8 @@
 
       session2.prepare(xid);
 
-      RemotingConnection conn = ((ClientSessionInternal)session2).getConnection();
+      fail(session2, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       try
       {
          session2.commit(xid, true);
@@ -1243,7 +1176,7 @@
       {
          ClientMessage message = sendSession.createClientMessage(true);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1278,7 +1211,7 @@
 
                assertNotNull(message);
 
-               assertEquals("message" + i, message.getBody().readString());
+               assertMessageBody(i, message);
 
                assertEquals(i, message.getProperty("counter"));
 
@@ -1334,7 +1267,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1351,22 +1284,13 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       for (int i = 0; i < numMessages; i++)
       {
          // Only the persistent messages will survive
@@ -1377,7 +1301,7 @@
 
             assertNotNull(message);
 
-            assertEquals("message" + i, message.getBody().readString());
+            assertMessageBody(i, message);
 
             assertEquals(i, message.getProperty("counter"));
 
@@ -1423,7 +1347,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1440,22 +1364,13 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       // Should get the same ones after failover since we didn't ack
 
       for (int i = 0; i < numMessages; i++)
@@ -1468,7 +1383,7 @@
 
             assertNotNull(message);
 
-            assertEquals("message" + i, message.getBody().readString());
+            assertMessageBody(i, message);
 
             assertEquals(i, message.getProperty("counter"));
 
@@ -1515,7 +1430,7 @@
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1532,31 +1447,22 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
          message.acknowledge();
       }
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       // Send some more
 
       for (int i = numMessages; i < numMessages * 2; i++)
       {
          ClientMessage message = session.createClientMessage(i % 2 == 0);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1571,7 +1477,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -1642,17 +1548,8 @@
 
       Thread.sleep(500);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      // Simulate failure on connection
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       sender.join();
 
       assertNotNull(sender.e);
@@ -1706,7 +1603,7 @@
             message.putStringProperty(MessageImpl.HDR_DUPLICATE_DETECTION_ID, new SimpleString(txID));
          }
          
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1759,16 +1656,8 @@
 
       Thread.sleep(500);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       committer.join();
 
       assertFalse(committer.failed);
@@ -1792,7 +1681,7 @@
             message.putStringProperty(MessageImpl.HDR_DUPLICATE_DETECTION_ID, new SimpleString(txID));
          }
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1811,7 +1700,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -1861,7 +1750,7 @@
       {
          ClientMessage message = session.createClientMessage(true);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1914,16 +1803,8 @@
 
       Thread.sleep(500);
 
-      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+      fail(session, latch);
 
-      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
-
-      // Wait to be informed of failure
-
-      boolean ok = latch.await(1000, TimeUnit.MILLISECONDS);
-
-      assertTrue(ok);
-
       committer.join();
 
       assertFalse(committer.failed);
@@ -1940,7 +1821,7 @@
       {
          ClientMessage message = session2.createClientMessage(true);
 
-         message.getBody().writeString("message" + i);
+         setBody(i, message);
 
          message.putIntProperty("counter", i);
 
@@ -1959,7 +1840,7 @@
 
          assertNotNull(message);
 
-         assertEquals("message" + i, message.getBody().readString());
+         assertMessageBody(i, message);
 
          assertEquals(i, message.getProperty("counter"));
 
@@ -2015,6 +1896,26 @@
       }
    }
 
+
+   /**
+    * @param i
+    * @param message
+    */
+   protected void assertMessageBody(int i, ClientMessage message)
+   {
+      assertEquals("message" + i, message.getBody().readString());
+   }
+
+   /**
+    * @param i
+    * @param message
+    * @throws Exception 
+    */
+   protected void setBody(int i, ClientMessage message) throws Exception
+   {
+      message.getBody().writeString("message" + i);
+   }
+
    // Private -------------------------------------------------------
 
    private ClientSession sendAndConsume(final ClientSessionFactory sf) throws Exception

Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTestBase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTestBase.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FailoverTestBase.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -13,12 +13,16 @@
 
 package org.hornetq.tests.integration.cluster.failover;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
 import org.hornetq.core.client.impl.ClientSessionFactoryInternal;
 import org.hornetq.core.config.Configuration;
 import org.hornetq.core.config.TransportConfiguration;
 import org.hornetq.core.remoting.impl.invm.InVMConnector;
 import org.hornetq.core.remoting.impl.invm.InVMRegistry;
+import org.hornetq.core.remoting.impl.invm.TransportConstants;
 import org.hornetq.core.server.HornetQServer;
 import org.hornetq.tests.util.ServiceTestBase;
 import org.hornetq.utils.SimpleString;
@@ -33,11 +37,11 @@
 public abstract class FailoverTestBase extends ServiceTestBase
 {
    // Constants -----------------------------------------------------
-   
+
    protected static final SimpleString ADDRESS = new SimpleString("FailoverTestAddress");
 
    // Attributes ----------------------------------------------------
-   
+
    protected HornetQServer server0Service;
 
    protected HornetQServer server1Service;
@@ -51,33 +55,83 @@
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
+
+   /**
+    * @param name
+    */
+   public FailoverTestBase(String name)
+   {
+      super(name);
+   }
    
+   public FailoverTestBase()
+   {
+   }
+
    protected void setUp() throws Exception
    {
       super.setUp();
+
+      createConfigs();
+
+      if (server1Service != null)
+      {
+         server1Service.start();
+      }
       
+      server0Service.start();
+   }
+
+   /**
+    * @throws Exception
+    */
+   protected void createConfigs() throws Exception
+   {
       Configuration config1 = super.createDefaultConfig();
       config1.getAcceptorConfigurations().clear();
-      config1.getAcceptorConfigurations()
-             .add(getAcceptorTransportConfiguration(false));
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
       config1.setSecurityEnabled(false);
       config1.setSharedStore(true);
       config1.setBackup(true);
+      server1Service = createServer(true, config1);
+
+      Configuration config0 = super.createDefaultConfig();
+      config0.getAcceptorConfigurations().clear();
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+      config0.setSecurityEnabled(false);
+      config0.setSharedStore(true);
+      server0Service = createServer(true, config0);
+
+   }
+
+   protected void createReplicatedConfigs() throws Exception
+   {
+      Configuration config1 = super.createDefaultConfig();
+      config1.setBindingsDirectory(config1.getBindingsDirectory() + "_backup");
+      config1.setJournalDirectory(config1.getJournalDirectory() + "_backup");
+      config1.setPagingDirectory(config1.getPagingDirectory() + "_backup");
+      config1.setLargeMessagesDirectory(config1.getLargeMessagesDirectory() + "_backup");
+      config1.getAcceptorConfigurations().clear();
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
+      config1.setSecurityEnabled(false);
+      config1.setSharedStore(false);
+      config1.setBackup(true);
       server1Service = super.createServer(true, config1);
 
       Configuration config0 = super.createDefaultConfig();
       config0.getAcceptorConfigurations().clear();
-      config0.getAcceptorConfigurations()
-             .add(getAcceptorTransportConfiguration(true));
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+
+      config0.getConnectorConfigurations().put("toBackup", getConnectorTransportConfiguration(false));
+      config0.setBackupConnectorName("toBackup");
       config0.setSecurityEnabled(false);
-      config0.setSharedStore(true);
+      config0.setSharedStore(false);
       server0Service = super.createServer(true, config0);
 
       server1Service.start();
       server0Service.start();
    }
-   
-   
+
    protected void tearDown() throws Exception
    {
       server1Service.stop();
@@ -89,19 +143,88 @@
       server1Service = null;
 
       server0Service = null;
-      
+
       InVMConnector.failOnCreateConnection = false;
 
       super.tearDown();
    }
-   
+
+   protected TransportConfiguration getInVMConnectorTransportConfiguration(final boolean live)
+   {
+      if (live)
+      {
+         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMConnectorFactory");
+      }
+      else
+      {
+         Map<String, Object> server1Params = new HashMap<String, Object>();
+
+         server1Params.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
+
+         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMConnectorFactory", server1Params);
+      }
+   }
+
+   protected TransportConfiguration getInVMTransportAcceptorConfiguration(boolean live)
+   {
+      if (live)
+      {
+         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory");
+      }
+      else
+      {
+         Map<String, Object> server1Params = new HashMap<String, Object>();
+
+         server1Params.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
+
+         return new TransportConfiguration("org.hornetq.core.remoting.impl.invm.InVMAcceptorFactory", server1Params);
+      }
+   }
+
+   protected TransportConfiguration getNettyAcceptorTransportConfiguration(boolean live)
+   {
+      if (live)
+      {
+         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyAcceptorFactory");
+      }
+      else
+      {
+         Map<String, Object> server1Params = new HashMap<String, Object>();
+
+         server1Params.put(org.hornetq.integration.transports.netty.TransportConstants.PORT_PROP_NAME,
+                           org.hornetq.integration.transports.netty.TransportConstants.DEFAULT_PORT + 1);
+
+         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyAcceptorFactory",
+                                           server1Params);
+      }
+   }
+
+   protected TransportConfiguration getNettyConnectorTransportConfiguration(final boolean live)
+   {
+      if (live)
+      {
+         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyConnectorFactory");
+      }
+      else
+      {
+         Map<String, Object> server1Params = new HashMap<String, Object>();
+
+         server1Params.put(org.hornetq.integration.transports.netty.TransportConstants.PORT_PROP_NAME,
+                           org.hornetq.integration.transports.netty.TransportConstants.DEFAULT_PORT + 1);
+
+         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyConnectorFactory",
+                                           server1Params);
+      }
+   }
+
    protected abstract TransportConfiguration getAcceptorTransportConfiguration(boolean live);
-   
+
    protected abstract TransportConfiguration getConnectorTransportConfiguration(final boolean live);
-   
+
    protected ClientSessionFactoryInternal getSessionFactory()
    {
-      return new ClientSessionFactoryImpl(getConnectorTransportConfiguration(true), getConnectorTransportConfiguration(false));
+      return new ClientSessionFactoryImpl(getConnectorTransportConfiguration(true),
+                                          getConnectorTransportConfiguration(false));
    }
 
    // Private -------------------------------------------------------

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/LargeMessageFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/LargeMessageFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/LargeMessageFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+import junit.framework.TestSuite;
+
+import org.hornetq.core.client.ClientMessage;
+import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+
+/**
+ * A LargeMessageFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class LargeMessageFailoverTest extends FailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   public static TestSuite suite()
+   {
+      TestSuite suite = new TestSuite();
+
+      suite.addTest(new LargeMessageFailoverTest("testNonTransacted"));
+      suite.addTest(new LargeMessageFailoverTest("testTransactedMessagesSentSoRollback"));
+      suite.addTest(new LargeMessageFailoverTest("testTransactedMessagesNotSentSoNoRollback"));
+      suite.addTest(new LargeMessageFailoverTest("testTransactedMessagesConsumedSoRollback"));
+      suite.addTest(new LargeMessageFailoverTest("testTransactedMessagesNotConsumedSoNoRollback"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesSentSoRollbackOnEnd"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesSentSoRollbackOnPrepare"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesSentSoRollbackOnCommit"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesNotSentSoNoRollbackOnCommit"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesConsumedSoRollbackOnEnd"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesConsumedSoRollbackOnPrepare"));
+      suite.addTest(new LargeMessageFailoverTest("testXAMessagesConsumedSoRollbackOnCommit"));
+      suite.addTest(new LargeMessageFailoverTest("testCreateNewFactoryAfterFailover"));
+
+      // Those tests are temporarily disabled for LargeMessage
+      // suite.addTest(new LargeMessageFailoverTest("testFailoverMultipleSessionsWithConsumers"));
+      // suite.addTest(new LargeMessageFailoverTest("testFailWithBrowser"));
+      // suite.addTest(new LargeMessageFailoverTest("testFailThenReceiveMoreMessagesAfterFailover"));
+      // suite.addTest(new LargeMessageFailoverTest("testFailThenReceiveMoreMessagesAfterFailover2"));
+
+      suite.addTest(new LargeMessageFailoverTest("testForceBlockingReturn"));
+      suite.addTest(new LargeMessageFailoverTest("testCommitOccurredUnblockedAndResendNoDuplicates"));
+      suite.addTest(new LargeMessageFailoverTest("testCommitDidNotOccurUnblockedAndResend"));
+      return suite;
+   }
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   /**
+    * @param name
+    */
+   public LargeMessageFailoverTest(String name)
+   {
+      super(name);
+   }
+
+   /**
+    * 
+    */
+   public LargeMessageFailoverTest()
+   {
+      super();
+   }
+
+   /**
+    * @param i
+    * @param message
+    */
+   protected void assertMessageBody(int i, ClientMessage message)
+   {
+      HornetQBuffer buffer = message.getBody();
+
+      for (int j = 0; j < ClientSessionFactoryImpl.DEFAULT_MIN_LARGE_MESSAGE_SIZE * 3; j++)
+      {
+         assertEquals(buffer.readByte(), getSamplebyte(j));
+      }
+   }
+
+   /**
+    * @param i
+    * @param message
+    */
+   protected void setBody(int i, ClientMessage message) throws Exception
+   {
+      message.setBodyInputStream(createFakeLargeStream(ClientSessionFactoryImpl.DEFAULT_MIN_LARGE_MESSAGE_SIZE * 3));
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyAsynchronousFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyAsynchronousFailoverTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyAsynchronousFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -31,34 +31,12 @@
    @Override
    protected TransportConfiguration getAcceptorTransportConfiguration(boolean live)
    {
-      if (live)
-      {
-         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyAcceptorFactory");
-      }
-      else
-      {
-         Map<String, Object> server1Params  = new HashMap<String, Object>();
-                  
-         server1Params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_PORT + 1);
-         
-         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyAcceptorFactory", server1Params);
-      }
+      return getNettyAcceptorTransportConfiguration(live);
    }
    
    @Override
    protected TransportConfiguration getConnectorTransportConfiguration(final boolean live)
    {
-      if (live)
-      {
-         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyConnectorFactory");
-      }
-      else
-      {
-         Map<String, Object> server1Params  = new HashMap<String, Object>();
-         
-         server1Params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_PORT + 1);
-         
-         return new TransportConfiguration("org.hornetq.integration.transports.netty.NettyConnectorFactory", server1Params);
-      }
+      return getNettyConnectorTransportConfiguration(live);
    }
 }

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyReplicatedFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyReplicatedFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyReplicatedFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+import org.hornetq.core.config.Configuration;
+
+/**
+ * A NettyReplicatedFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class NettyReplicatedFailoverTest extends NettyFailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   @Override
+   protected void createConfigs() throws Exception
+   {
+      Configuration config1 = super.createDefaultConfig();
+      config1.setBindingsDirectory(config1.getBindingsDirectory() + "_backup");
+      config1.setJournalDirectory(config1.getJournalDirectory() + "_backup");
+      config1.getAcceptorConfigurations().clear();
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
+      config1.setSecurityEnabled(false);
+      config1.setSharedStore(false);
+      config1.setBackup(true);
+      server1Service = super.createServer(true, config1);
+
+      Configuration config0 = super.createDefaultConfig();
+      config0.getAcceptorConfigurations().clear();
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+
+      config0.getConnectorConfigurations().put("toBackup", getConnectorTransportConfiguration(false));
+      config0.setBackupConnectorName("toBackup");
+      config0.setSecurityEnabled(false);
+      config0.setSharedStore(false);
+      server0Service = super.createServer(true, config0);
+
+      server1Service.start();
+      server0Service.start();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/PagingFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/PagingFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/PagingFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.hornetq.core.buffers.ChannelBuffers;
+import org.hornetq.core.client.ClientConsumer;
+import org.hornetq.core.client.ClientMessage;
+import org.hornetq.core.client.ClientProducer;
+import org.hornetq.core.client.ClientSession;
+import org.hornetq.core.client.impl.ClientSessionFactoryInternal;
+import org.hornetq.core.client.impl.ClientSessionInternal;
+import org.hornetq.core.config.Configuration;
+import org.hornetq.core.config.TransportConfiguration;
+import org.hornetq.core.exception.HornetQException;
+import org.hornetq.core.remoting.FailureListener;
+import org.hornetq.core.remoting.RemotingConnection;
+import org.hornetq.core.server.HornetQServer;
+import org.hornetq.core.settings.impl.AddressSettings;
+import org.hornetq.utils.SimpleString;
+
+/**
+ * A PagingFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class PagingFailoverTest extends FailoverTestBase
+{
+
+   // Constants -----------------------------------------------------
+
+   private static final int PAGE_MAX = 100 * 1024;
+
+   private static final int PAGE_SIZE = 10 * 1024;
+
+   static final SimpleString ADDRESS = new SimpleString("SimpleAddress");
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   public void testPage() throws Exception
+   {
+      internalTestPagedTransacted(false, false);
+   }
+   
+
+   public void testPageTransactioned() throws Exception
+   {
+      internalTestPagedTransacted(true, false);
+   }
+   
+   public void testPageTransactionedFailBeforeconsume() throws Exception
+   {
+      internalTestPagedTransacted(true, true);
+   }
+   
+   public void internalTestPagedTransacted(final boolean transacted, final boolean failBeforeConsume) throws Exception
+   {
+      ClientSessionFactoryInternal factory = getSessionFactory();
+      factory.setBlockOnPersistentSend(true);
+      ClientSession session = factory.createSession(!transacted, !transacted, 0);
+
+      try
+      {
+
+         session.createQueue(ADDRESS, ADDRESS, true);
+
+         final CountDownLatch latch = new CountDownLatch(1);
+
+         class MyListener implements FailureListener
+         {
+            public void connectionFailed(HornetQException me)
+            {
+               latch.countDown();
+            }
+         }
+
+         session.addFailureListener(new MyListener());
+
+         ClientProducer prod = session.createProducer(ADDRESS);
+
+         final int TOTAL_MESSAGES = 2000;
+
+         for (int i = 0; i < TOTAL_MESSAGES; i++)
+         {
+            if (transacted && i % 10 == 0)
+            {
+               session.commit();
+            }
+            ClientMessage msg = session.createClientMessage(true);
+            msg.setBody(ChannelBuffers.buffer(1024));
+            msg.putIntProperty(new SimpleString("key"), i);
+            prod.send(msg);
+         }
+
+         session.commit();
+         
+         if (failBeforeConsume)
+         {
+            failSession(session, latch);
+         }
+
+
+         session.start();
+
+         ClientConsumer cons = session.createConsumer(ADDRESS);
+
+         final int MIDDLE = TOTAL_MESSAGES / 2;
+
+         for (int i = 0; i < MIDDLE; i++)
+         {
+            ClientMessage msg = cons.receive(10000);
+            assertNotNull(msg);
+            msg.acknowledge();
+            if (transacted && i % 10 == 0)
+            {
+               session.commit();
+            }
+            assertEquals((Integer)i, (Integer)msg.getProperty(new SimpleString("key")));
+         }
+
+         session.commit();
+
+         if (!failBeforeConsume)
+         {
+            failSession(session, latch);
+         }
+
+         session.close();
+
+         session = factory.createSession(true, true, 0);
+
+         cons = session.createConsumer(ADDRESS);
+
+         session.start();
+
+         for (int i = MIDDLE; i < TOTAL_MESSAGES; i++)
+         {
+            ClientMessage msg = cons.receive(5000);
+            assertNotNull(msg);
+
+            msg.acknowledge();
+            int result = (Integer)msg.getProperty(new SimpleString("key"));
+            assertEquals(i, result);
+         }
+      }
+      finally
+      {
+         try
+         {
+            session.close();
+         }
+         catch (Exception ignored)
+         {
+         }
+      }
+   }
+
+
+   /**
+    * @param session
+    * @param latch
+    * @throws InterruptedException
+    */
+   private void failSession(ClientSession session, final CountDownLatch latch) throws InterruptedException
+   {
+      RemotingConnection conn = ((ClientSessionInternal)session).getConnection();
+
+      // Simulate failure on connection
+      conn.fail(new HornetQException(HornetQException.NOT_CONNECTED));
+
+      // Wait to be informed of failure
+
+      assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   /* (non-Javadoc)
+    * @see org.hornetq.tests.integration.cluster.failover.FailoverTestBase#getAcceptorTransportConfiguration(boolean)
+    */
+   @Override
+   protected TransportConfiguration getAcceptorTransportConfiguration(boolean live)
+   {
+      return getInVMTransportAcceptorConfiguration(live);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.tests.integration.cluster.failover.FailoverTestBase#getConnectorTransportConfiguration(boolean)
+    */
+   @Override
+   protected TransportConfiguration getConnectorTransportConfiguration(boolean live)
+   {
+      return getInVMConnectorTransportConfiguration(live);
+   }
+
+   protected HornetQServer createServer(final boolean realFiles, final Configuration configuration)
+   {
+      return createServer(realFiles, configuration, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());
+   }
+
+   /**
+    * @throws Exception
+    */
+   protected void createConfigs() throws Exception
+   {
+      Configuration config1 = super.createDefaultConfig();
+      config1.getAcceptorConfigurations().clear();
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
+      config1.setSecurityEnabled(false);
+      config1.setSharedStore(true);
+      config1.setBackup(true);
+      server1Service = createServer(true, config1);
+
+      Configuration config0 = super.createDefaultConfig();
+      config0.getAcceptorConfigurations().clear();
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+      config0.setSecurityEnabled(false);
+      config0.setSharedStore(true);
+      server0Service = createServer(true, config0);
+
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedAsynchronousFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedAsynchronousFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedAsynchronousFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+import org.hornetq.core.config.Configuration;
+
+/**
+ * A ReplicatedAsynchronousFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicatedAsynchronousFailoverTest extends AsynchronousFailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   @Override
+   protected void createConfigs() throws Exception
+   {
+      Configuration config1 = super.createDefaultConfig();
+      config1.setBindingsDirectory(config1.getBindingsDirectory() + "_backup");
+      config1.setJournalDirectory(config1.getJournalDirectory() + "_backup");
+      config1.getAcceptorConfigurations().clear();
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
+      config1.setSecurityEnabled(false);
+      config1.setSharedStore(false);
+      config1.setBackup(true);
+      server1Service = super.createServer(true, config1);
+
+      Configuration config0 = super.createDefaultConfig();
+      config0.getAcceptorConfigurations().clear();
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+
+      config0.getConnectorConfigurations().put("toBackup", getConnectorTransportConfiguration(false));
+      config0.setBackupConnectorName("toBackup");
+      config0.setSecurityEnabled(false);
+      config0.setSharedStore(false);
+      server0Service = super.createServer(true, config0);
+
+      server1Service.start();
+      server0Service.start();
+   }
+
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+
+/**
+ * A ReplicatedFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicatedFailoverTest extends FailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   @Override
+   protected void createConfigs() throws Exception
+   {
+      createReplicatedConfigs();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedLargeMessageFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedLargeMessageFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedLargeMessageFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+/**
+ * A ReplicatedLargeMessageFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicatedLargeMessageFailoverTest extends LargeMessageFailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+   
+   public ReplicatedLargeMessageFailoverTest()
+   {
+      super();
+   }
+
+   public ReplicatedLargeMessageFailoverTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   @Override
+   protected void createConfigs() throws Exception
+   {
+      createReplicatedConfigs();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedNettyAsynchronousFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedNettyAsynchronousFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedNettyAsynchronousFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+import org.hornetq.core.config.Configuration;
+
+/**
+ * A ReplicatedNettyAsynchronousFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicatedNettyAsynchronousFailoverTest extends NettyAsynchronousFailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   @Override
+   protected void createConfigs() throws Exception
+   {
+      Configuration config1 = super.createDefaultConfig();
+      config1.setBindingsDirectory(config1.getBindingsDirectory() + "_backup");
+      config1.setJournalDirectory(config1.getJournalDirectory() + "_backup");
+      config1.getAcceptorConfigurations().clear();
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
+      config1.setSecurityEnabled(false);
+      config1.setSharedStore(false);
+      config1.setBackup(true);
+      server1Service = super.createServer(true, config1);
+
+      Configuration config0 = super.createDefaultConfig();
+      config0.getAcceptorConfigurations().clear();
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+
+      config0.getConnectorConfigurations().put("toBackup", getConnectorTransportConfiguration(false));
+      config0.setBackupConnectorName("toBackup");
+      config0.setSecurityEnabled(false);
+      config0.setSharedStore(false);
+      server0Service = super.createServer(true, config0);
+
+      server1Service.start();
+      server0Service.start();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedPagingFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedPagingFailoverTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ReplicatedPagingFailoverTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.cluster.failover;
+
+import org.hornetq.core.config.Configuration;
+
+/**
+ * A ReplicatedPagingFailoverTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicatedPagingFailoverTest extends PagingFailoverTest
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   @Override
+   protected void createConfigs() throws Exception
+   {
+      Configuration config1 = super.createDefaultConfig();
+      config1.setBindingsDirectory(config1.getBindingsDirectory() + "_backup");
+      config1.setJournalDirectory(config1.getJournalDirectory() + "_backup");
+      config1.setPagingDirectory(config1.getPagingDirectory() + "_backup");
+      config1.getAcceptorConfigurations().clear();
+      config1.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(false));
+      config1.setSecurityEnabled(false);
+      config1.setSharedStore(false);
+      config1.setBackup(true);
+      server1Service = super.createServer(true, config1);
+
+      Configuration config0 = super.createDefaultConfig();
+      config0.getAcceptorConfigurations().clear();
+      config0.getAcceptorConfigurations().add(getAcceptorTransportConfiguration(true));
+
+      config0.getConnectorConfigurations().put("toBackup", getConnectorTransportConfiguration(false));
+      config0.setBackupConnectorName("toBackup");
+      config0.setSecurityEnabled(false);
+      config0.setSharedStore(false);
+      server0Service = super.createServer(true, config0);
+
+      server1Service.start();
+      server0Service.start();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: trunk/tests/src/org/hornetq/tests/integration/largemessage/mock/MockConnectorFactory.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/largemessage/mock/MockConnectorFactory.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/largemessage/mock/MockConnectorFactory.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -14,6 +14,7 @@
 package org.hornetq.tests.integration.largemessage.mock;
 
 import java.util.HashSet;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Executor;

Modified: trunk/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -310,7 +310,7 @@
             }
 
             @Override
-            protected Page createPage(final int page) throws Exception
+            public Page createPage(final int page) throws Exception
             {
 
                Page originalPage = super.createPage(page);

Added: trunk/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java	                        (rev 0)
+++ trunk/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -0,0 +1,681 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.replication;
+
+import static org.hornetq.tests.util.RandomUtil.randomString;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import org.hornetq.core.buffers.ChannelBuffers;
+import org.hornetq.core.client.ClientSessionFactory;
+import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
+import org.hornetq.core.client.impl.FailoverManager;
+import org.hornetq.core.client.impl.FailoverManagerImpl;
+import org.hornetq.core.config.Configuration;
+import org.hornetq.core.config.TransportConfiguration;
+import org.hornetq.core.exception.HornetQException;
+import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.journal.Journal;
+import org.hornetq.core.journal.LoaderCallback;
+import org.hornetq.core.journal.PreparedTransactionInfo;
+import org.hornetq.core.journal.RecordInfo;
+import org.hornetq.core.journal.TransactionFailureCallback;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.PagingStore;
+import org.hornetq.core.paging.impl.PagedMessageImpl;
+import org.hornetq.core.paging.impl.PagingManagerImpl;
+import org.hornetq.core.paging.impl.PagingStoreFactoryNIO;
+import org.hornetq.core.persistence.StorageManager;
+import org.hornetq.core.remoting.impl.invm.InVMConnectorFactory;
+import org.hornetq.core.remoting.spi.HornetQBuffer;
+import org.hornetq.core.replication.impl.ReplicatedJournal;
+import org.hornetq.core.replication.impl.ReplicationManagerImpl;
+import org.hornetq.core.server.HornetQServer;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.server.impl.HornetQServerImpl;
+import org.hornetq.core.server.impl.ServerMessageImpl;
+import org.hornetq.core.settings.HierarchicalRepository;
+import org.hornetq.core.settings.impl.AddressSettings;
+import org.hornetq.tests.util.ServiceTestBase;
+import org.hornetq.utils.ExecutorFactory;
+import org.hornetq.utils.HornetQThreadFactory;
+import org.hornetq.utils.SimpleString;
+
+/**
+ * A ReplicationTest
+ *
+ * @author <mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class ReplicationTest extends ServiceTestBase
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private ThreadFactory tFactory;
+
+   private ExecutorService executor;
+
+   private FailoverManager connectionManager;
+
+   private ScheduledExecutorService scheduledExecutor;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   public void testBasicConnection() throws Exception
+   {
+
+      Configuration config = createDefaultConfig(false);
+
+      config.setBackup(true);
+
+      HornetQServer server = new HornetQServerImpl(config);
+
+      server.start();
+
+      try
+      {
+         ReplicationManagerImpl manager = new ReplicationManagerImpl(connectionManager, executor);
+         manager.start();
+         manager.stop();
+      }
+      finally
+      {
+         server.stop();
+      }
+   }
+
+   public void testConnectIntoNonBackup() throws Exception
+   {
+
+      Configuration config = createDefaultConfig(false);
+
+      config.setBackup(false);
+
+      HornetQServer server = new HornetQServerImpl(config);
+
+      server.start();
+
+      try
+      {
+         ReplicationManagerImpl manager = new ReplicationManagerImpl(connectionManager, executor);
+         try
+         {
+            manager.start();
+            fail("Exception was expected");
+         }
+         catch (HornetQException expected)
+         {
+         }
+
+         manager.stop();
+      }
+      finally
+      {
+         server.stop();
+      }
+   }
+
+   public void testSendPackets() throws Exception
+   {
+
+      Configuration config = createDefaultConfig(false);
+
+      config.setBackup(true);
+
+      HornetQServer server = new HornetQServerImpl(config);
+
+      server.start();
+
+      try
+      {
+         ReplicationManagerImpl manager = new ReplicationManagerImpl(connectionManager, executor);
+         manager.start();
+
+         Journal replicatedJournal = new ReplicatedJournal((byte)1, new FakeJournal(), manager);
+
+         replicatedJournal.appendPrepareRecord(1, new FakeData(), false);
+
+         replicatedJournal.appendAddRecord(1, (byte)1, new FakeData(), false);
+         replicatedJournal.appendUpdateRecord(1, (byte)2, new FakeData(), false);
+         replicatedJournal.appendDeleteRecord(1, false);
+         replicatedJournal.appendAddRecordTransactional(2, 2, (byte)1, new FakeData());
+         replicatedJournal.appendUpdateRecordTransactional(2, 2, (byte)2, new FakeData());
+         replicatedJournal.appendCommitRecord(2, false);
+
+         replicatedJournal.appendDeleteRecordTransactional(3, 4, new FakeData());
+         replicatedJournal.appendPrepareRecord(3, new FakeData(), false);
+         replicatedJournal.appendRollbackRecord(3, false);
+
+         blockOnReplication(manager);
+
+         assertEquals(1, manager.getActiveTokens().size());
+
+         manager.closeContext();
+
+         for (int i = 0; i < 100; i++)
+         {
+            // This is asynchronous. Have to wait completion
+            if (manager.getActiveTokens().size() == 0)
+            {
+               break;
+            }
+            Thread.sleep(1);
+         }
+
+         assertEquals(0, manager.getActiveTokens().size());
+
+         ServerMessage msg = new ServerMessageImpl();
+
+         SimpleString dummy = new SimpleString("dummy");
+         msg.setDestination(dummy);
+         msg.setBody(ChannelBuffers.wrappedBuffer(new byte[10]));
+
+         replicatedJournal.appendAddRecordTransactional(23, 24, (byte)1, new FakeData());
+
+         PagedMessage pgmsg = new PagedMessageImpl(msg, -1);
+         manager.pageWrite(pgmsg, 1);
+         manager.pageWrite(pgmsg, 2);
+         manager.pageWrite(pgmsg, 3);
+         manager.pageWrite(pgmsg, 4);
+
+         blockOnReplication(manager);
+
+         PagingManager pagingManager = createPageManager(server.getStorageManager(),
+                                                         server.getConfiguration(),
+                                                         server.getExecutorFactory(),
+                                                         server.getAddressSettingsRepository());
+         
+         PagingStore store = pagingManager.getPageStore(dummy);
+         store.start();
+         assertEquals(5, store.getNumberOfPages());
+         store.stop();
+         
+         manager.pageDeleted(dummy, 1);
+         manager.pageDeleted(dummy, 2);
+         manager.pageDeleted(dummy, 3);
+         manager.pageDeleted(dummy, 4);
+         manager.pageDeleted(dummy, 5);
+         manager.pageDeleted(dummy, 6);
+
+         blockOnReplication(manager);
+         
+         ServerMessageImpl serverMsg = new ServerMessageImpl();
+         serverMsg.setMessageID(500);
+         serverMsg.setDestination(new SimpleString("tttt"));
+         
+         
+         HornetQBuffer buffer = ChannelBuffers.dynamicBuffer(100);
+         serverMsg.encodeProperties(buffer);
+         
+         manager.largeMessageBegin(500);
+
+         manager.largeMessageWrite(500, new byte[1024]);
+         
+         manager.largeMessageEnd(500);
+         
+         blockOnReplication(manager);
+         
+         store.start();
+         
+         assertEquals(0, store.getNumberOfPages());
+
+         manager.stop();
+      }
+      finally
+      {
+         server.stop();
+      }
+   }
+
+
+   public void testSendPacketsWithFailure() throws Exception
+   {
+
+      Configuration config = createDefaultConfig(false);
+
+      config.setBackup(true);
+
+      HornetQServer server = new HornetQServerImpl(config);
+
+      server.start();
+
+      try
+      {
+         ReplicationManagerImpl manager = new ReplicationManagerImpl(connectionManager, executor);
+         manager.start();
+
+         Journal replicatedJournal = new ReplicatedJournal((byte)1, new FakeJournal(), manager);
+
+         for (int i = 0 ; i < 500; i++)
+         {
+            replicatedJournal.appendAddRecord(i, (byte)1, new FakeData(), false);
+         }
+
+         final CountDownLatch latch = new CountDownLatch(1);
+         manager.afterReplicated(new Runnable()
+         {
+            public void run()
+            {
+               latch.countDown();
+            }
+         });
+         
+         manager.closeContext();
+         
+         assertTrue(latch.await(10, TimeUnit.SECONDS));
+      }
+      finally
+      {
+         server.stop();
+      }
+   }
+
+   /**
+    * @param manager
+    * @return
+    */
+   private void blockOnReplication(ReplicationManagerImpl manager) throws Exception
+   {
+      final CountDownLatch latch = new CountDownLatch(1);
+      manager.afterReplicated(new Runnable()
+      {
+
+         public void run()
+         {
+            latch.countDown();
+         }
+
+      });
+      
+      assertTrue(latch.await(30, TimeUnit.SECONDS));
+   }
+
+   public void testNoActions() throws Exception
+   {
+
+      Configuration config = createDefaultConfig(false);
+
+      config.setBackup(true);
+
+      HornetQServer server = new HornetQServerImpl(config);
+
+      server.start();
+
+      try
+      {
+         ReplicationManagerImpl manager = new ReplicationManagerImpl(connectionManager, executor);
+         manager.start();
+
+         Journal replicatedJournal = new ReplicatedJournal((byte)1, new FakeJournal(), manager);
+
+         replicatedJournal.appendPrepareRecord(1, new FakeData(), false);
+
+         final CountDownLatch latch = new CountDownLatch(1);
+         manager.afterReplicated(new Runnable()
+         {
+
+            public void run()
+            {
+               latch.countDown();
+            }
+
+         });
+         assertTrue(latch.await(1, TimeUnit.SECONDS));
+         assertEquals(1, manager.getActiveTokens().size());
+
+         manager.closeContext();
+
+         for (int i = 0; i < 100; i++)
+         {
+            // This is asynchronous. Have to wait completion
+            if (manager.getActiveTokens().size() == 0)
+            {
+               break;
+            }
+            Thread.sleep(1);
+         }
+
+         assertEquals(0, manager.getActiveTokens().size());
+         manager.stop();
+      }
+      finally
+      {
+         server.stop();
+      }
+   }
+
+   class FakeData implements EncodingSupport
+   {
+
+      public void decode(HornetQBuffer buffer)
+      {
+      }
+
+      public void encode(HornetQBuffer buffer)
+      {
+         buffer.writeBytes(new byte[5]);
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.EncodingSupport#getEncodeSize()
+       */
+      public int getEncodeSize()
+      {
+         return 5;
+      }
+
+   }
+
+   // Package protected ---------------------------------------------
+   /*class LocalRemotingServiceImpl extends RemotingServiceImpl
+   {
+      
+      public LocalRemotingServiceImpl(final Configuration config,
+                                 final HornetQServer server,
+                                 final ManagementService managementService,
+                                 final Executor threadPool,
+                                 final ScheduledExecutorService scheduledThreadPool)
+      {
+         super(config, server, managementService, threadPool, scheduledThreadPool);
+      }
+
+      protected ChannelHandler createHandler(RemotingConnection conn, Channel channel)
+      {
+         return super.createHandler(conn, channel);
+      }
+
+   }*/
+
+   // Protected -----------------------------------------------------
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+
+      tFactory = new HornetQThreadFactory("HornetQ-ReplicationTest", false);
+
+      executor = Executors.newCachedThreadPool(tFactory);
+
+      scheduledExecutor = new ScheduledThreadPoolExecutor(10, tFactory);
+
+      TransportConfiguration connectorConfig = new TransportConfiguration(InVMConnectorFactory.class.getName(),
+                                                                          new HashMap<String, Object>(),
+                                                                          randomString());
+
+      connectionManager = new FailoverManagerImpl((ClientSessionFactory)null,
+                                                  connectorConfig,
+                                                      null,
+                                                      false,
+                                                      ClientSessionFactoryImpl.DEFAULT_CALL_TIMEOUT,
+                                                      ClientSessionFactoryImpl.DEFAULT_CLIENT_FAILURE_CHECK_PERIOD,
+                                                      ClientSessionFactoryImpl.DEFAULT_CONNECTION_TTL,
+                                                      0,
+                                                      1.0d,
+                                                      0,
+                                                      1,
+                                                      executor,
+                                                      scheduledExecutor,
+                                                      null);
+
+   }
+
+   protected void tearDown() throws Exception
+   {
+
+      executor.shutdown();
+
+      scheduledExecutor.shutdown();
+
+      tFactory = null;
+
+      connectionManager = null;
+
+      scheduledExecutor = null;
+
+      super.tearDown();
+
+   }
+
+   protected PagingManager createPageManager(StorageManager storageManager,
+                                             Configuration configuration,
+                                             ExecutorFactory executorFactory,
+                                             HierarchicalRepository<AddressSettings> addressSettingsRepository) throws Exception
+   {
+
+      PagingManager paging = new PagingManagerImpl(new PagingStoreFactoryNIO(configuration.getPagingDirectory(),
+                                                                             executorFactory),
+                                                   storageManager,
+                                                   addressSettingsRepository,
+                                                   false);
+
+      paging.start();
+      return paging;
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+   static class FakeJournal implements Journal
+   {
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendAddRecord(long, byte, byte[], boolean)
+       */
+      public void appendAddRecord(long id, byte recordType, byte[] record, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendAddRecord(long, byte, org.hornetq.core.journal.EncodingSupport, boolean)
+       */
+      public void appendAddRecord(long id, byte recordType, EncodingSupport record, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendAddRecordTransactional(long, long, byte, byte[])
+       */
+      public void appendAddRecordTransactional(long txID, long id, byte recordType, byte[] record) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendAddRecordTransactional(long, long, byte, org.hornetq.core.journal.EncodingSupport)
+       */
+      public void appendAddRecordTransactional(long txID, long id, byte recordType, EncodingSupport record) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendCommitRecord(long, boolean)
+       */
+      public void appendCommitRecord(long txID, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendDeleteRecord(long, boolean)
+       */
+      public void appendDeleteRecord(long id, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendDeleteRecordTransactional(long, long, byte[])
+       */
+      public void appendDeleteRecordTransactional(long txID, long id, byte[] record) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendDeleteRecordTransactional(long, long, org.hornetq.core.journal.EncodingSupport)
+       */
+      public void appendDeleteRecordTransactional(long txID, long id, EncodingSupport record) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendDeleteRecordTransactional(long, long)
+       */
+      public void appendDeleteRecordTransactional(long txID, long id) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendPrepareRecord(long, org.hornetq.core.journal.EncodingSupport, boolean)
+       */
+      public void appendPrepareRecord(long txID, EncodingSupport transactionData, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendPrepareRecord(long, byte[], boolean)
+       */
+      public void appendPrepareRecord(long txID, byte[] transactionData, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendRollbackRecord(long, boolean)
+       */
+      public void appendRollbackRecord(long txID, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendUpdateRecord(long, byte, byte[], boolean)
+       */
+      public void appendUpdateRecord(long id, byte recordType, byte[] record, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendUpdateRecord(long, byte, org.hornetq.core.journal.EncodingSupport, boolean)
+       */
+      public void appendUpdateRecord(long id, byte recordType, EncodingSupport record, boolean sync) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendUpdateRecordTransactional(long, long, byte, byte[])
+       */
+      public void appendUpdateRecordTransactional(long txID, long id, byte recordType, byte[] record) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#appendUpdateRecordTransactional(long, long, byte, org.hornetq.core.journal.EncodingSupport)
+       */
+      public void appendUpdateRecordTransactional(long txID, long id, byte recordType, EncodingSupport record) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#getAlignment()
+       */
+      public int getAlignment() throws Exception
+      {
+
+         return 0;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#load(org.hornetq.core.journal.LoaderCallback)
+       */
+      public long load(LoaderCallback reloadManager) throws Exception
+      {
+
+         return 0;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#load(java.util.List, java.util.List, org.hornetq.core.journal.TransactionFailureCallback)
+       */
+      public long load(List<RecordInfo> committedRecords,
+                       List<PreparedTransactionInfo> preparedTransactions,
+                       TransactionFailureCallback transactionFailure) throws Exception
+      {
+
+         return 0;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.Journal#perfBlast(int)
+       */
+      public void perfBlast(int pages) throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.HornetQComponent#isStarted()
+       */
+      public boolean isStarted()
+      {
+
+         return false;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.HornetQComponent#start()
+       */
+      public void start() throws Exception
+      {
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.HornetQComponent#stop()
+       */
+      public void stop() throws Exception
+      {
+
+      }
+
+   }
+}

Modified: trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -24,6 +24,7 @@
 import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.impl.PageImpl;
 import org.hornetq.core.paging.impl.PagedMessageImpl;
+import org.hornetq.core.persistence.impl.nullpm.NullStorageManager;
 import org.hornetq.core.remoting.spi.HornetQBuffer;
 import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.server.impl.ServerMessageImpl;
@@ -77,7 +78,7 @@
 
       SequentialFile file = factory.createSequentialFile("00010.page", 1);
 
-      PageImpl impl = new PageImpl(factory, file, 10);
+      PageImpl impl = new PageImpl(new SimpleString("something"), new NullStorageManager(), factory, file, 10);
 
       assertEquals(10, impl.getPageId());
 
@@ -94,7 +95,7 @@
 
       file = factory.createSequentialFile("00010.page", 1);
       file.open();
-      impl = new PageImpl(factory, file, 10);
+      impl = new PageImpl(new SimpleString("something"), new NullStorageManager(), factory, file, 10);
 
       List<PagedMessage> msgs = impl.read();
 
@@ -124,7 +125,7 @@
 
       SequentialFile file = factory.createSequentialFile("00010.page", 1);
 
-      PageImpl impl = new PageImpl(factory, file, 10);
+      PageImpl impl = new PageImpl(new SimpleString("something"), new NullStorageManager(), factory, file, 10);
 
       assertEquals(10, impl.getPageId());
 
@@ -167,7 +168,7 @@
 
       file = factory.createSequentialFile("00010.page", 1);
       file.open();
-      impl = new PageImpl(factory, file, 10);
+      impl = new PageImpl(new SimpleString("something"), new NullStorageManager(), factory, file, 10);
 
       List<PagedMessage> msgs = impl.read();
 

Modified: trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -1105,6 +1105,78 @@
       {
       }
 
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#afterReplicated(java.lang.Runnable)
+       */
+      public void afterReplicated(Runnable run)
+      {
+         
+         
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#completeReplication()
+       */
+      public void completeReplication()
+      {
+         
+         
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#createLargeMessage(byte[])
+       */
+      public LargeServerMessage createLargeMessage(long messageId, byte[] header)
+      {
+         
+         return null;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#isReplicated()
+       */
+      public boolean isReplicated()
+      {
+         
+         return false;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#loadInternalOnly()
+       */
+      public void loadInternalOnly() throws Exception
+      {
+         
+         
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#pageClosed(org.hornetq.utils.SimpleString, int)
+       */
+      public void pageClosed(SimpleString storeName, int pageNumber)
+      {
+         
+         
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#pageDeleted(org.hornetq.utils.SimpleString, int)
+       */
+      public void pageDeleted(SimpleString storeName, int pageNumber)
+      {
+         
+         
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#pageWrite(org.hornetq.core.paging.PagedMessage, int)
+       */
+      public void pageWrite(PagedMessage message, int pageNumber)
+      {
+         
+         
+      }
+
    }
 
    class FakeStoreFactory implements PagingStoreFactory

Modified: trunk/tests/src/org/hornetq/tests/unit/core/persistence/impl/BatchIDGeneratorUnitTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/unit/core/persistence/impl/BatchIDGeneratorUnitTest.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/unit/core/persistence/impl/BatchIDGeneratorUnitTest.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -23,6 +23,7 @@
 import org.hornetq.core.journal.impl.JournalImpl;
 import org.hornetq.core.journal.impl.NIOSequentialFileFactory;
 import org.hornetq.core.persistence.impl.journal.BatchingIDGenerator;
+import org.hornetq.core.persistence.impl.journal.JournalStorageManager;
 import org.hornetq.core.remoting.spi.HornetQBuffer;
 import org.hornetq.tests.util.UnitTestCase;
 
@@ -142,7 +143,7 @@
 
       for (RecordInfo record : records)
       {
-         if (record.userRecordType == BatchingIDGenerator.ID_COUNTER_RECORD)
+         if (record.userRecordType == JournalStorageManager.ID_COUNTER_RECORD)
          {
             HornetQBuffer buffer = ChannelBuffers.wrappedBuffer(record.data);
             batch.loadState(record.id, buffer);

Modified: trunk/tests/src/org/hornetq/tests/util/ServiceTestBase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/util/ServiceTestBase.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/util/ServiceTestBase.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -67,6 +67,16 @@
 
    // Constructors --------------------------------------------------
 
+   public ServiceTestBase()
+   {
+      super();
+   }
+   
+   public ServiceTestBase(String name)
+   {
+      super(name);
+   }
+   
    // Public --------------------------------------------------------
 
    // Package protected ---------------------------------------------

Modified: trunk/tests/src/org/hornetq/tests/util/UnitTestCase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/util/UnitTestCase.java	2009-10-15 16:17:52 UTC (rev 8115)
+++ trunk/tests/src/org/hornetq/tests/util/UnitTestCase.java	2009-10-15 16:41:41 UTC (rev 8116)
@@ -96,6 +96,19 @@
    
    // Static --------------------------------------------------------
 
+   /**
+    * @param name
+    */
+   public UnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public UnitTestCase()
+   {
+      super();
+   }
+
    public static void forceGC()
    {
       WeakReference<Object> dumbReference = new WeakReference<Object>(new Object());



More information about the hornetq-commits mailing list