[jboss-cvs] JBoss Messaging SVN: r7478 - in branches/Branch_MultiThreaded_Replication: src/main/org/jboss/messaging/core/client/impl and 27 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jun 26 05:46:36 EDT 2009


Author: timfox
Date: 2009-06-26 05:46:34 -0400 (Fri, 26 Jun 2009)
New Revision: 7478

Added:
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicateLockSequenceMessage.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicationResponseMessage.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/ReplicableAction.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/Replicator.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/JBMThread.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/PriorityLock.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/ReplicatorImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/StatefulObjectReadWriteLock.java
   branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/replication/
   branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/replication/impl/
   branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/replication/impl/NewSequencedLockTest.java
Removed:
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReplicateCreateSessionMessage.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/SessionReplicateDeliveryMessage.java
Modified:
   branches/Branch_MultiThreaded_Replication/src/config/trunk/non-clustered/logging.properties
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/exception/MessagingException.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/ManagementService.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/MessagingServerControlImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/QueueControlImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/paging/impl/PagingStoreImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/nullpm/NullStorageManager.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/AddressManager.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/PostOffice.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/PostOfficeImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/SimpleAddressManager.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/WildcardAddressManager.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/Channel.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/ChannelImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/PacketDecoder.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnection.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/PacketImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/server/impl/RemotingServiceImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/MessagingServer.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/Queue.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerConsumer.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerSession.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterConnectionImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterManagerImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/Redistributor.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/LastValueQueue.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueFactoryImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/integration/logging/JBMLoggerFormatter.java
   branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/utils/JBMThreadFactory.java
   branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/integration/cluster/failover/SimpleAutomaticFailoverTest.java
   branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/postoffice/impl/BindingImplTest.java
   branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/impl/QueueImplTest.java
Log:
mt replication commit 1

Modified: branches/Branch_MultiThreaded_Replication/src/config/trunk/non-clustered/logging.properties
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/config/trunk/non-clustered/logging.properties	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/config/trunk/non-clustered/logging.properties	2009-06-26 09:46:34 UTC (rev 7478)
@@ -20,7 +20,7 @@
 java.util.logging.FileHandler.level=INFO
 java.util.logging.FileHandler.formatter=org.jboss.messaging.integration.logging.JBMLoggerFormatter
 java.util.logging.FileHandler.pattern=logs/messaging.log
-java.util.logging.FileHandler.limit=10000
+java.util.logging.FileHandler.limit=0
 # Default global logging level.
 # This specifies which kinds of events are logged across
 # all loggers.  For any given facility this global level

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -721,7 +721,7 @@
 
       try
       {
-         channel.transferConnection(backupConnection, channel.getID(), null);
+         channel.transferConnection(backupConnection);
 
          backupConnection.syncIDGeneratorSequence(remotingConnection.getIDGeneratorSequence());
 
@@ -735,7 +735,7 @@
 
          if (!response.isRemoved())
          {
-            channel.replayCommands(response.getLastReceivedCommandID(), channel.getID());
+            channel.replayCommands(response.getLastReceivedCommandID());
 
             ok = true;
          }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/exception/MessagingException.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/exception/MessagingException.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/exception/MessagingException.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -22,6 +22,8 @@
 
 package org.jboss.messaging.core.exception;
 
+import org.jboss.messaging.core.logging.Logger;
+
 /**
  * 
  * A MessagingException
@@ -32,7 +34,10 @@
 public class MessagingException extends Exception
 {
    private static final long serialVersionUID = -4802014152804997417L;
+   
+   private static final Logger log = Logger.getLogger(MessagingException.class);
 
+
    // Error codes -------------------------------------------------
 
    public static final int INTERNAL_ERROR = 000;
@@ -110,6 +115,8 @@
    public MessagingException(int code, String msg)
    {
       super(msg);
+      
+     // log.info("Creating new messagingexception", new Exception());
 
       this.code = code;
    }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/ManagementService.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/ManagementService.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/ManagementService.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -37,6 +37,7 @@
 import org.jboss.messaging.core.management.impl.MessagingServerControlImpl;
 import org.jboss.messaging.core.messagecounter.MessageCounterManager;
 import org.jboss.messaging.core.persistence.StorageManager;
+import org.jboss.messaging.core.postoffice.ClusterQueueStateManager;
 import org.jboss.messaging.core.postoffice.PostOffice;
 import org.jboss.messaging.core.remoting.server.RemotingService;
 import org.jboss.messaging.core.remoting.spi.Acceptor;
@@ -80,15 +81,16 @@
    // Resource Registration
 
    MessagingServerControlImpl registerServer(PostOffice postOffice,
-                                         StorageManager storageManager,
-                                         Configuration configuration,
-                                         HierarchicalRepository<AddressSettings> addressSettingsRepository,
-                                         HierarchicalRepository<Set<Role>> securityRepository,
-                                         ResourceManager resourceManager,
-                                         RemotingService remotingService,
-                                         MessagingServer messagingServer,
-                                         QueueFactory queueFactory,
-                                         boolean backup) throws Exception;
+                                             StorageManager storageManager,
+                                             Configuration configuration,
+                                             HierarchicalRepository<AddressSettings> addressSettingsRepository,
+                                             HierarchicalRepository<Set<Role>> securityRepository,
+                                             ResourceManager resourceManager,
+                                             RemotingService remotingService,
+                                             MessagingServer messagingServer,
+                                             QueueFactory queueFactory,
+                                             ClusterQueueStateManager clusterQueueStateManager,
+                                             boolean backup) throws Exception;
 
    void unregisterServer() throws Exception;
 

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/ManagementServiceImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -67,6 +67,7 @@
 import org.jboss.messaging.core.messagecounter.MessageCounterManager;
 import org.jboss.messaging.core.messagecounter.impl.MessageCounterManagerImpl;
 import org.jboss.messaging.core.persistence.StorageManager;
+import org.jboss.messaging.core.postoffice.ClusterQueueStateManager;
 import org.jboss.messaging.core.postoffice.PostOffice;
 import org.jboss.messaging.core.remoting.server.RemotingService;
 import org.jboss.messaging.core.remoting.spi.Acceptor;
@@ -111,13 +112,13 @@
 
    private StorageManager storageManager;
 
-   private MessagingServer messagingServer;
-
    private HierarchicalRepository<Set<Role>> securityRepository;
 
    private HierarchicalRepository<AddressSettings> addressSettingsRepository;
 
    private MessagingServerControlImpl messagingServerControl;
+   
+   private MessagingServer messagingServer;
 
    private final MessageCounterManager messageCounterManager;
 
@@ -140,6 +141,8 @@
    private final Set<NotificationListener> listeners = new org.jboss.messaging.utils.ConcurrentHashSet<NotificationListener>();
 
    private ReplicationOperationInvoker replicationInvoker;
+   
+   private ClusterQueueStateManager clusterQueueStateManager;
 
    // Static --------------------------------------------------------
 
@@ -199,12 +202,14 @@
                                                     final RemotingService remotingService,
                                                     final MessagingServer messagingServer,
                                                     final QueueFactory queueFactory,
+                                                    final ClusterQueueStateManager clusterQueueStateManager,
                                                     final boolean backup) throws Exception
    {
       this.postOffice = postOffice;
       this.addressSettingsRepository = addressSettingsRepository;
       this.securityRepository = securityRepository;
       this.storageManager = storageManager;
+      this.clusterQueueStateManager = clusterQueueStateManager;
       this.messagingServer = messagingServer;
 
       JBMSecurityManager sm = messagingServer.getSecurityManager();
@@ -213,7 +218,7 @@
          sm.addUser(managementClusterUser, managementClusterPassword);
       }
 
-      messagingServerControl = new MessagingServerControlImpl(postOffice,
+      messagingServerControl = new MessagingServerControlImpl(clusterQueueStateManager,
                                                               configuration,
                                                               resourceManager,
                                                               remotingService,
@@ -608,6 +613,8 @@
 
    public void sendNotification(final Notification notification) throws Exception
    {
+      log.info("messagingservercontrol " + this.messagingServerControl + " ne " + this.notificationsEnabled);
+      
       if (messagingServerControl != null && notificationsEnabled)
       {
          // This needs to be synchronized since we need to ensure notifications are processed in strict sequence
@@ -616,7 +623,7 @@
             // We also need to synchronize on the post office notification lock
             // otherwise we can get notifications arriving in wrong order / missing
             // if a notification occurs at same time as sendQueueInfoToQueue is processed
-            synchronized (postOffice.getNotificationLock())
+            synchronized (clusterQueueStateManager.getNotificationLock())
             {
 
                // First send to any local listeners

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/MessagingServerControlImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/MessagingServerControlImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/MessagingServerControlImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -49,7 +49,7 @@
 import org.jboss.messaging.core.management.NotificationType;
 import org.jboss.messaging.core.messagecounter.MessageCounterManager;
 import org.jboss.messaging.core.messagecounter.impl.MessageCounterManagerImpl;
-import org.jboss.messaging.core.postoffice.PostOffice;
+import org.jboss.messaging.core.postoffice.ClusterQueueStateManager;
 import org.jboss.messaging.core.remoting.RemotingConnection;
 import org.jboss.messaging.core.remoting.server.RemotingService;
 import org.jboss.messaging.core.server.MessagingServer;
@@ -77,7 +77,7 @@
 
    // Attributes ----------------------------------------------------
 
-   private final PostOffice postOffice;
+   private final ClusterQueueStateManager clusterQueueStateManager;
 
    private final Configuration configuration;
 
@@ -97,15 +97,15 @@
 
    // Constructors --------------------------------------------------
 
-   public MessagingServerControlImpl(final PostOffice postOffice,
-                                 final Configuration configuration,
-                                 final ResourceManager resourceManager,
-                                 final RemotingService remotingService,
-                                 final MessagingServer messagingServer,
-                                 final MessageCounterManager messageCounterManager,
-                                 final NotificationBroadcasterSupport broadcaster) throws Exception
+   public MessagingServerControlImpl(final ClusterQueueStateManager clusterQueueStateManager,
+                                     final Configuration configuration,
+                                     final ResourceManager resourceManager,
+                                     final RemotingService remotingService,
+                                     final MessagingServer messagingServer,
+                                     final MessageCounterManager messageCounterManager,
+                                     final NotificationBroadcasterSupport broadcaster) throws Exception
    {
-      this.postOffice = postOffice;
+      this.clusterQueueStateManager = clusterQueueStateManager;
       this.configuration = configuration;
       this.resourceManager = resourceManager;
       this.remotingService = remotingService;
@@ -151,19 +151,20 @@
 
    public String[] getInterceptorClassNames()
    {
-      return configuration.getInterceptorClassNames().toArray(new String[configuration.getInterceptorClassNames().size()]);
+      return configuration.getInterceptorClassNames().toArray(new String[configuration.getInterceptorClassNames()
+                                                                                      .size()]);
    }
 
    public int getAIOBufferSize()
    {
       return configuration.getAIOBufferSize();
    }
-   
+
    public int getAIOBufferTimeout()
    {
       return configuration.getAIOBufferTimeout();
    }
-   
+
    public String getJournalDirectory()
    {
       return configuration.getJournalDirectory();
@@ -203,7 +204,7 @@
    {
       return configuration.getScheduledThreadPoolMaxSize();
    }
-   
+
    public int getThreadPoolMaxSize()
    {
       return configuration.getThreadPoolMaxSize();
@@ -467,39 +468,39 @@
    public Object[] getConnectors() throws Exception
    {
       Collection<TransportConfiguration> connectorConfigurations = configuration.getConnectorConfigurations().values();
-      
+
       Object[] ret = new Object[connectorConfigurations.size()];
-      
+
       int i = 0;
-      for (TransportConfiguration config: connectorConfigurations)
+      for (TransportConfiguration config : connectorConfigurations)
       {
          Object[] tc = new Object[3];
-         
+
          tc[0] = config.getName();
          tc[1] = config.getFactoryClassName();
          tc[2] = config.getParams();
-         
+
          ret[i++] = tc;
       }
-      
+
       return ret;
    }
-   
+
    public String getConnectorsAsJSON() throws Exception
    {
       JSONArray array = new JSONArray();
-      
-      for (TransportConfiguration config: configuration.getConnectorConfigurations().values())
+
+      for (TransportConfiguration config : configuration.getConnectorConfigurations().values())
       {
          array.put(new JSONObject(config));
       }
-      
+
       return array.toString();
    }
 
    public void sendQueueInfoToQueue(final String queueName, final String address) throws Exception
    {
-      postOffice.sendQueueInfoToQueue(new SimpleString(queueName), new SimpleString(address));
+      clusterQueueStateManager.sendQueueInfoToQueue(new SimpleString(queueName), new SimpleString(address));
    }
 
    // NotificationEmitter implementation ----------------------------

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/QueueControlImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/QueueControlImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/management/impl/QueueControlImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -155,7 +155,7 @@
 
    public long getPersistenceID()
    {
-      return queue.getPersistenceID();
+      return queue.getID();
    }
 
    public long getScheduledCount()

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/paging/impl/PagingStoreImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/paging/impl/PagingStoreImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/paging/impl/PagingStoreImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -30,6 +30,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -47,6 +48,7 @@
 import org.jboss.messaging.core.persistence.StorageManager;
 import org.jboss.messaging.core.postoffice.PostOffice;
 import org.jboss.messaging.core.server.ServerMessage;
+import org.jboss.messaging.core.server.replication.impl.StatefulObjectReadWriteLock;
 import org.jboss.messaging.core.settings.impl.AddressSettings;
 import org.jboss.messaging.core.transaction.Transaction;
 import org.jboss.messaging.core.transaction.TransactionPropertyIndexes;
@@ -114,6 +116,8 @@
     * We need to perform checks on currentPage with minimal locking
     * */
    private final ReadWriteLock currentPageLock = new ReentrantReadWriteLock();
+   
+   //private final Lock lock = StatefulObjectReadWriteLock.createLock().writeLock();
 
    private volatile boolean running = false;
 
@@ -299,7 +303,6 @@
       }
    }
 
-   // TODO all of this can be simplified
    public boolean page(final PagedMessage message, final boolean sync, final boolean duplicateDetection) throws Exception
    {
       if (!running)

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/journal/JournalStorageManager.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -144,9 +144,13 @@
    
    private final int perfBlastPages;
 
+   private boolean backup;
+   
    public JournalStorageManager(final Configuration config, final Executor executor)
    {     
       this.executor = executor;
+      
+      backup = config.isBackup();
 
       if (config.getJournalType() != JournalType.NIO && config.getJournalType() != JournalType.ASYNCIO)
       {
@@ -245,6 +249,8 @@
    public long generateUniqueID()
    {            
       long id = idGenerator.generateID();
+      
+      log.info("Generating unique id on backup " + backup + " id " + id, new Exception());
 
       return id;
    }
@@ -306,7 +312,7 @@
    public void updateScheduledDeliveryTime(final MessageReference ref) throws Exception
    {
       ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(),
-                                                                         ref.getQueue().getPersistenceID());
+                                                                         ref.getQueue().getID());
 
       messageJournal.appendUpdateRecord(ref.getMessage().getMessageID(),
                                         SET_SCHEDULED_DELIVERY_TIME,
@@ -405,7 +411,7 @@
    public void updateScheduledDeliveryTimeTransactional(final long txID, final MessageReference ref) throws Exception
    {
       ScheduledDeliveryEncoding encoding = new ScheduledDeliveryEncoding(ref.getScheduledDeliveryTime(),
-                                                                         ref.getQueue().getPersistenceID());
+                                                                         ref.getQueue().getID());
 
       messageJournal.appendUpdateRecordTransactional(txID,
                                                      ref.getMessage().getMessageID(),
@@ -463,7 +469,7 @@
 
    public void updateDeliveryCount(final MessageReference ref) throws Exception
    {
-      DeliveryCountUpdateEncoding updateInfo = new DeliveryCountUpdateEncoding(ref.getQueue().getPersistenceID(),
+      DeliveryCountUpdateEncoding updateInfo = new DeliveryCountUpdateEncoding(ref.getQueue().getID(),
                                                                                ref.getDeliveryCount());
 
       messageJournal.appendUpdateRecord(ref.getMessage().getMessageID(),
@@ -912,11 +918,7 @@
                                                                                           binding.getAddress(),
                                                                                           filterString);
 
-      long id = this.generateUniqueID();
-
-      queue.setPersistenceID(id);
-
-      bindingsJournal.appendAddRecord(id, QUEUE_BINDING_RECORD, bindingEncoding, true);
+      bindingsJournal.appendAddRecord(queue.getID(), QUEUE_BINDING_RECORD, bindingEncoding, true);
    }
 
    public void deleteQueueBinding(final long queueBindingID) throws Exception

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/nullpm/NullStorageManager.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/nullpm/NullStorageManager.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/persistence/impl/nullpm/NullStorageManager.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -61,6 +61,13 @@
 
    private volatile boolean started;
    
+   private boolean backup;
+   
+   public NullStorageManager(final boolean backup)
+   {
+      this.backup = backup;
+   }
+   
    public UUID getPersistentID()
    {
       return id;
@@ -186,6 +193,8 @@
    {
       long id = idSequence.getAndIncrement();
       
+    //  log.info("Generating unique id on backup " + backup + " id " + id, new Exception());
+      
       return id;
    }
    

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/AddressManager.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/AddressManager.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/AddressManager.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -34,7 +34,7 @@
  */
 public interface AddressManager
 {
-   boolean addBinding(Binding binding);
+   void addBinding(Binding binding);
 
    Binding removeBinding(SimpleString uniqueName);
 

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/PostOffice.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/PostOffice.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/PostOffice.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -73,7 +73,7 @@
 
    DuplicateIDCache getDuplicateIDCache(SimpleString address);
    
-   void sendQueueInfoToQueue(SimpleString queueName, SimpleString address) throws Exception;
+   //void sendQueueInfoToQueue(SimpleString queueName, SimpleString address) throws Exception;
    
-   Object getNotificationLock();     
+  // Object getNotificationLock();     
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/PostOfficeImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/PostOfficeImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/PostOfficeImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -32,6 +32,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.locks.ReadWriteLock;
 
 import org.jboss.messaging.core.buffers.ChannelBuffers;
 import org.jboss.messaging.core.client.management.impl.ManagementHelper;
@@ -54,11 +55,11 @@
 import org.jboss.messaging.core.postoffice.DuplicateIDCache;
 import org.jboss.messaging.core.postoffice.PostOffice;
 import org.jboss.messaging.core.postoffice.QueueInfo;
-import org.jboss.messaging.core.server.MessagingServer;
 import org.jboss.messaging.core.server.Queue;
 import org.jboss.messaging.core.server.QueueFactory;
 import org.jboss.messaging.core.server.ServerMessage;
 import org.jboss.messaging.core.server.impl.ServerMessageImpl;
+import org.jboss.messaging.core.server.replication.impl.StatefulObjectReadWriteLock;
 import org.jboss.messaging.core.settings.HierarchicalRepository;
 import org.jboss.messaging.core.settings.impl.AddressSettings;
 import org.jboss.messaging.core.transaction.Transaction;
@@ -78,14 +79,12 @@
  * @author <a href="jmesnil at redhat.com">Jeff Mesnil</a>
  * @author <a href="csuconic at redhat.com">Clebert Suconic</a>
  */
-public class PostOfficeImpl implements PostOffice, NotificationListener
+public class PostOfficeImpl implements PostOffice // , NotificationListener
 {
    private static final Logger log = Logger.getLogger(PostOfficeImpl.class);
 
-   public static final SimpleString HDR_RESET_QUEUE_DATA = new SimpleString("_JBM_RESET_QUEUE_DATA");
+   // public static final SimpleString HDR_RESET_QUEUE_DATA = new SimpleString("_JBM_RESET_QUEUE_DATA");
 
-   private MessagingServer server;
-
    private final AddressManager addressManager;
 
    private final QueueFactory queueFactory;
@@ -105,7 +104,7 @@
    private final long reaperPeriod;
 
    private final int reaperPriority;
-   
+
    private Reaper reaper;
 
    private final ConcurrentMap<SimpleString, DuplicateIDCache> duplicateIDCaches = new ConcurrentHashMap<SimpleString, DuplicateIDCache>();
@@ -124,16 +123,17 @@
 
    private Set<Integer> transientIDs = new HashSet<Integer>();
 
-   private Map<SimpleString, QueueInfo> queueInfos = new HashMap<SimpleString, QueueInfo>();
+   // private Map<SimpleString, QueueInfo> queueInfos = new HashMap<SimpleString, QueueInfo>();
 
-   private final Object notificationLock = new Object();
+   // private final Object notificationLock = new Object();
 
-   private final org.jboss.messaging.utils.ExecutorFactory redistributorExecutorFactory;
+   // private final org.jboss.messaging.utils.ExecutorFactory redistributorExecutorFactory;
+   //
+   // private final HierarchicalRepository<AddressSettings> addressSettingsRepository;
 
-   private final HierarchicalRepository<AddressSettings> addressSettingsRepository;
+   private final ReadWriteLock lock;
 
-   public PostOfficeImpl(final MessagingServer server,
-                         final StorageManager storageManager,
+   public PostOfficeImpl(final StorageManager storageManager,
                          final PagingManager pagingManager,
                          final QueueFactory bindableFactory,
                          final ManagementService managementService,
@@ -142,13 +142,11 @@
                          final boolean enableWildCardRouting,
                          final boolean backup,
                          final int idCacheSize,
-                         final boolean persistIDCache,
-                         final ExecutorFactory orderedExecutorFactory,
-                         HierarchicalRepository<AddressSettings> addressSettingsRepository)
+                         final boolean persistIDCache)
+   // final ExecutorFactory orderedExecutorFactory,
+   // HierarchicalRepository<AddressSettings> addressSettingsRepository)
 
    {
-      this.server = server;
-
       this.storageManager = storageManager;
 
       this.queueFactory = bindableFactory;
@@ -176,16 +174,18 @@
 
       this.persistIDCache = persistIDCache;
 
-      this.redistributorExecutorFactory = orderedExecutorFactory;
+      // this.redistributorExecutorFactory = orderedExecutorFactory;
 
-      this.addressSettingsRepository = addressSettingsRepository;
+      // this.addressSettingsRepository = addressSettingsRepository;
+      
+      lock = new StatefulObjectReadWriteLock("postoffice", storageManager.generateUniqueID(), 0);
    }
 
    // MessagingComponent implementation ---------------------------------------
 
    public synchronized void start() throws Exception
    {
-      managementService.addNotificationListener(this);
+      // managementService.addNotificationListener(this);
 
       if (pagingManager != null)
       {
@@ -202,21 +202,21 @@
 
       started = true;
    }
-     
+
    public synchronized void stop() throws Exception
-   {
-      managementService.removeNotificationListener(this);
+   {      
+      // managementService.removeNotificationListener(this);
 
       if (reaper != null)
       {
          reaper.stop();
-         
+
          expiryReaper.join();
       }
 
       addressManager.clear();
 
-      queueInfos.clear();
+      // queueInfos.clear();
 
       transientIDs.clear();
 
@@ -230,256 +230,264 @@
 
    // NotificationListener implementation -------------------------------------
 
-   public void onNotification(final Notification notification)
-   {
-      synchronized (notificationLock)
-      {
-         NotificationType type = notification.getType();
+   // public void onNotification(final Notification notification)
+   // {
+   // synchronized (notificationLock)
+   // {
+   // NotificationType type = notification.getType();
+   //
+   // switch (type)
+   // {
+   // case BINDING_ADDED:
+   // {
+   // TypedProperties props = notification.getProperties();
+   //
+   // Integer bindingType = (Integer)props.getProperty(ManagementHelper.HDR_BINDING_TYPE);
+   //
+   // if (bindingType == null)
+   // {
+   // throw new IllegalArgumentException("Binding type not specified");
+   // }
+   //
+   // if (bindingType == BindingType.DIVERT_INDEX)
+   // {
+   // // We don't propagate diverts
+   // return;
+   // }
+   //
+   // SimpleString routingName = (SimpleString)props.getProperty(ManagementHelper.HDR_ROUTING_NAME);
+   //
+   // SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
+   //
+   // SimpleString address = (SimpleString)props.getProperty(ManagementHelper.HDR_ADDRESS);
+   //
+   // Integer transientID = (Integer)props.getProperty(ManagementHelper.HDR_BINDING_ID);
+   //
+   // SimpleString filterString = (SimpleString)props.getProperty(ManagementHelper.HDR_FILTERSTRING);
+   //
+   // Integer distance = (Integer)props.getProperty(ManagementHelper.HDR_DISTANCE);
+   //
+   // QueueInfo info = new QueueInfo(routingName, clusterName, address, filterString, transientID, distance);
+   //
+   // queueInfos.put(clusterName, info);
+   //
+   // break;
+   // }
+   // case BINDING_REMOVED:
+   // {
+   // TypedProperties props = notification.getProperties();
+   //
+   // SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
+   //
+   // if (clusterName == null)
+   // {
+   // throw new IllegalStateException("No cluster name");
+   // }
+   //
+   // QueueInfo info = queueInfos.remove(clusterName);
+   //
+   // if (info == null)
+   // {
+   // throw new IllegalStateException("Cannot find queue info for queue " + clusterName);
+   // }
+   //
+   // break;
+   // }
+   // case CONSUMER_CREATED:
+   // {
+   // TypedProperties props = notification.getProperties();
+   //
+   // SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
+   //
+   // if (clusterName == null)
+   // {
+   // throw new IllegalStateException("No cluster name");
+   // }
+   //
+   // SimpleString filterString = (SimpleString)props.getProperty(ManagementHelper.HDR_FILTERSTRING);
+   //
+   // QueueInfo info = queueInfos.get(clusterName);
+   //
+   // if (info == null)
+   // {
+   // throw new IllegalStateException("Cannot find queue info for queue " + clusterName);
+   // }
+   //
+   // info.incrementConsumers();
+   //
+   // if (filterString != null)
+   // {
+   // List<SimpleString> filterStrings = info.getFilterStrings();
+   //
+   // if (filterStrings == null)
+   // {
+   // filterStrings = new ArrayList<SimpleString>();
+   //
+   // info.setFilterStrings(filterStrings);
+   // }
+   //
+   // filterStrings.add(filterString);
+   // }
+   //
+   // Integer distance = (Integer)props.getProperty(ManagementHelper.HDR_DISTANCE);
+   //
+   // if (distance == null)
+   // {
+   // throw new IllegalStateException("No distance");
+   // }
+   //
+   // if (distance > 0)
+   // {
+   // SimpleString queueName = (SimpleString)props.getProperty(ManagementHelper.HDR_ROUTING_NAME);
+   //
+   // if (queueName == null)
+   // {
+   // throw new IllegalStateException("No queue name");
+   // }
+   //
+   // Binding binding = getBinding(queueName);
+   //
+   // if (binding != null)
+   // {
+   // // We have a local queue
+   // Queue queue = (Queue)binding.getBindable();
+   //
+   // AddressSettings addressSettings = addressSettingsRepository.getMatch(binding.getAddress()
+   // .toString());
+   //
+   // long redistributionDelay = addressSettings.getRedistributionDelay();
+   //
+   // if (redistributionDelay != -1)
+   // {
+   // queue.addRedistributor(redistributionDelay, redistributorExecutorFactory.getExecutor());
+   // }
+   // }
+   // }
+   //
+   // break;
+   // }
+   // case CONSUMER_CLOSED:
+   // {
+   // TypedProperties props = notification.getProperties();
+   //
+   // SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
+   //
+   // if (clusterName == null)
+   // {
+   // throw new IllegalStateException("No distance");
+   // }
+   //
+   // SimpleString filterString = (SimpleString)props.getProperty(ManagementHelper.HDR_FILTERSTRING);
+   //
+   // QueueInfo info = queueInfos.get(clusterName);
+   //
+   // if (info == null)
+   // {
+   // throw new IllegalStateException("Cannot find queue info for queue " + clusterName);
+   // }
+   //
+   // info.decrementConsumers();
+   //
+   // if (filterString != null)
+   // {
+   // List<SimpleString> filterStrings = info.getFilterStrings();
+   //
+   // filterStrings.remove(filterString);
+   // }
+   //
+   // if (info.getNumberOfConsumers() == 0)
+   // {
+   // Integer distance = (Integer)props.getProperty(ManagementHelper.HDR_DISTANCE);
+   //
+   // if (distance == null)
+   // {
+   // throw new IllegalStateException("No cluster name");
+   // }
+   //
+   // if (distance == 0)
+   // {
+   // SimpleString queueName = (SimpleString)props.getProperty(ManagementHelper.HDR_ROUTING_NAME);
+   //
+   // if (queueName == null)
+   // {
+   // throw new IllegalStateException("No queue name");
+   // }
+   //
+   // Binding binding = getBinding(queueName);
+   //
+   // if (binding == null)
+   // {
+   // throw new IllegalStateException("No queue " + queueName);
+   // }
+   //
+   // Queue queue = (Queue)binding.getBindable();
+   //
+   // AddressSettings addressSettings = addressSettingsRepository.getMatch(binding.getAddress()
+   // .toString());
+   //
+   // long redistributionDelay = addressSettings.getRedistributionDelay();
+   //
+   // if (redistributionDelay != -1)
+   // {
+   // queue.addRedistributor(redistributionDelay, redistributorExecutorFactory.getExecutor());
+   // }
+   // }
+   // }
+   //
+   // break;
+   // }
+   // case SECURITY_AUTHENTICATION_VIOLATION:
+   // case SECURITY_PERMISSION_VIOLATION:
+   // break;
+   // default:
+   // {
+   // throw new IllegalArgumentException("Invalid type " + type);
+   // }
+   //
+   // }
+   // }
+   // }
 
-         switch (type)
-         {
-            case BINDING_ADDED:
-            {
-               TypedProperties props = notification.getProperties();
-
-               Integer bindingType = (Integer)props.getProperty(ManagementHelper.HDR_BINDING_TYPE);
-
-               if (bindingType == null)
-               {
-                  throw new IllegalArgumentException("Binding type not specified");
-               }
-
-               if (bindingType == BindingType.DIVERT_INDEX)
-               {
-                  // We don't propagate diverts
-                  return;
-               }
-
-               SimpleString routingName = (SimpleString)props.getProperty(ManagementHelper.HDR_ROUTING_NAME);
-
-               SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
-
-               SimpleString address = (SimpleString)props.getProperty(ManagementHelper.HDR_ADDRESS);
-
-               Integer transientID = (Integer)props.getProperty(ManagementHelper.HDR_BINDING_ID);
-
-               SimpleString filterString = (SimpleString)props.getProperty(ManagementHelper.HDR_FILTERSTRING);
-
-               Integer distance = (Integer)props.getProperty(ManagementHelper.HDR_DISTANCE);
-
-               QueueInfo info = new QueueInfo(routingName, clusterName, address, filterString, transientID, distance);
-
-               queueInfos.put(clusterName, info);
-
-               break;
-            }
-            case BINDING_REMOVED:
-            {
-               TypedProperties props = notification.getProperties();
-
-               SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
-
-               if (clusterName == null)
-               {
-                  throw new IllegalStateException("No cluster name");
-               }
-
-               QueueInfo info = queueInfos.remove(clusterName);
-
-               if (info == null)
-               {
-                  throw new IllegalStateException("Cannot find queue info for queue " + clusterName);
-               }
-
-               break;
-            }
-            case CONSUMER_CREATED:
-            {
-               TypedProperties props = notification.getProperties();
-
-               SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
-
-               if (clusterName == null)
-               {
-                  throw new IllegalStateException("No cluster name");
-               }
-
-               SimpleString filterString = (SimpleString)props.getProperty(ManagementHelper.HDR_FILTERSTRING);
-
-               QueueInfo info = queueInfos.get(clusterName);
-
-               if (info == null)
-               {
-                  throw new IllegalStateException("Cannot find queue info for queue " + clusterName);
-               }
-
-               info.incrementConsumers();
-
-               if (filterString != null)
-               {
-                  List<SimpleString> filterStrings = info.getFilterStrings();
-
-                  if (filterStrings == null)
-                  {
-                     filterStrings = new ArrayList<SimpleString>();
-
-                     info.setFilterStrings(filterStrings);
-                  }
-
-                  filterStrings.add(filterString);
-               }
-
-               Integer distance = (Integer)props.getProperty(ManagementHelper.HDR_DISTANCE);
-
-               if (distance == null)
-               {
-                  throw new IllegalStateException("No distance");
-               }
-
-               if (distance > 0)
-               {
-                  SimpleString queueName = (SimpleString)props.getProperty(ManagementHelper.HDR_ROUTING_NAME);
-
-                  if (queueName == null)
-                  {
-                     throw new IllegalStateException("No queue name");
-                  }
-
-                  Binding binding = getBinding(queueName);
-
-                  if (binding != null)
-                  {
-                     // We have a local queue
-                     Queue queue = (Queue)binding.getBindable();
-
-                     AddressSettings addressSettings = addressSettingsRepository.getMatch(binding.getAddress()
-                                                                                                 .toString());
-
-                     long redistributionDelay = addressSettings.getRedistributionDelay();
-
-                     if (redistributionDelay != -1)
-                     {
-                        queue.addRedistributor(redistributionDelay, redistributorExecutorFactory.getExecutor(),
-                                               server.getReplicatingChannel());
-                     }
-                  }
-               }
-
-               break;
-            }
-            case CONSUMER_CLOSED:
-            {
-               TypedProperties props = notification.getProperties();
-
-               SimpleString clusterName = (SimpleString)props.getProperty(ManagementHelper.HDR_CLUSTER_NAME);
-
-               if (clusterName == null)
-               {
-                  throw new IllegalStateException("No distance");
-               }
-
-               SimpleString filterString = (SimpleString)props.getProperty(ManagementHelper.HDR_FILTERSTRING);
-
-               QueueInfo info = queueInfos.get(clusterName);
-
-               if (info == null)
-               {
-                  throw new IllegalStateException("Cannot find queue info for queue " + clusterName);
-               }
-
-               info.decrementConsumers();
-
-               if (filterString != null)
-               {
-                  List<SimpleString> filterStrings = info.getFilterStrings();
-
-                  filterStrings.remove(filterString);
-               }
-
-               if (info.getNumberOfConsumers() == 0)
-               {
-                  Integer distance = (Integer)props.getProperty(ManagementHelper.HDR_DISTANCE);
-
-                  if (distance == null)
-                  {
-                     throw new IllegalStateException("No cluster name");
-                  }
-
-                  if (distance == 0)
-                  {
-                     SimpleString queueName = (SimpleString)props.getProperty(ManagementHelper.HDR_ROUTING_NAME);
-
-                     if (queueName == null)
-                     {
-                        throw new IllegalStateException("No queue name");
-                     }
-
-                     Binding binding = getBinding(queueName);
-
-                     if (binding == null)
-                     {
-                        throw new IllegalStateException("No queue " + queueName);
-                     }
-
-                     Queue queue = (Queue)binding.getBindable();
-
-                     AddressSettings addressSettings = addressSettingsRepository.getMatch(binding.getAddress()
-                                                                                                 .toString());
-
-                     long redistributionDelay = addressSettings.getRedistributionDelay();
-
-                     if (redistributionDelay != -1)
-                     {
-                        queue.addRedistributor(redistributionDelay, redistributorExecutorFactory.getExecutor(),
-                                               server.getReplicatingChannel());
-                     }
-                  }
-               }
-
-               break;
-            }
-            case SECURITY_AUTHENTICATION_VIOLATION:
-            case SECURITY_PERMISSION_VIOLATION:
-               break;
-            default:
-            {
-               throw new IllegalArgumentException("Invalid type " + type);
-            }
-
-         }
-      }
-   }
-
    // PostOffice implementation -----------------------------------------------
 
-   // TODO - needs to be synchronized to prevent happening concurrently with activate().
+   // TODO - needs to be locked to prevent happening concurrently with activate().
    // (and possible removeBinding and other methods)
    // Otherwise can have situation where createQueue comes in before failover, then failover occurs
    // and post office is activated but queue remains unactivated after failover so delivery never occurs
    // even though failover is complete
-   public synchronized void addBinding(final Binding binding) throws Exception
+   public void addBinding(final Binding binding) throws Exception
    {
-      binding.setID(generateTransientID());
+      lock.writeLock().lock();
+      try
+      {
+         binding.setID(generateTransientID());
 
-      boolean existed = addressManager.addBinding(binding);
+         boolean addressExists = addressManager.getBindingsForRoutingAddress(binding.getAddress()) != null;
 
-      if (binding.getType() == BindingType.LOCAL_QUEUE)
-      {
-         Queue queue = (Queue)binding.getBindable();
+         addressManager.addBinding(binding);
 
-         if (backup)
+         if (binding.getType() == BindingType.LOCAL_QUEUE)
          {
-            queue.setBackup();
-         }
+            Queue queue = (Queue)binding.getBindable();
 
-         managementService.registerQueue(queue, binding.getAddress(), storageManager);
+            if (backup)
+            {
+               queue.setBackup();
+            }
 
-         if (!existed)
-         {
-            managementService.registerAddress(binding.getAddress());
+            managementService.registerQueue(queue, binding.getAddress(), storageManager);
+
+            if (!addressExists)
+            {
+               managementService.registerAddress(binding.getAddress());
+            }
          }
       }
-
+      finally
+      {
+         lock.writeLock().unlock();
+      }
+      
       TypedProperties props = new TypedProperties();
 
       props.putIntProperty(ManagementHelper.HDR_BINDING_TYPE, binding.getType().toInt());
@@ -499,40 +507,54 @@
       if (filter != null)
       {
          props.putStringProperty(ManagementHelper.HDR_FILTERSTRING, filter.getFilterString());
-      }
-
+      }        
+      
       String uid = UUIDGenerator.getInstance().generateStringUUID();
 
+      log.info("*** sending notification");
       managementService.sendNotification(new Notification(uid, NotificationType.BINDING_ADDED, props));
    }
 
-   public synchronized Binding removeBinding(final SimpleString uniqueName) throws Exception
+   public Binding removeBinding(final SimpleString uniqueName) throws Exception
    {
-      Binding binding = addressManager.removeBinding(uniqueName);
-      if (binding == null)
+      lock.writeLock().lock();
+      Binding binding;
+      try
       {
-         throw new MessagingException(MessagingException.QUEUE_DOES_NOT_EXIST);
-      }
+         binding = addressManager.removeBinding(uniqueName);
+         if (binding == null)
+         {
+            throw new MessagingException(MessagingException.QUEUE_DOES_NOT_EXIST);
+         }
 
-      if (binding.getType() == BindingType.LOCAL_QUEUE)
-      {
-         managementService.unregisterQueue(uniqueName, binding.getAddress());
+         if (binding.getType() == BindingType.LOCAL_QUEUE)
+         {
+            managementService.unregisterQueue(uniqueName, binding.getAddress());
 
-         if (addressManager.getBindingsForRoutingAddress(binding.getAddress()) == null)
+            if (addressManager.getBindingsForRoutingAddress(binding.getAddress()) == null)
+            {
+               managementService.unregisterAddress(binding.getAddress());
+            }
+         }
+         else if (binding.getType() == BindingType.DIVERT)
          {
-            managementService.unregisterAddress(binding.getAddress());
+            managementService.unregisterDivert(uniqueName);
+
+            if (addressManager.getBindingsForRoutingAddress(binding.getAddress()) == null)
+            {
+               managementService.unregisterAddress(binding.getAddress());
+            }
          }
+         
+         releaseTransientID(binding.getID());
+
+         
       }
-      else if (binding.getType() == BindingType.DIVERT)
+      finally
       {
-         managementService.unregisterDivert(uniqueName);
-
-         if (addressManager.getBindingsForRoutingAddress(binding.getAddress()) == null)
-         {
-            managementService.unregisterAddress(binding.getAddress());
-         }
+         lock.writeLock().unlock();
       }
-
+      
       TypedProperties props = new TypedProperties();
 
       props.putStringProperty(ManagementHelper.HDR_ADDRESS, binding.getAddress());
@@ -544,32 +566,54 @@
       props.putIntProperty(ManagementHelper.HDR_DISTANCE, binding.getDistance());
 
       managementService.sendNotification(new Notification(null, NotificationType.BINDING_REMOVED, props));
-
-      releaseTransientID(binding.getID());
-
+      
       return binding;
    }
 
    public Bindings getBindingsForAddress(final SimpleString address)
    {
-      Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
+      lock.readLock().lock();
+      try
+      {
+         Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
 
-      if (bindings == null)
+         if (bindings == null)
+         {
+            bindings = new BindingsImpl();
+         }
+
+         return bindings;
+      }
+      finally
       {
-         bindings = new BindingsImpl();
+         lock.readLock().unlock();
       }
-
-      return bindings;
    }
 
    public Binding getBinding(final SimpleString name)
    {
-      return addressManager.getBinding(name);
+      lock.readLock().lock();
+      try
+      {
+         return addressManager.getBinding(name);
+      }
+      finally
+      {
+         lock.readLock().unlock();
+      }
    }
-   
+
    public Bindings getMatchingBindings(final SimpleString address)
    {
-      return addressManager.getMatchingBindings(address);
+      lock.readLock().lock();
+      try
+      {
+         return addressManager.getMatchingBindings(address);
+      }
+      finally
+      {
+         lock.readLock().unlock();
+      }
    }
 
    public void route(final ServerMessage message, Transaction tx) throws Exception
@@ -577,7 +621,7 @@
       SimpleString address = message.getDestination();
 
       byte[] duplicateIDBytes = null;
-      
+
       Object duplicateID = message.getProperty(MessageImpl.HDR_DUPLICATE_DETECTION_ID);
 
       DuplicateIDCache cache = null;
@@ -594,7 +638,7 @@
          {
             duplicateIDBytes = (byte[])duplicateID;
          }
-         
+
          if (cache.contains(duplicateIDBytes))
          {
             if (tx == null)
@@ -624,41 +668,49 @@
 
             startedTx = true;
          }
-         
+
          cache.addToCache(duplicateIDBytes, tx);
       }
 
-      if (tx == null)
+      lock.readLock().lock();
+      try
       {
-         if (pagingManager.page(message, true))
+         if (tx == null)
          {
-            return;
+            if (pagingManager.page(message, true))
+            {
+               return;
+            }
          }
-      }
-      else
-      {
-         SimpleString destination = message.getDestination();
+         else
+         {
+            SimpleString destination = message.getDestination();
 
-         boolean depage = tx.getProperty(TransactionPropertyIndexes.IS_DEPAGE) != null;
+            boolean depage = tx.getProperty(TransactionPropertyIndexes.IS_DEPAGE) != null;
 
-         if (!depage && pagingManager.isPaging(destination))
-         {
-            getPageOperation(tx).addMessageToPage(message);
+            if (!depage && pagingManager.isPaging(destination))
+            {
+               getPageOperation(tx).addMessageToPage(message);
 
-            return;
+               return;
+            }
          }
-      }
 
-      Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
+         Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
 
-      if (bindings != null)
-      {
-         bindings.route(message, tx);
+         if (bindings != null)
+         {
+            bindings.route(message, tx);
+         }
+
+         if (startedTx)
+         {
+            tx.commit();
+         }
       }
-
-      if (startedTx)
+      finally
       {
-         tx.commit();
+         lock.readLock().unlock();
       }
    }
 
@@ -669,15 +721,23 @@
 
    public boolean redistribute(final ServerMessage message, final Queue originatingQueue, final Transaction tx) throws Exception
    {
-      Bindings bindings = addressManager.getBindingsForRoutingAddress(message.getDestination());
+      lock.readLock().lock();
+      try
+      {
+         Bindings bindings = addressManager.getBindingsForRoutingAddress(message.getDestination());
 
-      if (bindings != null)
-      {
-         return bindings.redistribute(message, originatingQueue, tx);
+         if (bindings != null)
+         {
+            return bindings.redistribute(message, originatingQueue, tx);
+         }
+         else
+         {
+            return false;
+         }
       }
-      else
+      finally
       {
-         return false;
+         lock.readLock().unlock();
       }
    }
 
@@ -734,88 +794,88 @@
 
       return cache;
    }
-   
-   public Object getNotificationLock()
-   {
-      return notificationLock;
-   }
 
-   public void sendQueueInfoToQueue(final SimpleString queueName, final SimpleString address) throws Exception
-   {
-      // We send direct to the queue so we can send it to the same queue that is bound to the notifications adress -
-      // this is crucial for ensuring
-      // that queue infos and notifications are received in a contiguous consistent stream
-      Binding binding = addressManager.getBinding(queueName);
+   // public Object getNotificationLock()
+   // {
+   // return notificationLock;
+   // }
 
-      if (binding == null)
-      {
-         throw new IllegalStateException("Cannot find queue " + queueName);
-      }
+   // public void sendQueueInfoToQueue(final SimpleString queueName, final SimpleString address) throws Exception
+   // {
+   // // We send direct to the queue so we can send it to the same queue that is bound to the notifications adress -
+   // // this is crucial for ensuring
+   // // that queue infos and notifications are received in a contiguous consistent stream
+   // Binding binding = addressManager.getBinding(queueName);
+   //
+   // if (binding == null)
+   // {
+   // throw new IllegalStateException("Cannot find queue " + queueName);
+   // }
+   //
+   // Queue queue = (Queue)binding.getBindable();
+   //
+   // // Need to lock to make sure all queue info and notifications are in the correct order with no gaps
+   // synchronized (notificationLock)
+   // {
+   // // First send a reset message
+   //
+   // ServerMessage message = new ServerMessageImpl(storageManager.generateUniqueID());
+   // message.setBody(ChannelBuffers.EMPTY_BUFFER);
+   // message.setDestination(queueName);
+   // message.putBooleanProperty(HDR_RESET_QUEUE_DATA, true);
+   // queue.preroute(message, null);
+   // queue.route(message, null);
+   //
+   // for (QueueInfo info : queueInfos.values())
+   // {
+   // if (info.getAddress().startsWith(address))
+   // {
+   // message = createQueueInfoMessage(NotificationType.BINDING_ADDED, queueName);
+   //
+   // message.putStringProperty(ManagementHelper.HDR_ADDRESS, info.getAddress());
+   // message.putStringProperty(ManagementHelper.HDR_CLUSTER_NAME, info.getClusterName());
+   // message.putStringProperty(ManagementHelper.HDR_ROUTING_NAME, info.getRoutingName());
+   // message.putIntProperty(ManagementHelper.HDR_BINDING_ID, info.getID());
+   // message.putStringProperty(ManagementHelper.HDR_FILTERSTRING, info.getFilterString());
+   // message.putIntProperty(ManagementHelper.HDR_DISTANCE, info.getDistance());
+   //
+   // routeDirect(queue, message);
+   //
+   // int consumersWithFilters = info.getFilterStrings() != null ? info.getFilterStrings().size() : 0;
+   //
+   // for (int i = 0; i < info.getNumberOfConsumers() - consumersWithFilters; i++)
+   // {
+   // message = createQueueInfoMessage(NotificationType.CONSUMER_CREATED, queueName);
+   //
+   // message.putStringProperty(ManagementHelper.HDR_ADDRESS, info.getAddress());
+   // message.putStringProperty(ManagementHelper.HDR_CLUSTER_NAME, info.getClusterName());
+   // message.putStringProperty(ManagementHelper.HDR_ROUTING_NAME, info.getRoutingName());
+   // message.putIntProperty(ManagementHelper.HDR_DISTANCE, info.getDistance());
+   //
+   // routeDirect(queue, message);
+   // }
+   //
+   // if (info.getFilterStrings() != null)
+   // {
+   // for (SimpleString filterString : info.getFilterStrings())
+   // {
+   // message = createQueueInfoMessage(NotificationType.CONSUMER_CREATED, queueName);
+   //
+   // message.putStringProperty(ManagementHelper.HDR_ADDRESS, info.getAddress());
+   // message.putStringProperty(ManagementHelper.HDR_CLUSTER_NAME, info.getClusterName());
+   // message.putStringProperty(ManagementHelper.HDR_ROUTING_NAME, info.getRoutingName());
+   // message.putStringProperty(ManagementHelper.HDR_FILTERSTRING, filterString);
+   // message.putIntProperty(ManagementHelper.HDR_DISTANCE, info.getDistance());
+   //
+   // routeDirect(queue, message);
+   // }
+   // }
+   // }
+   // }
+   // }
+   //
+   // }
 
-      Queue queue = (Queue)binding.getBindable();
-
-      // Need to lock to make sure all queue info and notifications are in the correct order with no gaps
-      synchronized (notificationLock)
-      {
-         // First send a reset message
-
-         ServerMessage message = new ServerMessageImpl(storageManager.generateUniqueID());
-         message.setBody(ChannelBuffers.EMPTY_BUFFER);
-         message.setDestination(queueName);
-         message.putBooleanProperty(HDR_RESET_QUEUE_DATA, true);
-         queue.preroute(message, null);
-         queue.route(message, null);
-
-         for (QueueInfo info : queueInfos.values())
-         {
-            if (info.getAddress().startsWith(address))
-            {
-               message = createQueueInfoMessage(NotificationType.BINDING_ADDED, queueName);
-
-               message.putStringProperty(ManagementHelper.HDR_ADDRESS, info.getAddress());
-               message.putStringProperty(ManagementHelper.HDR_CLUSTER_NAME, info.getClusterName());
-               message.putStringProperty(ManagementHelper.HDR_ROUTING_NAME, info.getRoutingName());
-               message.putIntProperty(ManagementHelper.HDR_BINDING_ID, info.getID());
-               message.putStringProperty(ManagementHelper.HDR_FILTERSTRING, info.getFilterString());
-               message.putIntProperty(ManagementHelper.HDR_DISTANCE, info.getDistance());
-
-               routeDirect(queue, message);
-
-               int consumersWithFilters = info.getFilterStrings() != null ? info.getFilterStrings().size() : 0;
-
-               for (int i = 0; i < info.getNumberOfConsumers() - consumersWithFilters; i++)
-               {
-                  message = createQueueInfoMessage(NotificationType.CONSUMER_CREATED, queueName);
-
-                  message.putStringProperty(ManagementHelper.HDR_ADDRESS, info.getAddress());
-                  message.putStringProperty(ManagementHelper.HDR_CLUSTER_NAME, info.getClusterName());
-                  message.putStringProperty(ManagementHelper.HDR_ROUTING_NAME, info.getRoutingName());
-                  message.putIntProperty(ManagementHelper.HDR_DISTANCE, info.getDistance());
-
-                  routeDirect(queue, message);
-               }
-
-               if (info.getFilterStrings() != null)
-               {
-                  for (SimpleString filterString : info.getFilterStrings())
-                  {
-                     message = createQueueInfoMessage(NotificationType.CONSUMER_CREATED, queueName);
-
-                     message.putStringProperty(ManagementHelper.HDR_ADDRESS, info.getAddress());
-                     message.putStringProperty(ManagementHelper.HDR_CLUSTER_NAME, info.getClusterName());
-                     message.putStringProperty(ManagementHelper.HDR_ROUTING_NAME, info.getRoutingName());
-                     message.putStringProperty(ManagementHelper.HDR_FILTERSTRING, filterString);
-                     message.putIntProperty(ManagementHelper.HDR_DISTANCE, info.getDistance());
-
-                     routeDirect(queue, message);
-                  }
-               }
-            }
-         }
-      }
-
-   }
-
    // Private -----------------------------------------------------------------
 
    private synchronized void startExpiryScanner()
@@ -823,41 +883,41 @@
       if (reaperPeriod > 0)
       {
          reaper = new Reaper();
-         
+
          expiryReaper = new Thread(reaper, "JBM-expiry-reaper");
-         
+
          expiryReaper.setPriority(reaperPriority);
-         
+
          expiryReaper.start();
       }
    }
-   
-   private void routeDirect(final Queue queue, final ServerMessage message) throws Exception
-   {
-      if (queue.getFilter() == null || queue.getFilter().match(message))
-      {
-         queue.preroute(message, null);
-         queue.route(message, null);
-      }
-   }
 
-   private ServerMessage createQueueInfoMessage(final NotificationType type, final SimpleString queueName)
-   {
-      ServerMessage message = new ServerMessageImpl(storageManager.generateUniqueID());
-      message.setBody(ChannelBuffers.EMPTY_BUFFER);
+   // private void routeDirect(final Queue queue, final ServerMessage message) throws Exception
+   // {
+   // if (queue.getFilter() == null || queue.getFilter().match(message))
+   // {
+   // queue.preroute(message, null);
+   // queue.route(message, null);
+   // }
+   // }
+   //
+   // private ServerMessage createQueueInfoMessage(final NotificationType type, final SimpleString queueName)
+   // {
+   // ServerMessage message = new ServerMessageImpl(storageManager.generateUniqueID());
+   // message.setBody(ChannelBuffers.EMPTY_BUFFER);
+   //
+   // message.setDestination(queueName);
+   //
+   // String uid = UUIDGenerator.getInstance().generateStringUUID();
+   //
+   // message.putStringProperty(ManagementHelper.HDR_NOTIFICATION_TYPE, new SimpleString(type.toString()));
+   // message.putLongProperty(ManagementHelper.HDR_NOTIFICATION_TIMESTAMP, System.currentTimeMillis());
+   //
+   // message.putStringProperty(new SimpleString("foobar"), new SimpleString(uid));
+   //
+   // return message;
+   // }
 
-      message.setDestination(queueName);
-
-      String uid = UUIDGenerator.getInstance().generateStringUUID();
-
-      message.putStringProperty(ManagementHelper.HDR_NOTIFICATION_TYPE, new SimpleString(type.toString()));
-      message.putLongProperty(ManagementHelper.HDR_NOTIFICATION_TIMESTAMP, System.currentTimeMillis());
-
-      message.putStringProperty(new SimpleString("foobar"), new SimpleString(uid));
-
-      return message;
-   }
-
    private int generateTransientID()
    {
       int start = transientIDSequence;
@@ -902,26 +962,26 @@
          return oper;
       }
    }
-   
+
    private class Reaper implements Runnable
    {
       private boolean closed;
-      
+
       public synchronized void stop()
       {
          closed = true;
-         
+
          notify();
       }
-      
+
       public synchronized void run()
       {
          while (true)
          {
             long toWait = reaperPeriod;
-   
+
             long start = System.currentTimeMillis();
-   
+
             while (!closed && toWait > 0)
             {
                try
@@ -931,33 +991,33 @@
                catch (InterruptedException e)
                {
                }
-   
+
                long now = System.currentTimeMillis();
-   
+
                toWait -= now - start;
-   
+
                start = now;
             }
-            
+
             if (closed)
             {
                return;
             }
-   
+
             Map<SimpleString, Binding> nameMap = addressManager.getBindings();
-   
+
             List<Queue> queues = new ArrayList<Queue>();
-   
+
             for (Binding binding : nameMap.values())
             {
                if (binding.getType() == BindingType.LOCAL_QUEUE)
                {
                   Queue queue = (Queue)binding.getBindable();
-   
+
                   queues.add(queue);
                }
             }
-   
+
             for (Queue queue : queues)
             {
                try
@@ -982,8 +1042,6 @@
          messagesToPage.add(message);
       }
 
-      
-
       /* (non-Javadoc)
        * @see org.jboss.messaging.core.transaction.TransactionOperation#getDistinctQueues()
        */

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/SimpleAddressManager.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/SimpleAddressManager.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/SimpleAddressManager.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -21,9 +21,8 @@
  */
 package org.jboss.messaging.core.postoffice.impl;
 
+import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import org.jboss.messaging.core.logging.Logger;
 import org.jboss.messaging.core.postoffice.Address;
@@ -43,18 +42,22 @@
 {
    private static final Logger log = Logger.getLogger(SimpleAddressManager.class);
 
-   private final ConcurrentMap<SimpleString, Bindings> mappings = new ConcurrentHashMap<SimpleString, Bindings>();
+   private final Map<SimpleString, Bindings> mappings = new HashMap<SimpleString, Bindings>();
 
-   private final ConcurrentMap<SimpleString, Binding> nameMap = new ConcurrentHashMap<SimpleString, Binding>();
+   private final Map<SimpleString, Binding> nameMap = new HashMap<SimpleString, Binding>();
 
-   public boolean addBinding(final Binding binding)
+   public void addBinding(final Binding binding)
    {
-      if (nameMap.putIfAbsent(binding.getUniqueName(), binding) != null)
+      if (nameMap.containsKey(binding.getUniqueName()))
       {
          throw new IllegalStateException("Binding already exists " + binding);         
       }
       
-      return addMappingInternal(binding.getAddress(), binding);
+      nameMap.put(binding.getUniqueName(), binding);
+      
+      addMappingInternal(binding.getAddress(), binding);
+      
+      log.info(System.identityHashCode(this) + " adding binding " + binding.getUniqueName());
    }
 
    public Binding removeBinding(final SimpleString uniqueName)
@@ -77,7 +80,19 @@
    }
 
    public Binding getBinding(final SimpleString bindableName)
-   {
+   {      
+      log.info(System.identityHashCode(this) + " dumping bindings");
+      
+      for (SimpleString name: nameMap.keySet())
+      {
+         log.info("binding name: " + name);
+      }
+      
+      for (SimpleString address: mappings.keySet())
+      {
+         log.info("address name: " + address);
+      }
+      
       return nameMap.get(bindableName);
    }
 
@@ -151,26 +166,17 @@
       return theBinding;
    }
 
-   protected boolean addMappingInternal(final SimpleString address, final Binding binding)
+   protected void addMappingInternal(final SimpleString address, final Binding binding)
    {
       Bindings bindings = mappings.get(address);
 
-      Bindings prevBindings = null;
-
       if (bindings == null)
       {
          bindings = new BindingsImpl();
 
-         prevBindings = mappings.putIfAbsent(address, bindings);
-
-         if (prevBindings != null)
-         {
-            bindings = prevBindings;
-         }
+         mappings.put(address, bindings);
       }
 
       bindings.addBinding(binding);
-
-      return prevBindings != null;
    }
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/WildcardAddressManager.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/WildcardAddressManager.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/postoffice/impl/WildcardAddressManager.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -23,10 +23,8 @@
 
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.jboss.messaging.core.logging.Logger;
 import org.jboss.messaging.core.postoffice.Address;
@@ -64,8 +62,8 @@
    public Bindings getBindingsForRoutingAddress(final SimpleString address)
    {
       Bindings bindings = super.getBindingsForRoutingAddress(address);
-      
-      //this should only happen if we're routing to an address that has no mappings when we're running checkAllowable
+
+      // this should only happen if we're routing to an address that has no mappings when we're running checkAllowable
       if (bindings == null && !wildCardAddresses.isEmpty())
       {
          Address add = addAndUpdateAddressMap(address);
@@ -88,43 +86,38 @@
       }
       return bindings;
    }
-      
+
    /**
     * If the address to add the binding to contains a wildcard then a copy of the binding (with the same underlying queue)
     * will be added to the actual mappings. Otherwise the binding is added as normal.
     *
     * @param binding the binding to add
-    * @return true if the address was a new mapping
     */
-   public boolean addBinding(final Binding binding)
+   public void addBinding(final Binding binding)
    {
-      boolean exists = super.addBinding(binding);
-      if (!exists)
+      log.info("Adding binding " + binding.getAddress() + " name " + binding.getUniqueName());
+      super.addBinding(binding);
+      Address add = addAndUpdateAddressMap(binding.getAddress());
+      if (add.containsWildCard())
       {
-         Address add = addAndUpdateAddressMap(binding.getAddress());
-         if (add.containsWildCard())
+         for (Address destAdd : add.getLinkedAddresses())
          {
-            for (Address destAdd : add.getLinkedAddresses())
-            {
-               super.addMappingInternal(destAdd.getAddress(), binding);
-            }
+            super.addMappingInternal(destAdd.getAddress(), binding);
          }
-         else
+      }
+      else
+      {
+         for (Address destAdd : add.getLinkedAddresses())
          {
-            for (Address destAdd : add.getLinkedAddresses())
+            Bindings bindings = super.getBindingsForRoutingAddress(destAdd.getAddress());
+            for (Binding b : bindings.getBindings())
             {
-               Bindings bindings = super.getBindingsForRoutingAddress(destAdd.getAddress());
-               for (Binding b : bindings.getBindings())
-               {
-                  super.addMappingInternal(binding.getAddress(), b);
-               }
+               super.addMappingInternal(binding.getAddress(), b);
             }
          }
       }
-      return exists;
    }
 
-
    /**
     * If the address is a wild card then the binding will be removed from the actual mappings for any linked address.
     * otherwise it will be removed as normal.
@@ -243,7 +236,7 @@
 
    private synchronized void removeAndUpdateAddressMap(final Address address)
    {
-      //we only remove if there are no bindings left
+      // we only remove if there are no bindings left
       Bindings bindings = super.getBindingsForRoutingAddress(address.getAddress());
       if (bindings == null || bindings.getBindings().size() == 0)
       {

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/Channel.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/Channel.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/Channel.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -14,6 +14,7 @@
 import java.util.concurrent.locks.Lock;
 
 import org.jboss.messaging.core.exception.MessagingException;
+import org.jboss.messaging.core.server.replication.Replicator;
 
 /**
  * A Channel A Channel *does not* support concurrent access by more than one thread!
@@ -30,7 +31,7 @@
    
    Packet sendBlocking(Packet packet) throws MessagingException;
 
-   void replicatePacket(Packet packet, long replicatedChannelID, Runnable action);
+   //void replicatePacket(Packet packet, long replicatedChannelID, Runnable action);
    
    void setHandler(ChannelHandler handler);
    
@@ -38,9 +39,9 @@
 
    void close();
 
-   void transferConnection(RemotingConnection newConnection, final long newID, final Channel replicatingChannel);
+   void transferConnection(RemotingConnection newConnection);
    
-   void replayCommands(int lastReceivedCommandID, final long newID);
+   void replayCommands(int lastReceivedCommandID);
 
    int getLastReceivedCommandID();
 
@@ -54,7 +55,7 @@
    
    RemotingConnection getConnection();
    
-   void executeOutstandingDelayedResults();
+   //void executeOutstandingDelayedResults();
    
    void confirm(Packet packet);
    
@@ -64,5 +65,7 @@
    
    void handlePacket(Packet packet);
    
-   void waitForAllReplicationResponse();
+   //void waitForAllReplicationResponse();
+   
+   void replicationResponseReceived(Replicator replicator);
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -75,5 +75,7 @@
    
    long getBlockingCallTimeout();
    
-   Object getTransferLock();     
+   Object getTransferLock();  
+   
+   RemotingConnection getReplicatingConnection();
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/ChannelImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/ChannelImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/ChannelImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -48,6 +48,9 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
 import org.jboss.messaging.core.remoting.impl.wireformat.PacketsConfirmedMessage;
 import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.core.server.replication.impl.JBMThread;
+import org.jboss.messaging.utils.Pair;
 
 /**
  * A ChannelImpl
@@ -86,11 +89,11 @@
 
    private final Object sendBlockingLock = new Object();
 
-   private final Object replicationLock = new Object();
+   // private final Object replicationLock = new Object();
 
    private boolean failingOver;
 
-   private final Queue<Runnable> responseActions = new ConcurrentLinkedQueue<Runnable>();
+   // private final Queue<Runnable> responseActions = new ConcurrentLinkedQueue<Runnable>();
 
    private final int windowSize;
 
@@ -102,9 +105,9 @@
 
    private CommandConfirmationHandler commandConfirmationHandler;
 
-   private int responseActionCount;
+   // private int responseActionCount;
 
-   private boolean playedResponsesOnFailure;
+   // private boolean playedResponsesOnFailure;
 
    public ChannelImpl(final RemotingConnection connection, final long id, final int windowSize, final boolean block)
    {
@@ -177,10 +180,30 @@
    {
       send(packet, false);
    }
-
+   
    // This must never called by more than one thread concurrently
    public void send(final Packet packet, final boolean flush)
    {
+      //FIXME - this is a bit hacky
+      
+      Thread t = Thread.currentThread();
+      
+      if (t instanceof JBMThread)
+      {         
+         JBMThread thread = (JBMThread)t;
+   
+         if (thread.isRecording())
+         {
+            thread.getReplicator().registerWaitingChannel(this);
+   
+            log.info("Queueing write");
+            
+            queuedWrites.add(new Pair<Replicator, Packet>(thread.getReplicator(), packet));
+            
+            return;
+         }
+      }
+
       synchronized (sendLock)
       {
          packet.setChannelID(id);
@@ -226,6 +249,7 @@
 
             if (connection.isActive() || packet.isWriteAlways())
             {
+               log.info("actually writing packet " + packet.getType());
                connection.getTransportConnection().write(buffer, flush);
             }
          }
@@ -294,7 +318,7 @@
             {
                resendCache.add(packet);
             }
-
+           
             connection.getTransportConnection().write(buffer);
 
             long toWait = connection.getBlockingCallTimeout();
@@ -349,98 +373,98 @@
 
    // Must be synchronized since can be called by incoming session commands but also by deliveries
    // Also needs to be synchronized with respect to replicatingChannelDead
-   public void replicatePacket(final Packet packet, final long replicatedChannelID, final Runnable action)
-   {
-      packet.setChannelID(replicatedChannelID);
+   // public void replicatePacket(final Packet packet, final long replicatedChannelID, final Runnable action)
+   // {
+   // packet.setChannelID(replicatedChannelID);
+   //
+   // boolean runItNow = false;
+   //
+   // synchronized (replicationLock)
+   // {
+   // if (playedResponsesOnFailure && action != null)
+   // {
+   // // Already replicating channel failed, so just play the action now
+   //
+   // runItNow = true;
+   // }
+   // else
+   // {
+   // if (action != null)
+   // {
+   // responseActions.add(action);
+   //
+   // responseActionCount++;
+   // }
+   //
+   // final MessagingBuffer buffer = connection.getTransportConnection()
+   // .createBuffer(packet.getRequiredBufferSize());
+   //
+   // packet.encode(buffer);
+   //
+   // connection.getTransportConnection().write(buffer);
+   // }
+   // }
+   //
+   // // Execute outside lock
+   //
+   // if (runItNow)
+   // {
+   // action.run();
+   // }
+   // }
 
-      boolean runItNow = false;
-
-      synchronized (replicationLock)
-      {
-         if (playedResponsesOnFailure && action != null)
-         {
-            // Already replicating channel failed, so just play the action now
-
-            runItNow = true;
-         }
-         else
-         {
-            if (action != null)
-            {
-               responseActions.add(action);
-
-               responseActionCount++;
-            }
-
-            final MessagingBuffer buffer = connection.getTransportConnection()
-                                                     .createBuffer(packet.getRequiredBufferSize());
-
-            packet.encode(buffer);
-
-            connection.getTransportConnection().write(buffer);
-         }
-      }
-
-      // Execute outside lock
-
-      if (runItNow)
-      {
-         action.run();
-      }
-   }
-   
    public void setCommandConfirmationHandler(final CommandConfirmationHandler handler)
    {
       this.commandConfirmationHandler = handler;
    }
 
-   public void executeOutstandingDelayedResults()
-   {
-      // Execute on different thread to avoid deadlock
+   // public void executeOutstandingDelayedResults()
+   // {
+   // // Execute on different thread to avoid deadlock
+   //
+   // new Thread()
+   // {
+   // public void run()
+   // {
+   // doExecuteOutstandingDelayedResults();
+   // }
+   // }.start();
+   // }
+   //
+   // private void doExecuteOutstandingDelayedResults()
+   // {
+   // List<Runnable> toRun = new ArrayList<Runnable>();
+   //
+   // synchronized (replicationLock)
+   // {
+   // // Execute all the response actions now
+   //
+   // while (true)
+   // {
+   // Runnable action = responseActions.poll();
+   //
+   // if (action != null)
+   // {
+   // toRun.add(action);
+   // }
+   // else
+   // {
+   // break;
+   // }
+   // }
+   //
+   // responseActionCount = 0;
+   //
+   // playedResponsesOnFailure = true;
+   //
+   // for (Runnable action : toRun)
+   // {
+   // action.run();
+   // }
+   // }
+   //
+   // }
 
-      new Thread()
-      {
-         public void run()
-         {
-            doExecuteOutstandingDelayedResults();
-         }
-      }.start();
-   }
-
-   private void doExecuteOutstandingDelayedResults()
-   {
-      List<Runnable> toRun = new ArrayList<Runnable>();
-
-      synchronized (replicationLock)
-      {
-         // Execute all the response actions now
-
-         while (true)
-         {
-            Runnable action = responseActions.poll();
-
-            if (action != null)
-            {
-               toRun.add(action);
-            }
-            else
-            {
-               break;
-            }
-         }
-
-         responseActionCount = 0;
-
-         playedResponsesOnFailure = true;
-
-         for (Runnable action : toRun)
-         {
-            action.run();
-         }
-      }
-
-   }
-
    public void setHandler(final ChannelHandler handler)
    {
       this.handler = handler;
@@ -466,9 +490,7 @@
       closed = true;
    }
 
-   public void transferConnection(final RemotingConnection newConnection,
-                                  final long newChannelID,
-                                  final Channel replicatingChannel)
+   public void transferConnection(final RemotingConnection newConnection)
    {
       // Needs to synchronize on the connection to make sure no packets from
       // the old connection get processed after transfer has occurred
@@ -476,36 +498,32 @@
       {
          connection.removeChannel(id);
 
-         if (replicatingChannel != null)
-         {
-            // If we're reconnecting to a live node which is replicated then there will be a replicating channel
-            // too. We need to then make sure that all replication responses come back since packets aren't
-            // considered confirmed until response comes back and is processed. Otherwise responses to previous
-            // message sends could come back after reconnection resulting in clients resending same message
-            // since it wasn't confirmed yet.
-            replicatingChannel.waitForAllReplicationResponse();
-         }
+//         if (replicatingChannel != null)
+//         {
+//            // If we're reconnecting to a live node which is replicated then there will be a replicating channel
+//            // too. We need to then make sure that all replication responses come back since packets aren't
+//            // considered confirmed until response comes back and is processed. Otherwise responses to previous
+//            // message sends could come back after reconnection resulting in clients resending same message
+//            // since it wasn't confirmed yet.
+//            replicatingChannel.waitForAllReplicationResponse();
+//         }
 
          // And switch it
 
          final RemotingConnectionImpl rnewConnection = (RemotingConnectionImpl)newConnection;
 
-         rnewConnection.putChannel(newChannelID, this);
+         rnewConnection.putChannel(id, this);
 
          connection = rnewConnection;
-
-         this.id = newChannelID;
       }
    }
 
-   public void replayCommands(final int otherLastReceivedCommandID, final long newChannelID)
+   public void replayCommands(final int otherLastReceivedCommandID)
    {
       clearUpTo(otherLastReceivedCommandID);
 
       for (final Packet packet : resendCache)
       {
-         packet.setChannelID(newChannelID);
-
          doWrite(packet);
       }
    }
@@ -591,16 +609,10 @@
 
          return;
       }
-      else if (packet.getType() == REPLICATION_RESPONSE)
-      {
-         replicateResponseReceived();
-
-         return;
-      }
       else
       {
          if (packet.isResponse())
-         {
+         {            
             response = packet;
 
             confirm(packet);
@@ -622,96 +634,96 @@
          }
       }
 
-      replicateComplete();
+      // replicateComplete();
    }
-   
-   public void waitForAllReplicationResponse()
-   {
-      synchronized (replicationLock)
-      {
-         long toWait = 10000; // TODO don't hardcode timeout
 
-         long start = System.currentTimeMillis();
+   // public void waitForAllReplicationResponse()
+   // {
+   // synchronized (replicationLock)
+   // {
+   // long toWait = 10000; // TODO don't hardcode timeout
+   //
+   // long start = System.currentTimeMillis();
+   //
+   // while (responseActionCount > 0 && toWait > 0)
+   // {
+   // try
+   // {
+   // replicationLock.wait();
+   // }
+   // catch (InterruptedException e)
+   // {
+   // }
+   //
+   // long now = System.currentTimeMillis();
+   //
+   // toWait -= now - start;
+   //
+   // start = now;
+   // }
+   //
+   // if (toWait <= 0)
+   // {
+   // log.warn("Timed out waiting for replication responses to return");
+   // }
+   // }
+   // }
 
-         while (responseActionCount > 0 && toWait > 0)
-         {
-            try
-            {
-               replicationLock.wait();
-            }
-            catch (InterruptedException e)
-            {
-            }
+   // private void replicateComplete()
+   // {
+   // if (!connection.isActive() && id != 0)
+   // {
+   // // We're on backup and not ping channel so send back a replication response
+   //
+   // Packet packet = new PacketImpl(REPLICATION_RESPONSE);
+   //
+   // packet.setChannelID(2);
+   //
+   // doWrite(packet);
+   // }
+   // }
 
-            long now = System.currentTimeMillis();
-
-            toWait -= now - start;
-
-            start = now;
-         }
-
-         if (toWait <= 0)
-         {
-            log.warn("Timed out waiting for replication responses to return");
-         }
-      }
-   }
-
-   private void replicateComplete()
-   {
-      if (!connection.isActive() && id != 0)
-      {
-         // We're on backup and not ping channel so send back a replication response
-
-         Packet packet = new PacketImpl(REPLICATION_RESPONSE);
-
-         packet.setChannelID(2);
-
-         doWrite(packet);
-      }
-   }
-
    // This will never get called concurrently by more than one thread
 
    // TODO it's not ideal synchronizing this since it forms a contention point with replication
    // but we need to do this to protect it w.r.t. the check on replicatingChannel
-   private void replicateResponseReceived()
-   {
-      Runnable result = null;
+   // private void replicateResponseReceived()
+   // {
+   // Runnable result = null;
+   //
+   // synchronized (replicationLock)
+   // {
+   // if (playedResponsesOnFailure)
+   // {
+   // return;
+   // }
+   //
+   // result = responseActions.poll();
+   //
+   // if (result == null)
+   // {
+   // throw new IllegalStateException("Cannot find response action");
+   // }
+   // }
+   //
+   // // Must execute outside of lock
+   // if (result != null)
+   // {
+   // result.run();
+   //
+   // // TODO - we can optimise this not to lock every time - only if waiting for all replications to return
+   // synchronized (replicationLock)
+   // {
+   // responseActionCount--;
+   //
+   // if (responseActionCount == 0)
+   // {
+   // replicationLock.notify();
+   // }
+   // }
+   // }
+   // }
 
-      synchronized (replicationLock)
-      {
-         if (playedResponsesOnFailure)
-         {
-            return;
-         }
-
-         result = responseActions.poll();
-
-         if (result == null)
-         {
-            throw new IllegalStateException("Cannot find response action");
-         }
-      }
-
-      // Must execute outside of lock
-      if (result != null)
-      {
-         result.run();
-
-         // TODO - we can optimise this not to lock every time - only if waiting for all replications to return
-         synchronized (replicationLock)
-         {
-            responseActionCount--;
-
-            if (responseActionCount == 0)
-            {
-               replicationLock.notify();
-            }
-         }
-      }
-   }
-   
    private void doWrite(final Packet packet)
    {
       final MessagingBuffer buffer = connection.getTransportConnection().createBuffer(packet.getRequiredBufferSize());
@@ -763,4 +775,28 @@
          sendSemaphore.release(sizeToFree);
       }
    }
+   
+   
+   private java.util.Queue<Pair<Replicator, Packet>> queuedWrites = new ConcurrentLinkedQueue<Pair<Replicator, Packet>>();
+
+   public void replicationResponseReceived(final Replicator replicator)
+   {
+      Pair<Replicator, Packet> pair = queuedWrites.peek();
+
+      if (pair != null && pair.a == replicator)
+      {
+         do
+         {
+            queuedWrites.remove();
+
+            log.info("replication response received, sending packet " + pair.b);
+            send(pair.b);
+
+            pair = queuedWrites.peek();
+         }
+         while (pair != null && pair.a.isResponseReceived());
+      }
+   }
+
+   
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/PacketDecoder.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/PacketDecoder.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/PacketDecoder.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -36,7 +36,7 @@
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_ACKNOWLEDGE;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_ADD_REMOTE_CONSUMER;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_ADD_REMOTE_QUEUE_BINDING;
-import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_CREATESESSION;
+import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_LOCK_SEQUENCES;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_REDISTRIBUTION;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_REMOVE_REMOTE_CONSUMER;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_REMOVE_REMOTE_QUEUE_BINDING;
@@ -56,7 +56,6 @@
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_QUEUEQUERY_RESP;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_RECEIVE_CONTINUATION;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_RECEIVE_MSG;
-import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_REPLICATE_DELIVERY;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_ROLLBACK;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_SEND;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_SEND_CONTINUATION;
@@ -80,6 +79,7 @@
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_XA_START;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_XA_SUSPEND;
 
+import org.jboss.messaging.core.logging.Logger;
 import org.jboss.messaging.core.remoting.Packet;
 import org.jboss.messaging.core.remoting.impl.wireformat.CreateQueueMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.CreateSessionMessage;
@@ -91,7 +91,6 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.Ping;
 import org.jboss.messaging.core.remoting.impl.wireformat.ReattachSessionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.ReattachSessionResponseMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.ReplicateCreateSessionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.RollbackMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionAcknowledgeMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionBindingQueryMessage;
@@ -124,13 +123,14 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXASetTimeoutResponseMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXAStartMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateAcknowledgeMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateLockSequenceMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRedistributionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteBindingAddedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteBindingRemovedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteConsumerAddedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteConsumerRemovedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateStartupInfoMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.SessionReplicateDeliveryMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicationResponseMessage;
 import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
 
 /**
@@ -142,9 +142,13 @@
  */
 public class PacketDecoder
 {
+   private static final Logger log = Logger.getLogger(PacketDecoder.class);
+   
    public Packet decode(final MessagingBuffer in)
    {
       final byte packetType = in.readByte();
+      
+      log.info("decoding packet " + packetType);
 
       Packet packet;
 
@@ -172,7 +176,7 @@
          }
          case REPLICATION_RESPONSE:
          {
-            packet = new PacketImpl(REPLICATION_RESPONSE);
+            packet = new ReplicationResponseMessage();
             break;
          }
          case CREATESESSION:
@@ -180,11 +184,6 @@
             packet = new CreateSessionMessage();
             break;
          }
-         case REPLICATE_CREATESESSION:
-         {
-            packet = new ReplicateCreateSessionMessage();
-            break;
-         }
          case CREATESESSION_RESP:
          {
             packet = new CreateSessionResponseMessage();
@@ -415,11 +414,6 @@
             packet = new ReplicateRemoteConsumerRemovedMessage();
             break;
          }
-         case SESS_REPLICATE_DELIVERY:
-         {
-            packet = new SessionReplicateDeliveryMessage();
-            break;
-         }
          case REPLICATE_STARTUP_INFO:
          {
             packet = new ReplicateStartupInfoMessage();
@@ -435,6 +429,11 @@
             packet = new ReplicateRedistributionMessage();
             break;
          }
+         case REPLICATE_LOCK_SEQUENCES:
+         {
+            packet = new ReplicateLockSequenceMessage();
+            break;
+         }
          default:
          {
             throw new IllegalArgumentException("Invalid type: " + packetType);

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -84,6 +84,8 @@
    // -----------------------------------------------------------------------------------
 
    private final Connection transportConnection;
+   
+   private final RemotingConnection replicatingConnection;
 
    private final Map<Long, Channel> channels = new ConcurrentHashMap<Long, Channel>();
 
@@ -127,21 +129,23 @@
                                  final long blockingCallTimeout,
                                  final List<Interceptor> interceptors)
    {
-      this(transportConnection, blockingCallTimeout, interceptors, true, true);
+      this(transportConnection, null, blockingCallTimeout, interceptors, true, true);
    }
 
    /*
     * Create a server side connection
     */
    public RemotingConnectionImpl(final Connection transportConnection,
+                                 final RemotingConnection replicatingConnection,
                                  final List<Interceptor> interceptors,
                                  final boolean active)
 
    {
-      this(transportConnection, -1, interceptors, active, false);
+      this(transportConnection, replicatingConnection, -1, interceptors, active, false);
    }
 
    private RemotingConnectionImpl(final Connection transportConnection,
+                                 final RemotingConnection replicatingConnection,
                                   final long blockingCallTimeout,
                                   final List<Interceptor> interceptors,
                                   final boolean active,
@@ -149,6 +153,8 @@
 
    {
       this.transportConnection = transportConnection;
+      
+      this.replicatingConnection = replicatingConnection;
 
       this.blockingCallTimeout = blockingCallTimeout;
 
@@ -284,15 +290,6 @@
 
       for (Channel channel : channels.values())
       {
-         // channel.lock.lock();
-         // try
-         // {
-         // channel.sendCondition.signalAll();
-         // }
-         // finally
-         // {
-         // channel.lock.unlock();
-         // }
          channel.returnBlocking();
       }
    }
@@ -358,6 +355,11 @@
    {
       return blockingCallTimeout;
    }
+   
+   public RemotingConnection getReplicatingConnection()
+   {
+      return replicatingConnection;
+   }
 
    // Buffer Handler implementation
    // ----------------------------------------------------
@@ -365,6 +367,8 @@
    public void bufferReceived(final Object connectionID, final MessagingBuffer buffer)
    {
       final Packet packet = decoder.decode(buffer);
+      
+      log.info("packet received " + packet.getType());
 
       synchronized (transferLock)
       {

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnection.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnection.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnection.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -50,6 +50,8 @@
    private final String id;
 
    private boolean closed;
+   
+   private volatile boolean closing;
 
    private final int serverID;
 
@@ -82,8 +84,6 @@
       listener.connectionCreated(this);
    }
 
-   private volatile boolean closing;
-
    public void close()
    {
       if (closing)
@@ -123,18 +123,24 @@
    {
       try
       {
+         log.info("writing on invm connection");
          executor.execute(new Runnable()
          {
             public void run()
             {
                try
                {
+                  log.info("runnable running");
                   if (!closed)
                   {
                      buffer.readInt(); // read and discard
 
                      handler.bufferReceived(id, buffer);
                   }
+                  else
+                  {
+                     log.info("it's closed");
+                  }
                }
                catch (Exception e)
                {
@@ -148,6 +154,7 @@
       catch (RejectedExecutionException e)
       {
          // Ignore - this can happen if server/client is shutdown and another request comes in
+         log.error("shutdown", e);
       }
    }
 

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/PacketImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/PacketImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/PacketImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -64,11 +64,9 @@
 
    public static final byte REATTACH_SESSION_RESP = 33;
 
-   public static final byte REPLICATE_CREATESESSION = 34;
-   
-   public static final byte CREATE_QUEUE = 35;
+   public static final byte CREATE_QUEUE = 34;
 
-   public static final byte DELETE_QUEUE = 36;
+   public static final byte DELETE_QUEUE = 35;
 
 
    // Session
@@ -146,8 +144,6 @@
    
    //Replication
 
-   public static final byte SESS_REPLICATE_DELIVERY = 90;
-   
    public static final byte REPLICATE_ADD_REMOTE_QUEUE_BINDING = 91;
    
    public static final byte REPLICATE_REMOVE_REMOTE_QUEUE_BINDING = 92;
@@ -162,6 +158,8 @@
    
    public static final byte REPLICATE_REDISTRIBUTION = 97;
    
+   public static final byte REPLICATE_LOCK_SEQUENCES = 98;
+   
    // Static --------------------------------------------------------
 
    public PacketImpl(final byte type)
@@ -189,6 +187,11 @@
    
    public int encode(final MessagingBuffer buffer)
    {
+//      if (this.type == PacketImpl.EXCEPTION)
+//      {
+//         log.info("encoding exception", new Exception());
+//      }
+      
       // The standard header fields
       buffer.writeInt(0); // The length gets filled in at the end
       buffer.writeByte(type);

Deleted: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReplicateCreateSessionMessage.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReplicateCreateSessionMessage.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReplicateCreateSessionMessage.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -1,264 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.messaging.core.remoting.impl.wireformat;
-
-import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
-import org.jboss.messaging.utils.DataConstants;
-
-/**
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>.
- * 
- * @version <tt>$Revision$</tt>
- */
-public class ReplicateCreateSessionMessage extends PacketImpl
-{
-   // Constants -----------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   private String name;
-
-   private long replicatedSessionChannelID;
-
-   private long originalSessionChannelID;
-
-   private int version;
-
-   private String username;
-
-   private String password;
-
-   private int minLargeMessageSize;
-
-   private boolean xa;
-
-   private boolean autoCommitSends;
-
-   private boolean autoCommitAcks;
-
-   private boolean preAcknowledge;
-
-   private int windowSize;
-
-   // Static --------------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public ReplicateCreateSessionMessage(final String name,
-                                        final long replicatedSessionChannelID,
-                                        final long originalSessionChannelID,
-                                        final int version,
-                                        final String username,
-                                        final String password,
-                                        final int minLargeMessageSize,
-                                        final boolean xa,
-                                        final boolean autoCommitSends,
-                                        final boolean autoCommitAcks,
-                                        final boolean preAcknowledge,
-                                        final int windowSize)
-   {
-      super(REPLICATE_CREATESESSION);
-
-      this.name = name;
-
-      this.replicatedSessionChannelID = replicatedSessionChannelID;
-
-      this.originalSessionChannelID = originalSessionChannelID;
-
-      this.version = version;
-
-      this.username = username;
-
-      this.password = password;
-
-      this.minLargeMessageSize = minLargeMessageSize;
-
-      this.xa = xa;
-
-      this.autoCommitSends = autoCommitSends;
-
-      this.autoCommitAcks = autoCommitAcks;
-
-      this.preAcknowledge = preAcknowledge;
-
-      this.windowSize = windowSize;
-   }
-
-   public ReplicateCreateSessionMessage()
-   {
-      super(REPLICATE_CREATESESSION);
-   }
-
-   // Public --------------------------------------------------------
-
-   public String getName()
-   {
-      return name;
-   }
-
-   public long getReplicatedSessionChannelID()
-   {
-      return replicatedSessionChannelID;
-   }
-
-   public long getOriginalSessionChannelID()
-   {
-      return originalSessionChannelID;
-   }
-
-   public int getVersion()
-   {
-      return version;
-   }
-
-   public String getUsername()
-   {
-      return username;
-   }
-
-   public String getPassword()
-   {
-      return password;
-   }
-
-   public int getMinLargeMessageSize()
-   {
-      return minLargeMessageSize;
-   }
-
-   public boolean isXA()
-   {
-      return xa;
-   }
-
-   public boolean isAutoCommitSends()
-   {
-      return autoCommitSends;
-   }
-
-   public boolean isAutoCommitAcks()
-   {
-      return autoCommitAcks;
-   }
-
-   public boolean isPreAcknowledge()
-   {
-      return preAcknowledge;
-   }
-
-   public int getWindowSize()
-   {
-      return windowSize;
-   }
-
-   public int getRequiredBufferSize()
-   {
-      return BASIC_PACKET_SIZE + 
-             stringEncodeSize(name) + // buffer.writeString(name);
-             DataConstants.SIZE_LONG + // buffer.writeLong(originalSessionChannelID);
-             DataConstants.SIZE_LONG + // buffer.writeLong(replicatedSessionChannelID);
-             DataConstants.SIZE_INT + // buffer.writeInt(version);
-             nullableStringEncodeSize(username) + // buffer.writeNullableString(username);
-             nullableStringEncodeSize(password) + // buffer.writeNullableString(password);
-             DataConstants.SIZE_INT + // buffer.writeInt(minLargeMessageSize);
-             DataConstants.SIZE_BOOLEAN + // buffer.writeBoolean(xa);
-             DataConstants.SIZE_BOOLEAN + // buffer.writeBoolean(autoCommitSends);
-             DataConstants.SIZE_BOOLEAN + // buffer.writeBoolean(autoCommitAcks);
-             DataConstants.SIZE_INT + // buffer.writeInt(windowSize);
-             DataConstants.SIZE_BOOLEAN; // buffer.writeBoolean(preAcknowledge);
-   }
-
-   @Override
-   public void encodeBody(final MessagingBuffer buffer)
-   {
-      buffer.writeString(name);
-      buffer.writeLong(originalSessionChannelID);
-      buffer.writeLong(replicatedSessionChannelID);
-      buffer.writeInt(version);
-      buffer.writeNullableString(username);
-      buffer.writeNullableString(password);
-      buffer.writeInt(minLargeMessageSize);
-      buffer.writeBoolean(xa);
-      buffer.writeBoolean(autoCommitSends);
-      buffer.writeBoolean(autoCommitAcks);
-      buffer.writeInt(windowSize);
-      buffer.writeBoolean(preAcknowledge);
-   }
-
-   @Override
-   public void decodeBody(final MessagingBuffer buffer)
-   {
-      name = buffer.readString();
-      originalSessionChannelID = buffer.readLong();
-      replicatedSessionChannelID = buffer.readLong();
-      version = buffer.readInt();
-      username = buffer.readNullableString();
-      password = buffer.readNullableString();
-      minLargeMessageSize = buffer.readInt();
-      xa = buffer.readBoolean();
-      autoCommitSends = buffer.readBoolean();
-      autoCommitAcks = buffer.readBoolean();
-      windowSize = buffer.readInt();
-      preAcknowledge = buffer.readBoolean();
-   }
-
-   @Override
-   public boolean equals(final Object other)
-   {
-      if (other instanceof ReplicateCreateSessionMessage == false)
-      {
-         return false;
-      }
-
-      ReplicateCreateSessionMessage r = (ReplicateCreateSessionMessage)other;
-
-      boolean matches = super.equals(other) && name.equals(r.name) &&
-                        originalSessionChannelID == r.originalSessionChannelID &&
-                        replicatedSessionChannelID == r.replicatedSessionChannelID &&
-                        version == r.version &&
-                        xa == r.xa &&
-                        autoCommitSends == r.autoCommitSends &&
-                        autoCommitAcks == r.autoCommitAcks &&
-                        (username == null ? r.username == null : username.equals(r.username)) &&
-                        (password == null ? r.password == null : password.equals(r.password)) &&
-                        minLargeMessageSize == r.minLargeMessageSize &&
-                        windowSize == r.windowSize;
-
-      return matches;
-   }
-
-   @Override
-   public final boolean isRequiresConfirmations()
-   {
-      return false;
-   }
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicateLockSequenceMessage.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicateLockSequenceMessage.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicateLockSequenceMessage.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,96 @@
+/*
+ * JBoss, Home of Professional Open Source Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors by
+ * the @authors tag. See the copyright.txt in the distribution for a full listing of individual contributors. This is
+ * free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details. You should have received a copy of the GNU Lesser General Public License along with this software; if not,
+ * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.core.remoting.impl.wireformat.replication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
+import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
+import org.jboss.messaging.utils.DataConstants;
+import org.jboss.messaging.utils.Pair;
+
+/**
+ * 
+ * A ReplicateLockSequenceMessage
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class ReplicateLockSequenceMessage extends PacketImpl
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private List<Pair<Long, Integer>> sequences;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicateLockSequenceMessage(final List<Pair<Long, Integer>> sequences)
+   {
+      super(REPLICATE_LOCK_SEQUENCES);
+
+      this.sequences = sequences;
+   }
+
+   // Public --------------------------------------------------------
+
+   public ReplicateLockSequenceMessage()
+   {
+      super(REPLICATE_LOCK_SEQUENCES);
+   }
+
+   public int getRequiredBufferSize()
+   {
+      return BASIC_PACKET_SIZE + DataConstants.SIZE_INT + sequences.size() * (DataConstants.SIZE_LONG + DataConstants.SIZE_INT);
+   }
+
+   @Override
+   public void encodeBody(final MessagingBuffer buffer)
+   {
+      buffer.writeInt(sequences.size());
+      for (Pair<Long, Integer> sequence : sequences)
+      {
+         buffer.writeLong(sequence.a);
+         buffer.writeInt(sequence.b);
+      }
+   }
+
+   @Override
+   public void decodeBody(final MessagingBuffer buffer)
+   {
+      int len = buffer.readInt();
+      sequences = new ArrayList<Pair<Long, Integer>>(len);
+      for (int i = 0; i < len; i++)
+      {
+         sequences.add(new Pair<Long, Integer>(buffer.readLong(), buffer.readInt()));
+      }
+   }
+
+   public List<Pair<Long, Integer>> getSequences()
+   {
+      return sequences;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicationResponseMessage.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicationResponseMessage.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/ReplicationResponseMessage.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.core.remoting.impl.wireformat.replication;
+
+import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATION_RESPONSE;
+
+import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
+
+/**
+ * A ReplicationResponseMessage
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class ReplicationResponseMessage extends PacketImpl
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public ReplicationResponseMessage()
+   {
+      super(REPLICATION_RESPONSE);
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public boolean isWriteAlways()
+   {
+      return true;
+   }
+   
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}
+

Deleted: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/SessionReplicateDeliveryMessage.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/SessionReplicateDeliveryMessage.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/impl/wireformat/replication/SessionReplicateDeliveryMessage.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -1,110 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors by
- * the @authors tag. See the copyright.txt in the distribution for a full listing of individual contributors. This is
- * free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
- * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details. You should have received a copy of the GNU Lesser General Public License along with this software; if not,
- * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
- * site: http://www.fsf.org.
- */
-
-package org.jboss.messaging.core.remoting.impl.wireformat.replication;
-
-import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
-import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
-import org.jboss.messaging.utils.DataConstants;
-
-/**
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision$</tt>
- */
-public class SessionReplicateDeliveryMessage extends PacketImpl
-{
-   // Constants -----------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   private long consumerID;
-
-   private long messageID;
-
-   // Static --------------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public SessionReplicateDeliveryMessage(final long consumerID, final long messageID)
-   {
-      super(SESS_REPLICATE_DELIVERY);
-
-      this.consumerID = consumerID;
-
-      this.messageID = messageID;
-   }
-
-   public SessionReplicateDeliveryMessage()
-   {
-      super(SESS_REPLICATE_DELIVERY);
-   }
-
-   // Public --------------------------------------------------------
-
-   public long getConsumerID()
-   {
-      return consumerID;
-   }
-
-   public long getMessageID()
-   {
-      return messageID;
-   }
-
-   public int getRequiredBufferSize()
-   {
-      return BASIC_PACKET_SIZE + DataConstants.SIZE_LONG + DataConstants.SIZE_LONG;
-   }
-
-   @Override
-   public void encodeBody(final MessagingBuffer buffer)
-   {
-      buffer.writeLong(consumerID);
-
-      buffer.writeLong(messageID);
-   }
-
-   @Override
-   public void decodeBody(final MessagingBuffer buffer)
-   {
-      consumerID = buffer.readLong();
-
-      messageID = buffer.readLong();
-   }
-
-   @Override
-   public boolean isRequiresConfirmations()
-   {
-      return false;
-   }
-
-   @Override
-   public boolean equals(final Object other)
-   {
-      if (other instanceof SessionReplicateDeliveryMessage == false)
-      {
-         return false;
-      }
-
-      SessionReplicateDeliveryMessage r = (SessionReplicateDeliveryMessage)other;
-
-      return super.equals(other) && consumerID == r.consumerID && messageID == r.messageID;
-   }
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-}

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/server/impl/RemotingServiceImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/server/impl/RemotingServiceImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/remoting/server/impl/RemotingServiceImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -53,6 +53,8 @@
 import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
 import org.jboss.messaging.core.server.MessagingServer;
 import org.jboss.messaging.core.server.impl.MessagingServerPacketHandler;
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.core.server.replication.impl.ReplicatorImpl;
 
 /**
  * @author <a href="mailto:jmesnil at redhat.com">Jeff Mesnil</a>
@@ -280,12 +282,46 @@
          throw new IllegalStateException("Unable to create connection, server hasn't finished starting up");
       }
 
-      RemotingConnection rc = new RemotingConnectionImpl(connection, interceptors, !config.isBackup());
+      RemotingConnection replicatingConnection = server.getReplicatingConnection();
+           
+      RemotingConnection rc = new RemotingConnectionImpl(connection, replicatingConnection, interceptors, !config.isBackup());
 
+      log.info("** creating connection " + System.identityHashCode(rc) + " replicating connection is " + replicatingConnection + 
+               " backup is " + config.isBackup());
+      
       Channel channel1 = rc.getChannel(1, -1, false);
+      
+      final Replicator replicator;
+      
+      if (replicatingConnection != null)
+      {      
+         Channel replicatingChannel = replicatingConnection.getChannel(1, -1, false);
+   
+         replicator = new ReplicatorImpl(replicatingChannel);
+   
+         replicatingChannel.setHandler(new ChannelHandler()
+         {
+            public void handlePacket(final Packet packet)
+            {
+               if (packet.getType() == PacketImpl.REPLICATION_RESPONSE)
+               {
+                  log.info("*** got replication response from create session");
+                  replicator.replicationResponseReceived();
+               }
+               else
+               {
+                  throw new IllegalArgumentException("Invalid packet " + packet.getType());
+               }
+            }
+         });
+      }
+      else
+      {
+         replicator = null;
+      }
+      
+      ChannelHandler handler = new MessagingServerPacketHandler(server, channel1, rc, replicator);
 
-      ChannelHandler handler = new MessagingServerPacketHandler(server, channel1, rc);
-
       channel1.setHandler(handler);
 
       connections.put(connection.getID(), rc);

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/MessagingServer.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/MessagingServer.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/MessagingServer.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -18,7 +18,6 @@
 import javax.management.MBeanServer;
 
 import org.jboss.messaging.core.config.Configuration;
-import org.jboss.messaging.core.deployers.DeploymentManager;
 import org.jboss.messaging.core.management.ManagementService;
 import org.jboss.messaging.core.management.impl.MessagingServerControlImpl;
 import org.jboss.messaging.core.persistence.StorageManager;
@@ -71,8 +70,7 @@
    ReattachSessionResponseMessage reattachSession(RemotingConnection connection, String name, int lastReceivedCommandID) throws Exception;
 
    CreateSessionResponseMessage createSession(String name,
-                                              long channelID,
-                                              long replicatedSessionID,
+                                              long channelID,                                              
                                               String username,
                                               String password,
                                               int minLargeMessageSize,
@@ -82,22 +80,9 @@
                                               boolean autoCommitAcks,
                                               boolean preAcknowledge,
                                               boolean xa,
-                                              int producerWindowSize) throws Exception;
+                                              int producerWindowSize,
+                                              boolean direct) throws Exception;
 
-   void replicateCreateSession(String name,
-                               long channelID,
-                               long originalSessionID,
-                               String username,
-                               String password,
-                               int minLargeMessageSize,
-                               int incrementingVersion,
-                               RemotingConnection remotingConnection,
-                               boolean autoCommitSends,
-                               boolean autoCommitAcks,
-                               boolean preAcknowledge,
-                               boolean xa,
-                               int sendWindowSize) throws Exception;
-
    void removeSession(String name) throws Exception;
 
    ServerSession getSession(String name);
@@ -124,7 +109,9 @@
 
    SimpleString getNodeID();
 
-   Channel getReplicatingChannel();
+   //Channel getReplicatingChannel();
+   
+   RemotingConnection getReplicatingConnection();
 
    void initialiseBackup(UUID nodeID, long currentMessageID) throws Exception;
 

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/Queue.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/Queue.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/Queue.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -27,7 +27,6 @@
 import java.util.concurrent.Executor;
 
 import org.jboss.messaging.core.filter.Filter;
-import org.jboss.messaging.core.remoting.Channel;
 import org.jboss.messaging.core.transaction.Transaction;
 import org.jboss.messaging.utils.SimpleString;
 
@@ -46,10 +45,8 @@
 
    SimpleString getName();
 
-   long getPersistenceID();
+   long getID();
 
-   void setPersistenceID(long id);
-
    Filter getFilter();
 
    boolean isDurable();
@@ -139,16 +136,14 @@
 
    boolean consumerFailedOver();
 
-   void addRedistributor(long delay, Executor executor, final Channel replicatingChannel);
+   void addRedistributor(long delay, Executor executor);
 
-   void cancelRedistributor() throws Exception;
-
    // Only used in testing
    void deliverNow();
 
    boolean checkDLQ(MessageReference ref) throws Exception;
    
-   void lockDelivery();
+   void lock();
    
-   void unlockDelivery();
+   void unlock();
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerConsumer.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerConsumer.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerConsumer.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -55,9 +55,9 @@
 	
 	void failedOver();
 	
-	void deliverReplicated(long messageID) throws Exception;
+	//void deliverReplicated(long messageID) throws Exception;
 	
-	void lock();
-	
-	void unlock();
+//	void lock();
+//	
+//	void unlock();
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerSession.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerSession.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/ServerSession.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -26,7 +26,6 @@
 import org.jboss.messaging.core.remoting.Packet;
 import org.jboss.messaging.core.remoting.RemotingConnection;
 import org.jboss.messaging.core.remoting.impl.wireformat.CreateQueueMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.PacketsConfirmedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.RollbackMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionAcknowledgeMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionBindingQueryMessage;
@@ -48,7 +47,6 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXARollbackMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXASetTimeoutMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXAStartMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.SessionReplicateDeliveryMessage;
 import org.jboss.messaging.core.server.impl.ServerSessionPacketHandler;
 
 /**
@@ -78,7 +76,12 @@
    void close() throws Exception;
 
    void promptDelivery(Queue queue);
+   
+   
+   void handleCreateConsumer(SessionCreateConsumerMessage packet);
 
+   
+
    void handleAcknowledge(final SessionAcknowledgeMessage packet);
 
    void handleExpired(final SessionExpiredMessage packet);
@@ -119,8 +122,6 @@
 
    void handleDeleteQueue(SessionDeleteQueueMessage packet);
 
-   void handleCreateConsumer(SessionCreateConsumerMessage packet);
-
    void handleExecuteQueueQuery(SessionQueueQueryMessage packet);
 
    void handleExecuteBindingQuery(SessionBindingQueryMessage packet);
@@ -139,10 +140,6 @@
 
    void handleClose(Packet packet);
 
-   void handleReplicatedDelivery(SessionReplicateDeliveryMessage packet);
-   
-   void handlePacketsConfirmed(PacketsConfirmedMessage packet);
-
    int transferConnection(RemotingConnection newConnection, int lastReceivedCommandID);
 
    Channel getChannel();

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/BridgeImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -136,8 +136,6 @@
 
    private final String clusterPassword;
 
-   private Channel replicatingChannel;
-
    private boolean activated;
    
    // Static --------------------------------------------------------
@@ -163,8 +161,7 @@
                      final SimpleString managementAddress,
                      final SimpleString managementNotificationAddress,
                      final String clusterUser,
-                     final String clusterPassword,
-                     final Channel replicatingChannel,
+                     final String clusterPassword,                  
                      final boolean activated,
                      final StorageManager storageManager) throws Exception
    {
@@ -187,7 +184,6 @@
            clusterUser,
            clusterPassword,
            null,
-           replicatingChannel,
            activated,
            storageManager, null);
    }
@@ -211,7 +207,6 @@
                      final String clusterUser,
                      final String clusterPassword,
                      final MessageFlowRecord flowRecord,
-                     final Channel replicatingChannel,
                      final boolean activated,
                      final StorageManager storageManager,
                      MessagingServer server) throws Exception
@@ -263,8 +258,6 @@
 
       this.flowRecord = flowRecord;
 
-      this.replicatingChannel = replicatingChannel;
-
       this.activated = activated;  
    }
 
@@ -325,8 +318,6 @@
 
    public synchronized void activate()
    {
-      replicatingChannel = null;
-
       activated = true;
 
       executor.execute(new CreateObjectsRunnable());
@@ -390,30 +381,7 @@
 
          if (ref != null)
          {
-            if (replicatingChannel == null)
-            {
-               // Acknowledge when we know send has been processed on the server
-               ref.getQueue().acknowledge(ref);
-            }
-            else
-            {
-               Packet packet = new ReplicateAcknowledgeMessage(name, ref.getMessage().getMessageID());
-
-               replicatingChannel.replicatePacket(packet, 1, new Runnable()
-               {
-                  public void run()
-                  {
-                     try
-                     {
-                        ref.getQueue().acknowledge(ref);
-                     }
-                     catch (Exception e)
-                     {
-                        log.error("Failed to ack", e);
-                     }
-                  }
-               });
-            }
+            ref.getQueue().acknowledge(ref);            
          }
       }
       catch (Exception e)

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterConnectionImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterConnectionImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterConnectionImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -24,7 +24,7 @@
 
 import static org.jboss.messaging.core.management.NotificationType.CONSUMER_CLOSED;
 import static org.jboss.messaging.core.management.NotificationType.CONSUMER_CREATED;
-import static org.jboss.messaging.core.postoffice.impl.PostOfficeImpl.HDR_RESET_QUEUE_DATA;
+import static org.jboss.messaging.core.postoffice.impl.ClusterQueueStateManagerImpl.HDR_RESET_QUEUE_DATA;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -46,13 +46,7 @@
 import org.jboss.messaging.core.postoffice.Binding;
 import org.jboss.messaging.core.postoffice.Bindings;
 import org.jboss.messaging.core.postoffice.PostOffice;
-import org.jboss.messaging.core.remoting.Channel;
-import org.jboss.messaging.core.remoting.Packet;
-import org.jboss.messaging.core.remoting.impl.wireformat.CreateQueueMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteBindingAddedMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteBindingRemovedMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteConsumerAddedMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteConsumerRemovedMessage;
+import org.jboss.messaging.core.postoffice.impl.ClusterQueueStateManagerImpl;
 import org.jboss.messaging.core.server.MessagingServer;
 import org.jboss.messaging.core.server.Queue;
 import org.jboss.messaging.core.server.cluster.Bridge;
@@ -106,8 +100,6 @@
 
    private final UUID nodeUUID;
 
-   private final Channel replicatingChannel;
-
    private final List<Pair<TransportConfiguration, TransportConfiguration>> staticConnectors;
 
    private boolean backup;
@@ -131,8 +123,7 @@
                                 final ScheduledExecutorService scheduledExecutor,
                                 final List<Pair<TransportConfiguration, TransportConfiguration>> connectors,
                                 final int maxHops,
-                                final UUID nodeUUID,
-                                final Channel replicatingChannel,
+                                final UUID nodeUUID,                       
                                 final boolean backup) throws Exception
    {
       this.name = name;
@@ -166,8 +157,6 @@
 
       this.nodeUUID = nodeUUID;
 
-      this.replicatingChannel = replicatingChannel;
-
       this.backup = backup;
 
       this.staticConnectors = connectors;
@@ -193,8 +182,7 @@
                                 final ScheduledExecutorService scheduledExecutor,
                                 final DiscoveryGroup discoveryGroup,
                                 final int maxHops,
-                                final UUID nodeUUID,
-                                final Channel replicatingChannel,
+                                final UUID nodeUUID,                              
                                 final boolean backup) throws Exception
    {
       this.name = name;
@@ -223,8 +211,6 @@
 
       this.nodeUUID = nodeUUID;
 
-      this.replicatingChannel = replicatingChannel;
-
       this.backup = backup;
 
       this.staticConnectors = null;
@@ -384,47 +370,9 @@
                // Add binding in storage so the queue will get reloaded on startup and we can find it - it's never
                // actually routed to at that address though
 
-               if (replicatingChannel == null)
-               {
-                  queue = server.createQueue(queueName, queueName, null, true, false);
+               queue = server.createQueue(queueName, queueName, null, true, false);
 
-                  createNewRecord(entry.getKey(), connectorPair, queueName, queue, true);
-               }
-               else
-               {
-                  // We need to create the record before we replicate, since otherwise, two updates can come in for
-                  // the same entry before the first replication comes back, and it won't find the record, so it
-                  // will try and create the queue twice
-                  createNewRecord(entry.getKey(), connectorPair, queueName, null, false);
-
-                  // Replicate the createQueue first
-                  Packet packet = new CreateQueueMessage(queueName, queueName, null, true, false);
-
-                  replicatingChannel.replicatePacket(packet, 1, new Runnable()
-                  {
-                     public void run()
-                     {
-                        try
-                        {
-                           Queue queue = server.createQueue(queueName, queueName, null, true, false);
-
-                           synchronized (ClusterConnectionImpl.this)
-                           {
-                              MessageFlowRecord record = records.get(entry.getKey());
-
-                              if (record != null)
-                              {
-                                 record.activate(queue);
-                              }
-                           }
-                        }
-                        catch (Exception e)
-                        {
-                           log.error("Failed create record", e);
-                        }
-                     }
-                  });
-               }
+               createNewRecord(entry.getKey(), connectorPair, queueName, queue, true);
             }
          }
       }
@@ -456,8 +404,7 @@
                                      managementService.getManagementNotificationAddress(),
                                      managementService.getClusterUser(),
                                      managementService.getClusterPassword(),
-                                     record,
-                                     replicatingChannel,
+                                     record,                                 
                                      !backup,
                                      server.getStorageManager(),
                                      server);
@@ -600,7 +547,7 @@
             {
                case BINDING_ADDED:
                {
-                  doBindingAdded(message, replicatingChannel);
+                  doBindingAdded(message);
 
                   break;
                }
@@ -612,13 +559,13 @@
                }
                case CONSUMER_CREATED:
                {
-                  doConsumerCreated(message, replicatingChannel);
+                  doConsumerCreated(message);
 
                   break;
                }
                case CONSUMER_CLOSED:
                {
-                  doConsumerClosed(message, replicatingChannel);
+                  doConsumerClosed(message);
 
                   break;
                }
@@ -641,11 +588,11 @@
       {       
          for (RemoteQueueBinding binding : new HashSet<RemoteQueueBinding>(bindings.values()))
          {
-            removeBinding(binding.getClusterName(), replicatingChannel);
+            removeBinding(binding.getClusterName());
          }         
       }
 
-      private synchronized void doBindingAdded(final ClientMessage message, final Channel replChannel) throws Exception
+      private synchronized void doBindingAdded(final ClientMessage message) throws Exception
       {
          Integer distance = (Integer)message.getProperty(ManagementHelper.HDR_DISTANCE);
 
@@ -684,38 +631,7 @@
             throw new IllegalStateException("queueID is null");
          }
 
-         if (replChannel != null)
-         {
-            Packet packet = new ReplicateRemoteBindingAddedMessage(name,
-                                                                   queueAddress,
-                                                                   clusterName,
-                                                                   routingName,
-                                                                   queueID,
-                                                                   filterString,
-                                                                   queue.getName(),
-                                                                   distance + 1);
-
-            beforeReplicate();
-            replChannel.replicatePacket(packet, 1, new Runnable()
-            {
-               public void run()
-               {                  
-                  try
-                  {
-                     doBindingAdded(message, null);
-                  }
-                  catch (Exception e)
-                  {
-                     log.error("Failed to add remote queue binding", e);
-                  }
-                  
-                  replicationComplete();
-               }
-            });
-         }
-         else
-         {
-            RemoteQueueBinding binding = new RemoteQueueBindingImpl(queueAddress,
+         RemoteQueueBinding binding = new RemoteQueueBindingImpl(queueAddress,
                                                                     clusterName,
                                                                     routingName,
                                                                     queueID,
@@ -724,33 +640,33 @@
                                                                     bridge.getName(),
                                                                     distance + 1);
 
-            bindings.put(clusterName, binding);
+         bindings.put(clusterName, binding);
 
-            if (postOffice.getBinding(clusterName) != null)
-            {
-               // Sanity check - this means the binding has already been added via another bridge, probably max
-               // hops is too high
-               // or there are multiple cluster connections for the same address
+         if (postOffice.getBinding(clusterName) != null)
+         {
+            // Sanity check - this means the binding has already been added via another bridge, probably max
+            // hops is too high
+            // or there are multiple cluster connections for the same address
 
-               log.warn("Remote queue binding " + clusterName +
-                        " has already been bound in the post office. Most likely cause for this is you have a loop " +
-                        "in your cluster due to cluster max-hops being too large or you have multiple cluster connections to the same nodes using overlapping addresses");
+            log.warn("Remote queue binding " + clusterName +
+                     " has already been bound in the post office. Most likely cause for this is you have a loop " +
+                     "in your cluster due to cluster max-hops being too large or you have multiple cluster connections to the same nodes using overlapping addresses");
 
-               return;
-            }
+            return;
+         }
 
-            try
-            {
-               postOffice.addBinding(binding);
-            }
-            catch (Exception ignore)
-            {
-            }
+         try
+         {
+            postOffice.addBinding(binding);
+         }
+         catch (Exception ignore)
+         {
+         }
 
-            Bindings theBindings = postOffice.getBindingsForAddress(queueAddress);
+         Bindings theBindings = postOffice.getBindingsForAddress(queueAddress);
 
-            theBindings.setRouteWhenNoConsumers(routeWhenNoConsumers);
-         }
+         theBindings.setRouteWhenNoConsumers(routeWhenNoConsumers);
+         
       }
 
       private void doBindingRemoved(final ClientMessage message) throws Exception
@@ -762,47 +678,22 @@
             throw new IllegalStateException("clusterName is null");
          }
 
-         removeBinding(clusterName, replicatingChannel);
+         removeBinding(clusterName);
       }
       
-      private synchronized void removeBinding(final SimpleString clusterName, final Channel replChannel) throws Exception
+      private synchronized void removeBinding(final SimpleString clusterName) throws Exception
       {
-         if (replChannel != null)
-         {
-            Packet packet = new ReplicateRemoteBindingRemovedMessage(clusterName);
+         RemoteQueueBinding binding = bindings.remove(clusterName);
 
-            beforeReplicate();
-            replChannel.replicatePacket(packet, 1, new Runnable()
-            {
-               public void run()
-               {
-                  try
-                  {
-                     removeBinding(clusterName, null);
-                  }
-                  catch (Exception e)
-                  {
-                     log.error("Failed to remove remote queue binding", e);
-                  }
-                  
-                  replicationComplete();
-               }
-            });
-         }
-         else
+         if (binding == null)
          {
-            RemoteQueueBinding binding = bindings.remove(clusterName);
-
-            if (binding == null)
-            {
-               throw new IllegalStateException("Cannot find binding for queue " + clusterName);
-            }
-
-            postOffice.removeBinding(binding.getUniqueName());
+            throw new IllegalStateException("Cannot find binding for queue " + clusterName);
          }
+
+         postOffice.removeBinding(binding.getUniqueName());         
       }
 
-      private synchronized void doConsumerCreated(final ClientMessage message, final Channel replChannel) throws Exception
+      private synchronized void doConsumerCreated(final ClientMessage message) throws Exception
       {
          Integer distance = (Integer)message.getProperty(ManagementHelper.HDR_DISTANCE);
 
@@ -822,47 +713,22 @@
 
          SimpleString filterString = (SimpleString)message.getProperty(ManagementHelper.HDR_FILTERSTRING);
 
-         if (replChannel != null)
-         {
-            Packet packet = new ReplicateRemoteConsumerAddedMessage(clusterName, filterString, message.getProperties());
+         RemoteQueueBinding binding = bindings.get(clusterName);
 
-            beforeReplicate();
-            replChannel.replicatePacket(packet, 1, new Runnable()
-            {
-               public void run()
-               {
-                  try
-                  {
-                     doConsumerCreated(message, null);
-                  }
-                  catch (Exception e)
-                  {
-                     log.error("Failed to add remote consumer", e);
-                  }
-                  
-                  replicationComplete();
-               }
-            });
-         }
-         else
+         if (binding == null)
          {
-            RemoteQueueBinding binding = bindings.get(clusterName);
+            throw new IllegalStateException("Cannot find binding for " + clusterName);
+         }
 
-            if (binding == null)
-            {
-               throw new IllegalStateException("Cannot find binding for " + clusterName);
-            }
+         binding.addConsumer(filterString);
 
-            binding.addConsumer(filterString);
+         // Need to propagate the consumer add
+         Notification notification = new Notification(null, CONSUMER_CREATED, message.getProperties());
 
-            // Need to propagate the consumer add
-            Notification notification = new Notification(null, CONSUMER_CREATED, message.getProperties());
-
-            managementService.sendNotification(notification);
-         }
+         managementService.sendNotification(notification);         
       }
 
-      private synchronized void doConsumerClosed(final ClientMessage message, final Channel replChannel) throws Exception
+      private synchronized void doConsumerClosed(final ClientMessage message) throws Exception
       {
          Integer distance = (Integer)message.getProperty(ManagementHelper.HDR_DISTANCE);
 
@@ -882,46 +748,19 @@
 
          SimpleString filterString = (SimpleString)message.getProperty(ManagementHelper.HDR_FILTERSTRING);
 
-         if (replChannel != null)
-         {
-            Packet packet = new ReplicateRemoteConsumerRemovedMessage(clusterName,
-                                                                      filterString,
-                                                                      message.getProperties());
+         RemoteQueueBinding binding = bindings.get(clusterName);
 
-            beforeReplicate();
-            replChannel.replicatePacket(packet, 1, new Runnable()
-            {
-               public void run()
-               {
-                  try
-                  {
-                     doConsumerClosed(message, null);
-                  }
-                  catch (Exception e)
-                  {
-                     log.error("Failed to remove remote consumer", e);
-                  }
-                  
-                  replicationComplete();
-               }
-            });
-         }
-         else
+         if (binding == null)
          {
-            RemoteQueueBinding binding = bindings.get(clusterName);
+            throw new IllegalStateException("Cannot find binding for " + clusterName);
+         }
 
-            if (binding == null)
-            {
-               throw new IllegalStateException("Cannot find binding for " + clusterName);
-            }
+         binding.removeConsumer(filterString);
 
-            binding.removeConsumer(filterString);
+         // Need to propagate the consumer close
+         Notification notification = new Notification(null, CONSUMER_CLOSED, message.getProperties());
 
-            // Need to propagate the consumer close
-            Notification notification = new Notification(null, CONSUMER_CLOSED, message.getProperties());
-
-            managementService.sendNotification(notification);
-         }
+         managementService.sendNotification(notification);         
       }
 
    }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterManagerImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterManagerImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/ClusterManagerImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -46,7 +46,6 @@
 import org.jboss.messaging.core.management.ManagementService;
 import org.jboss.messaging.core.postoffice.Binding;
 import org.jboss.messaging.core.postoffice.PostOffice;
-import org.jboss.messaging.core.remoting.Channel;
 import org.jboss.messaging.core.server.MessagingServer;
 import org.jboss.messaging.core.server.Queue;
 import org.jboss.messaging.core.server.cluster.Bridge;
@@ -93,8 +92,6 @@
 
    private final UUID nodeUUID;
    
-   private Channel replicatingChannel;
-
    private volatile boolean started;
    
    private boolean backup;
@@ -105,8 +102,7 @@
                              final ScheduledExecutorService scheduledExecutor,
                              final ManagementService managementService,
                              final Configuration configuration,
-                             final UUID nodeUUID,
-                             final Channel replicatingChannel,
+                             final UUID nodeUUID,                            
                              final boolean backup)
    {
       if (nodeUUID == null)
@@ -128,8 +124,6 @@
 
       this.nodeUUID = nodeUUID;
       
-      this.replicatingChannel = replicatingChannel;
-      
       this.backup = backup;
    }
 
@@ -244,9 +238,7 @@
       {
          cc.activate();
       }
-      
-      replicatingChannel = null;
-      
+        
       backup = false;
    }
 
@@ -444,8 +436,7 @@
                                  managementService.getManagementAddress(),
                                  managementService.getManagementNotificationAddress(),
                                  managementService.getClusterUser(),
-                                 managementService.getClusterPassword(),
-                                 replicatingChannel,
+                                 managementService.getClusterPassword(),                             
                                  !backup,
                                  server.getStorageManager());
 
@@ -524,8 +515,7 @@
                                                        scheduledExecutor,                                            
                                                        connectors,
                                                        config.getMaxHops(),
-                                                       nodeUUID,
-                                                       replicatingChannel,
+                                                       nodeUUID,                                             
                                                        backup);
       }
       else
@@ -550,8 +540,7 @@
                                                        scheduledExecutor,                                               
                                                        dg,
                                                        config.getMaxHops(),
-                                                       nodeUUID,
-                                                       replicatingChannel,
+                                                       nodeUUID,                                            
                                                        backup);
       }
 

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/Redistributor.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/Redistributor.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/cluster/impl/Redistributor.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -29,8 +29,6 @@
 import org.jboss.messaging.core.persistence.StorageManager;
 import org.jboss.messaging.core.postoffice.PostOffice;
 import org.jboss.messaging.core.remoting.Channel;
-import org.jboss.messaging.core.remoting.Packet;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRedistributionMessage;
 import org.jboss.messaging.core.server.Consumer;
 import org.jboss.messaging.core.server.HandleStatus;
 import org.jboss.messaging.core.server.MessageReference;
@@ -66,14 +64,11 @@
 
    private int count;
    
-   private final Channel replicatingChannel;
-   
    public Redistributor(final Queue queue,
                         final StorageManager storageManager,
                         final PostOffice postOffice,
                         final Executor executor,
-                        final int batchSize,
-                        final Channel replicatingChannel)
+                        final int batchSize)
    {
       this.queue = queue;
       
@@ -84,8 +79,6 @@
       this.executor = executor;
 
       this.batchSize = batchSize;
-      
-      this.replicatingChannel = replicatingChannel;
    }
    
    public Filter getFilter()
@@ -143,30 +136,8 @@
 
       if (routed)
       {    
-         if (replicatingChannel == null)
-         {
-            doRedistribute(reference, tx);
-         }
-         else
-         {
-            Packet packet = new ReplicateRedistributionMessage(queue.getName(), reference.getMessage().getMessageID());
-            
-            replicatingChannel.replicatePacket(packet, 1, new Runnable()
-            {
-               public void run()
-               {
-                  try
-                  {
-                     doRedistribute(reference, tx);
-                  }
-                  catch (Exception e)
-                  {
-                     log.error("Failed to handle redistribution", e);
-                  }
-               }
-            });
-         }
-
+         doRedistribute(reference, tx);
+         
          return HandleStatus.HANDLED;
       }
       else

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/LastValueQueue.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/LastValueQueue.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/LastValueQueue.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -60,18 +60,18 @@
 
    private final StorageManager storageManager;
 
-   public LastValueQueue(final long persistenceID,
-                        final SimpleString address,
-                        final SimpleString name,
-                        final Filter filter,
-                        final boolean durable,
-                        final boolean temporary,
-                        final ScheduledExecutorService scheduledExecutor,
-                        final PostOffice postOffice,
-                        final StorageManager storageManager,
-                        final HierarchicalRepository<AddressSettings> addressSettingsRepository)
+   public LastValueQueue(final long id,
+                         final SimpleString address,
+                         final SimpleString name,
+                         final Filter filter,
+                         final boolean durable,
+                         final boolean temporary,
+                         final ScheduledExecutorService scheduledExecutor,
+                         final PostOffice postOffice,
+                         final StorageManager storageManager,
+                         final HierarchicalRepository<AddressSettings> addressSettingsRepository)
    {
-      super(persistenceID,
+      super(id,
             address,
             name,
             filter,
@@ -182,7 +182,7 @@
       }
    }
 
-   void postRollback(final LinkedList<MessageReference> refs) throws Exception
+   protected void postRollback(final LinkedList<MessageReference> refs) throws Exception
    {
       List<MessageReference> refsToDiscard = new ArrayList<MessageReference>();
       List<SimpleString> refsToClear = new ArrayList<SimpleString>();
@@ -220,7 +220,7 @@
       super.postRollback(refs);
    }
 
-   final void discardMessage(MessageReference ref, Transaction tx) throws Exception
+   private final void discardMessage(MessageReference ref, Transaction tx) throws Exception
    {
       deliveringCount.decrementAndGet();
       PagingStore store = pagingManager.getPageStore(ref.getMessage().getDestination());
@@ -241,13 +241,13 @@
             }
             else
             {
-               storageManager.deleteMessageTransactional(tx.getID(), getPersistenceID(), msg.getMessageID());
+               storageManager.deleteMessageTransactional(tx.getID(), getID(), msg.getMessageID());
             }
          }
       }
    }
 
-   final void discardMessage(Long id, Transaction tx) throws Exception
+   private final void discardMessage(long id, Transaction tx) throws Exception
    {
       RefsOperation oper = getRefsOperation(tx);
       Iterator<MessageReference> iterator = oper.refsToAdd.iterator();
@@ -266,7 +266,7 @@
 
    }
 
-   final void rediscardMessage(long id, Transaction tx) throws Exception
+   private final void rediscardMessage(long id, Transaction tx) throws Exception
    {
       RefsOperation oper = getRefsOperation(tx);
       Iterator<MessageReference> iterator = oper.refsToAdd.iterator();
@@ -284,7 +284,7 @@
       }
    }
 
-   final void rediscardMessage(MessageReference ref) throws Exception
+   private final void rediscardMessage(final MessageReference ref) throws Exception
    {
       deliveringCount.decrementAndGet();
       PagingStore store = pagingManager.getPageStore(ref.getMessage().getDestination());

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -32,8 +32,6 @@
 import javax.management.MBeanServer;
 
 import org.jboss.messaging.core.client.impl.ClientSessionFactoryImpl;
-import org.jboss.messaging.core.client.impl.ConnectionManager;
-import org.jboss.messaging.core.client.impl.ConnectionManagerImpl;
 import org.jboss.messaging.core.config.Configuration;
 import org.jboss.messaging.core.config.TransportConfiguration;
 import org.jboss.messaging.core.config.cluster.DivertConfiguration;
@@ -61,20 +59,27 @@
 import org.jboss.messaging.core.persistence.impl.journal.JournalStorageManager;
 import org.jboss.messaging.core.persistence.impl.nullpm.NullStorageManager;
 import org.jboss.messaging.core.postoffice.Binding;
+import org.jboss.messaging.core.postoffice.ClusterQueueStateManager;
 import org.jboss.messaging.core.postoffice.DuplicateIDCache;
 import org.jboss.messaging.core.postoffice.PostOffice;
+import org.jboss.messaging.core.postoffice.impl.ClusterQueueStateManagerImpl;
 import org.jboss.messaging.core.postoffice.impl.DivertBinding;
 import org.jboss.messaging.core.postoffice.impl.LocalQueueBinding;
 import org.jboss.messaging.core.postoffice.impl.PostOfficeImpl;
 import org.jboss.messaging.core.remoting.Channel;
-import org.jboss.messaging.core.remoting.FailureListener;
+import org.jboss.messaging.core.remoting.ChannelHandler;
 import org.jboss.messaging.core.remoting.Packet;
 import org.jboss.messaging.core.remoting.RemotingConnection;
+import org.jboss.messaging.core.remoting.impl.RemotingConnectionImpl;
 import org.jboss.messaging.core.remoting.impl.wireformat.CreateSessionResponseMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
 import org.jboss.messaging.core.remoting.impl.wireformat.ReattachSessionResponseMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateStartupInfoMessage;
 import org.jboss.messaging.core.remoting.server.RemotingService;
 import org.jboss.messaging.core.remoting.server.impl.RemotingServiceImpl;
+import org.jboss.messaging.core.remoting.spi.Connection;
+import org.jboss.messaging.core.remoting.spi.ConnectionLifeCycleListener;
+import org.jboss.messaging.core.remoting.spi.ConnectorFactory;
 import org.jboss.messaging.core.security.CheckType;
 import org.jboss.messaging.core.security.JBMSecurityManager;
 import org.jboss.messaging.core.security.Role;
@@ -90,6 +95,9 @@
 import org.jboss.messaging.core.server.cluster.ClusterManager;
 import org.jboss.messaging.core.server.cluster.Transformer;
 import org.jboss.messaging.core.server.cluster.impl.ClusterManagerImpl;
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.core.server.replication.impl.JBMThread;
+import org.jboss.messaging.core.server.replication.impl.ReplicatorImpl;
 import org.jboss.messaging.core.settings.HierarchicalRepository;
 import org.jboss.messaging.core.settings.impl.AddressSettings;
 import org.jboss.messaging.core.settings.impl.HierarchicalObjectRepository;
@@ -186,20 +194,13 @@
 
    private final Map<String, ServerSession> sessions = new ConcurrentHashMap<String, ServerSession>();
 
-   private RemotingConnection replicatingConnection;
-
-   private Channel replicatingChannel;
-
    private final Object initialiseLock = new Object();
 
    private boolean initialised;
-   
-   private ConnectionManager replicatingConnectionManager;
 
    private int managementConnectorID;
-   
+
    private static AtomicInteger managementConnectorSequence = new AtomicInteger(0);
-   
 
    // Constructors
    // ---------------------------------------------------------------------------------
@@ -223,7 +224,7 @@
    {
       this(configuration, null, securityManager);
    }
-   
+
    public MessagingServerImpl(Configuration configuration,
                               MBeanServer mbeanServer,
                               final JBMSecurityManager securityManager)
@@ -252,10 +253,10 @@
       this.addressSettingsRepository = new HierarchicalObjectRepository<AddressSettings>();
 
       addressSettingsRepository.setDefault(new AddressSettings());
-      
+
       this.managementConnectorID = managementConnectorSequence.decrementAndGet();
    }
-   
+
    // lifecycle methods
    // ----------------------------------------------------------------
 
@@ -286,7 +287,7 @@
    }
 
    public synchronized void stop() throws Exception
-   {      
+   {
       if (!started)
       {
          return;
@@ -335,23 +336,10 @@
          securityManager.stop();
       }
 
-      if (replicatingConnection != null)
-      {
-         try
-         {
-            replicatingConnection.destroy();
-         }
-         catch (Exception ignore)
-         {
-         }
+      resourceManager.stop();
 
-         replicatingConnection = null;
-         replicatingChannel = null;
-         
-         replicatingConnectionManager.close();
-      }
+      clusterQueueStateManager.stop();
 
-      resourceManager.stop();
       postOffice.stop();
 
       // Need to shutdown pools before shutting down paging manager to make sure everything is written ok
@@ -492,39 +480,8 @@
       }
    }
 
-   public void replicateCreateSession(final String name,
-                                      final long replicatedChannelID,
-                                      final long originalChannelID,
-                                      final String username,
-                                      final String password,
-                                      final int minLargeMessageSize,
-                                      final int incrementingVersion,
-                                      final RemotingConnection connection,
-                                      final boolean autoCommitSends,
-                                      final boolean autoCommitAcks,
-                                      final boolean preAcknowledge,
-                                      final boolean xa,
-                                      final int producerWindowSize) throws Exception
-   {
-      doCreateSession(name,
-                      replicatedChannelID,
-                      originalChannelID,
-                      username,
-                      password,
-                      minLargeMessageSize,
-                      incrementingVersion,
-                      connection,
-                      autoCommitSends,
-                      autoCommitAcks,
-                      preAcknowledge,
-                      xa,
-                      producerWindowSize,
-                      true);
-   }
-
    public CreateSessionResponseMessage createSession(final String name,
                                                      final long channelID,
-                                                     final long replicatedChannelID,
                                                      final String username,
                                                      final String password,
                                                      final int minLargeMessageSize,
@@ -534,13 +491,16 @@
                                                      final boolean autoCommitAcks,
                                                      final boolean preAcknowledge,
                                                      final boolean xa,
-                                                     final int sendWindowSize) throws Exception
+                                                     final int sendWindowSize,
+                                                     final boolean direct) throws Exception
    {
-      checkActivate(connection);
-      
+      if (direct)
+      {
+         checkActivate(connection);
+      }
+
       return doCreateSession(name,
                              channelID,
-                             replicatedChannelID,
                              username,
                              password,
                              minLargeMessageSize,
@@ -598,7 +558,7 @@
       {
          throw new IllegalArgumentException("node id is null");
       }
-      
+
       synchronized (initialiseLock)
       {
          if (initialised)
@@ -618,9 +578,12 @@
          {
             initialised = false;
 
-            throw new IllegalStateException("Live and backup unique ids different (" + liveUniqueID + ":" + backupID + "). You're probably trying to restart a live backup pair after a crash");
+            throw new IllegalStateException("Live and backup unique ids different (" + liveUniqueID +
+                                            ":" +
+                                            backupID +
+                                            "). You're probably trying to restart a live backup pair after a crash");
          }
-         
+
          log.info("Backup server is now operational");
       }
    }
@@ -730,7 +693,7 @@
 
       if (queue.isDurable())
       {
-         storageManager.deleteQueueBinding(queue.getPersistenceID());
+         storageManager.deleteQueueBinding(queue.getID());
       }
 
       postOffice.removeBinding(queueName);
@@ -746,6 +709,148 @@
       activateCallbacks.remove(callback);
    }
 
+   private ConnectorFactory backupConnectorFactory;
+
+   private Map<String, Object> backupConnectorParams;
+
+   private void setupBackupConnectorFactory()
+   {
+      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
+         {
+
+            ClassLoader loader = Thread.currentThread().getContextClassLoader();
+            try
+            {
+               Class<?> clz = loader.loadClass(backupConnector.getFactoryClassName());
+               backupConnectorFactory = (ConnectorFactory)clz.newInstance();
+            }
+            catch (Exception e)
+            {
+               throw new IllegalArgumentException("Error instantiating interceptor \"" + backupConnector.getFactoryClassName() +
+                                                           "\"",
+                                                  e);
+            }
+
+            backupConnectorParams = backupConnector.getParams();
+         }
+      }
+   }
+
+   private boolean activatedBackup;
+
+   public synchronized RemotingConnection getReplicatingConnection()
+   {
+      // Note we must always get a new connection each time - since there must
+      // be a one to one correspondence
+      // between connections to clients and replicating connections, since we
+      // need to preserve channel ids
+      // before and after failover
+
+      if (backupConnectorFactory != null)
+      {
+         NoCacheConnectionLifeCycleListener listener = new NoCacheConnectionLifeCycleListener();
+
+         RemotingConnectionImpl replicatingConnection = (RemotingConnectionImpl)RemotingConnectionImpl.createConnection(backupConnectorFactory,
+                                                                                                                        backupConnectorParams,
+                                                                                                                        ClientSessionFactoryImpl.DEFAULT_CALL_TIMEOUT,
+                                                                                                                        threadPool,
+                                                                                                                        listener);
+
+         listener.conn = replicatingConnection;
+
+         if (!activatedBackup)
+         {
+            // 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());
+
+            Channel channel1 = replicatingConnection.getChannel(1, -1, false);
+
+            ChannelHandler prevHandler = channel1.getHandler();
+            
+            log.info("Prev handler is " + prevHandler);
+            
+            final Future future = new Future();
+
+            channel1.setHandler(new ChannelHandler()
+            {
+               public void handlePacket(final Packet packet)
+               {
+                  if (packet.getType() == PacketImpl.REPLICATION_RESPONSE)
+                  {
+                     log.info("&&&&&&&&&&&&&&&& got replication response");
+                     future.run();
+                  }
+                  else
+                  {
+                     throw new IllegalArgumentException("Invalid packet " + packet.getType());
+                  }
+               }
+            });
+
+            channel1.send(packet);
+
+            boolean ok = future.await(10000);
+
+            if (!ok)
+            {
+               throw new IllegalStateException("Timed out waiting for response from backup for initialisation");
+            }
+
+            log.info("got response");
+            
+            channel1.setHandler(prevHandler);
+
+            activatedBackup = true;
+         }
+
+         // TODO - pinging + execute outstanding results on channels when failure occurs!!!
+
+         return replicatingConnection;
+      }
+      else
+      {
+         return null;
+      }
+
+   }
+
+   private static class NoCacheConnectionLifeCycleListener implements ConnectionLifeCycleListener
+   {
+      private RemotingConnection conn;
+
+      public void connectionCreated(final Connection connection)
+      {
+      }
+
+      public void connectionDestroyed(final Object connectionID)
+      {
+         if (conn != null)
+         {
+            conn.destroy();
+         }
+      }
+
+      public void connectionException(final Object connectionID, final MessagingException me)
+      {
+         if (conn != null)
+         {
+            conn.fail(me);
+         }
+      }
+   }
+
    // Public
    // ---------------------------------------------------------------------------------------
 
@@ -782,7 +887,7 @@
       if (configuration.isBackup())
       {
          log.info("A connection has been made to the backup server so it will be activated! This will result in the live server being considered failed.");
-         
+
          synchronized (this)
          {
             freezeBackupConnection();
@@ -802,7 +907,7 @@
             {
                clusterManager.activate();
             }
-            
+
             if (configuration.isFileDeploymentEnabled())
             {
                queueDeployer = new QueueDeployer(deploymentManager, messagingServerControl);
@@ -854,7 +959,7 @@
    {
       // Create the pools - we have two pools - one for non scheduled - and another for scheduled
 
-      ThreadFactory tFactory = new JBMThreadFactory("JBM-server-threads" + System.identityHashCode(this), false);
+      ThreadFactory tFactory = new JBMThreadThreadFactory("JBM-server-threads" + System.identityHashCode(this), false);
 
       if (configuration.getThreadPoolMaxSize() == -1)
       {
@@ -867,15 +972,24 @@
 
       executorFactory = new OrderedExecutorFactory(threadPool);
 
-      scheduledPool = new ScheduledThreadPoolExecutor(configuration.getScheduledThreadPoolMaxSize(),
-                                                      new org.jboss.messaging.utils.JBMThreadFactory("JBM-scheduled-threads",
-                                                                                                     false));
+      ThreadFactory scheduledTFactory = new JBMThreadThreadFactory("JBM-scheduled-threads", false);
 
+      scheduledPool = new ScheduledThreadPoolExecutor(configuration.getScheduledThreadPoolMaxSize(), scheduledTFactory);
+
       managementService = new ManagementServiceImpl(mbeanServer, configuration, managementConnectorID);
-      
-      remotingService = new RemotingServiceImpl(configuration, this, managementService, threadPool, scheduledPool, managementConnectorID);
+
+      remotingService = new RemotingServiceImpl(configuration,
+                                                this,
+                                                managementService,
+                                                threadPool,
+                                                scheduledPool,
+                                                managementConnectorID);
+
+      setupBackupConnectorFactory();
    }
-   
+
+   private ClusterQueueStateManager clusterQueueStateManager;
+
    private void initialisePart2() throws Exception
    {
       // Create the hard-wired components
@@ -891,7 +1005,7 @@
       }
       else
       {
-         storageManager = new NullStorageManager();
+         storageManager = new NullStorageManager(configuration.isBackup());
       }
 
       securityRepository = new HierarchicalObjectRepository<Set<Role>>();
@@ -911,8 +1025,7 @@
 
       resourceManager = new ResourceManagerImpl((int)(configuration.getTransactionTimeout() / 1000),
                                                 configuration.getTransactionTimeoutScanPeriod());
-      postOffice = new PostOfficeImpl(this,
-                                      storageManager,
+      postOffice = new PostOfficeImpl(storageManager,
                                       pagingManager,
                                       queueFactory,
                                       managementService,
@@ -921,10 +1034,14 @@
                                       configuration.isWildcardRoutingEnabled(),
                                       configuration.isBackup(),
                                       configuration.getIDCacheSize(),
-                                      configuration.isPersistIDCache(),
-                                      executorFactory,
-                                      addressSettingsRepository);
+                                      configuration.isPersistIDCache());
 
+      clusterQueueStateManager = new ClusterQueueStateManagerImpl(executorFactory,
+                                                                  addressSettingsRepository,
+                                                                  postOffice,
+                                                                  storageManager,
+                                                                  managementService);
+
       messagingServerControl = managementService.registerServer(postOffice,
                                                                 storageManager,
                                                                 configuration,
@@ -934,9 +1051,10 @@
                                                                 remotingService,
                                                                 this,
                                                                 queueFactory,
+                                                                clusterQueueStateManager,
                                                                 configuration.isBackup());
 
-      // Address settings need to deployed initially, since they're require on paging manager.start()
+      // Address settings need to deployed initially, since they're required on paging manager.start()
 
       if (configuration.isFileDeploymentEnabled())
       {
@@ -954,6 +1072,11 @@
 
       postOffice.start();
 
+      if (clusterQueueStateManager != null)
+      {
+         clusterQueueStateManager.start();
+      }
+
       pagingManager.start();
 
       managementService.start();
@@ -983,8 +1106,9 @@
       deployQueuesFromConfiguration();
 
       // Deploy any predefined queues
-      
-      // We don't activate queue deployer on the backup - all queues deployed on live are deployed on backup by replicating them
+
+      // We don't activate queue deployer on the backup - all queues deployed on live are deployed on backup by
+      // replicating them
       if (configuration.isFileDeploymentEnabled() && !configuration.isBackup())
       {
          queueDeployer = new QueueDeployer(deploymentManager, messagingServerControl);
@@ -999,11 +1123,11 @@
       // Deply any pre-defined diverts
       deployDiverts();
 
-      // Set-up the replicating connection
-      if (!setupReplicatingConnection())
-      {
-         return;
-      }
+      // // Set-up the replicating connection
+      // if (!setupReplicatingConnection())
+      // {
+      // return;
+      // }
 
       if (configuration.isClustered())
       {
@@ -1015,7 +1139,6 @@
                                                  managementService,
                                                  configuration,
                                                  uuid,
-                                                 replicatingChannel,
                                                  configuration.isBackup());
 
          clusterManager.start();
@@ -1044,90 +1167,90 @@
       }
    }
 
-   public Channel getReplicatingChannel()
-   {
-      return replicatingChannel;
-   }
+   // public RemotingConnection getReplicatingConnection()
+   // {
+   //      
+   // }
 
-   private boolean setupReplicatingConnection() throws Exception
-   {
-      String backupConnectorName = configuration.getBackupConnectorName();
+   // 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 boolean connectionFailed(MessagingException me)
+   // {
+   // replicatingChannel.executeOutstandingDelayedResults();
+   //
+   // return true;
+   // }
+   // });
+   //
+   // // 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;
+   // }
 
-      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 boolean connectionFailed(MessagingException me)
-                  {
-                     replicatingChannel.executeOutstandingDelayedResults();
-
-                     return true;
-                  }
-               });
-
-               // 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 void loadJournal() throws Exception
    {
       List<QueueBindingInfo> queueBindingInfos = new ArrayList<QueueBindingInfo>();
@@ -1180,15 +1303,15 @@
    }
 
    private void setNodeID() throws Exception
-   {      
+   {
       if (!configuration.isBackup())
-      {         
+      {
          if (uuid == null)
-         {            
+         {
             uuid = storageManager.getPersistentID();
-            
+
             if (uuid == null)
-            {               
+            {
                uuid = UUIDGenerator.getInstance().generateUUID();
 
                storageManager.setPersistentID(uuid);
@@ -1198,9 +1321,9 @@
          }
       }
       else
-      {         
+      {
          UUID currentUUID = storageManager.getPersistentID();
-         
+
          if (currentUUID != null)
          {
             if (!currentUUID.equals(uuid))
@@ -1222,6 +1345,7 @@
                              final boolean temporary,
                              final boolean ignoreIfExists) throws Exception
    {
+      log.info("** creating queue " + queueName);
       Binding binding = postOffice.getBinding(queueName);
 
       if (binding != null)
@@ -1243,7 +1367,7 @@
          filter = new FilterImpl(filterString);
       }
 
-      final Queue queue = queueFactory.createQueue(-1, address, queueName, filter, durable, temporary);
+      final Queue queue = queueFactory.createQueue(storageManager.generateUniqueID(), address, queueName, filter, durable, temporary);
 
       binding = new LocalQueueBinding(address, queue, nodeID);
 
@@ -1322,7 +1446,6 @@
 
    private CreateSessionResponseMessage doCreateSession(final String name,
                                                         final long channelID,
-                                                        final long oppositeChannelID,
                                                         final String username,
                                                         final String password,
                                                         final int minLargeMessageSize,
@@ -1364,11 +1487,42 @@
       }
 
       Channel channel = connection.getChannel(channelID, sendWindowSize, false);
+           
+      RemotingConnection replicatingConnection = connection.getReplicatingConnection();
+      
+      log.info("getting repl conenction from " + System.identityHashCode(connection) + " it is " + replicatingConnection);
 
-      Channel replicatingChannel = getReplicatingChannel();
+      log.info("Creating session, replicating connection is " + replicatingConnection);
 
+      final Replicator replicator;
+
+      if (replicatingConnection != null)
+      {
+         Channel replicatingChannel = replicatingConnection.getChannel(channelID, -1, false);
+
+         replicator = new ReplicatorImpl(replicatingChannel);
+
+         replicatingChannel.setHandler(new ChannelHandler()
+         {
+            public void handlePacket(final Packet packet)
+            {
+               if (packet.getType() == PacketImpl.REPLICATION_RESPONSE)
+               {
+                  replicator.replicationResponseReceived();
+               }
+               else
+               {
+                  throw new IllegalArgumentException("Invalid packet " + packet.getType());
+               }
+            }
+         });
+      }
+      else
+      {
+         replicator = null;
+      }
+
       final ServerSessionImpl session = new ServerSessionImpl(name,
-                                                              oppositeChannelID,
                                                               username,
                                                               password,
                                                               minLargeMessageSize,
@@ -1387,14 +1541,14 @@
                                                               managementService,
                                                               queueFactory,
                                                               this,
-                                                              configuration.getManagementAddress(),
-                                                              replicatingChannel,
-                                                              backup);
+                                                              configuration.getManagementAddress());
 
       sessions.put(name, session);
+ 
+      ServerSessionPacketHandler handler = new ServerSessionPacketHandler(session, replicator, configuration);
 
-      ServerSessionPacketHandler handler = new ServerSessionPacketHandler(session);
-
+      log.info(System.identityHashCode(handler)+ " ** creating serversessionpackethandler on backup "+ configuration.isBackup() + " replicator is " + replicator);      
+      
       session.setHandler(handler);
 
       channel.setHandler(handler);
@@ -1441,4 +1595,31 @@
       }
    }
 
+   private static class JBMThreadThreadFactory extends JBMThreadFactory
+   {
+      public JBMThreadThreadFactory(final String groupName, final boolean daemon)
+      {
+         super(groupName, daemon);
+      }
+
+      public JBMThreadThreadFactory(final String groupName, final int threadPriority, final boolean daemon)
+      {
+         super(groupName, threadPriority, daemon);
+      }
+
+      @Override
+      public Thread newThread(final Runnable command)
+      {
+         Thread t = new JBMThread(group, command, "Thread-" + threadCount.getAndIncrement() +
+                                                  " (group:" +
+                                                  group.getName() +
+                                                  ")");
+
+         t.setDaemon(daemon);
+         t.setPriority(threadPriority);
+         return t;
+      }
+
+   }
+
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -17,9 +17,11 @@
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.CREATESESSION;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.CREATE_QUEUE;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REATTACH_SESSION;
-import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_CREATESESSION;
+import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_LOCK_SEQUENCES;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_STARTUP_INFO;
 
+import java.util.List;
+
 import org.jboss.messaging.core.exception.MessagingException;
 import org.jboss.messaging.core.logging.Logger;
 import org.jboss.messaging.core.management.Notification;
@@ -33,21 +35,24 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.MessagingExceptionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
 import org.jboss.messaging.core.remoting.impl.wireformat.ReattachSessionMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.ReplicateCreateSessionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateAcknowledgeMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateLockSequenceMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRedistributionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteBindingAddedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteBindingRemovedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteConsumerAddedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateRemoteConsumerRemovedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateStartupInfoMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicationResponseMessage;
 import org.jboss.messaging.core.server.MessageReference;
 import org.jboss.messaging.core.server.MessagingServer;
 import org.jboss.messaging.core.server.Queue;
 import org.jboss.messaging.core.server.cluster.ClusterConnection;
 import org.jboss.messaging.core.server.cluster.RemoteQueueBinding;
-import org.jboss.messaging.core.transaction.Transaction;
-import org.jboss.messaging.core.transaction.impl.TransactionImpl;
+import org.jboss.messaging.core.server.replication.ReplicableAction;
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.core.server.replication.impl.JBMThread;
+import org.jboss.messaging.utils.Pair;
 
 /**
  * A packet handler for all packets that need to be handled at the server level
@@ -56,7 +61,7 @@
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @author <a href="ataylor at redhat.com">Andy Taylor</a>
  */
-public class MessagingServerPacketHandler implements ChannelHandler
+public class MessagingServerPacketHandler implements ChannelHandler, ReplicableAction
 {
    private static final Logger log = Logger.getLogger(MessagingServerPacketHandler.class);
 
@@ -66,19 +71,81 @@
 
    private final RemotingConnection connection;
    
+   private Replicator replicator;
+   
+   private Packet packet;
+   
+   private List<Pair<Long, Integer>> sequences;
+      
    public MessagingServerPacketHandler(final MessagingServer server,
                                        final Channel channel1,
-                                       final RemotingConnection connection)
+                                       final RemotingConnection connection,
+                                       final Replicator replicator)
    {
       this.server = server;
 
       this.channel1 = channel1;
 
       this.connection = connection;
+      
+      this.replicator = replicator;
    }
-
+   
+   public void run()
+   {
+      handlePacket();
+   }
+   
+   public Packet getPacket()
+   {
+      return packet;
+   }
+   
    public void handlePacket(final Packet packet)
    {
+      this.packet = packet;
+      
+      log.info("Handling packet " + packet.getType() + " on backup " + server.getConfiguration().isBackup());
+      
+      if (server.getConfiguration().isBackup())
+      {         
+         log.info("getting current thread");
+         
+         JBMThread thread = JBMThread.currentThread();
+         
+         thread.setReplay(sequences);
+         
+         //thread.setReplay(true);
+         
+         log.info("about to call handle packet");
+         
+         handlePacket();  
+         
+         //send the response message
+         
+         log.info("sending back replication response");
+         
+         if (packet.getType() != PacketImpl.REPLICATE_LOCK_SEQUENCES)
+         {
+            channel1.send(new ReplicationResponseMessage());
+         }
+      }
+      else
+      {     
+         log.info("not backup");
+         if (replicator != null)
+         {
+            replicator.execute(this);
+         }
+         else
+         {
+            handlePacket();
+         }
+      }
+   }
+
+   private void handlePacket()
+   {
       byte type = packet.getType();
       
       if (!server.isInitialised() && type != PacketImpl.REPLICATE_STARTUP_INFO)
@@ -90,6 +157,13 @@
       // reliability replay functionality
       switch (type)
       {
+         case REPLICATE_LOCK_SEQUENCES:
+         {
+            ReplicateLockSequenceMessage msg = (ReplicateLockSequenceMessage)packet;
+            sequences = msg.getSequences();
+            log.info("Got sequences " + sequences.size());
+            return;
+         }
          case REPLICATE_STARTUP_INFO:
          {          
             ReplicateStartupInfoMessage msg = (ReplicateStartupInfoMessage)packet;
@@ -109,18 +183,11 @@
          {
             CreateSessionMessage request = (CreateSessionMessage)packet;
 
-            handleCreateSession(request);
+            log.info("sequences is " + sequences);
+            handleCreateSession(request, sequences == null);
 
             break;
          }
-         case REPLICATE_CREATESESSION:
-         {
-            ReplicateCreateSessionMessage request = (ReplicateCreateSessionMessage)packet;
-
-            handleReplicateCreateSession(request);
-
-            break;
-         }
          case REATTACH_SESSION:
          {
             ReattachSessionMessage request = (ReattachSessionMessage)packet;
@@ -192,16 +259,16 @@
             log.error("Invalid packet " + packet);
          }
       }
+      sequences = null;
    }
 
-   private void doHandleCreateSession(final CreateSessionMessage request, final long oppositeChannelID)
+   private void handleCreateSession(final CreateSessionMessage request, final boolean activate)
    {
       Packet response;
       try
-      {
+      {         
          response = server.createSession(request.getName(),
-                                         request.getSessionChannelID(),
-                                         oppositeChannelID,
+                                         request.getSessionChannelID(),                                         
                                          request.getUsername(),
                                          request.getPassword(),
                                          request.getMinLargeMessageSize(),
@@ -211,7 +278,8 @@
                                          request.isAutoCommitAcks(),
                                          request.isPreAcknowledge(),
                                          request.isXA(),
-                                         request.getWindowSize());
+                                         request.getWindowSize(),
+                                         activate);
       }
       catch (Exception e)
       {
@@ -227,68 +295,9 @@
          }
       }
       
-      channel1.send(response);
+      channel1.send(response); 
    }
-
-   private void handleCreateSession(final CreateSessionMessage request)
-   {
-      Channel replicatingChannel = server.getReplicatingChannel();
-
-      if (replicatingChannel == null)
-      {
-         doHandleCreateSession(request, -1);
-      }
-      else
-      {
-         final long replicatedChannelID = replicatingChannel.getConnection().generateChannelID();
-
-         Packet replPacket = new ReplicateCreateSessionMessage(request.getName(),
-                                                               replicatedChannelID,
-                                                               request.getSessionChannelID(),
-                                                               request.getVersion(),
-                                                               request.getUsername(),
-                                                               request.getPassword(),
-                                                               request.getMinLargeMessageSize(),
-                                                               request.isXA(),
-                                                               request.isAutoCommitSends(),
-                                                               request.isAutoCommitAcks(),
-                                                               request.isPreAcknowledge(),
-                                                               request.getWindowSize());
-
-         replicatingChannel.replicatePacket(replPacket, 1, new Runnable()
-         {
-            public void run()
-            {
-               doHandleCreateSession(request, replicatedChannelID);
-            }
-         });
-      }
-   }
-
-   private void handleReplicateCreateSession(final ReplicateCreateSessionMessage request)
-   {
-      try
-      {
-         server.replicateCreateSession(request.getName(),
-                                       request.getReplicatedSessionChannelID(),
-                                       request.getOriginalSessionChannelID(),
-                                       request.getUsername(),
-                                       request.getPassword(),
-                                       request.getMinLargeMessageSize(),
-                                       request.getVersion(),
-                                       connection,
-                                       request.isAutoCommitSends(),
-                                       request.isAutoCommitAcks(),
-                                       request.isPreAcknowledge(),
-                                       request.isXA(),
-                                       request.getWindowSize());
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to handle replicate create session", e);
-      }
-   }
-
+   
    private void handleReattachSession(final ReattachSessionMessage request)
    {
       Packet response;

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueFactoryImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueFactoryImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueFactoryImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -68,7 +68,7 @@
       this.postOffice = postOffice;
    }
 
-   public Queue createQueue(final long persistenceID,
+   public Queue createQueue(final long id,
                             final SimpleString address,
                             final SimpleString name,
                             final Filter filter,
@@ -80,7 +80,7 @@
       Queue queue;
       if (addressSettings.isLastValueQueue())
       {
-         queue = new LastValueQueue(persistenceID,
+         queue = new LastValueQueue(id,
                                    address,
                                    name,
                                    filter,
@@ -93,7 +93,7 @@
       }
       else
       {
-         queue = new QueueImpl(persistenceID,
+         queue = new QueueImpl(id,
                                address,
                                name,
                                filter,

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/QueueImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -28,10 +28,10 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
 
 import org.jboss.messaging.core.filter.Filter;
 import org.jboss.messaging.core.list.PriorityLinkedList;
@@ -43,7 +43,6 @@
 import org.jboss.messaging.core.persistence.StorageManager;
 import org.jboss.messaging.core.postoffice.Bindings;
 import org.jboss.messaging.core.postoffice.PostOffice;
-import org.jboss.messaging.core.remoting.Channel;
 import org.jboss.messaging.core.server.Consumer;
 import org.jboss.messaging.core.server.Distributor;
 import org.jboss.messaging.core.server.HandleStatus;
@@ -52,6 +51,7 @@
 import org.jboss.messaging.core.server.ScheduledDeliveryHandler;
 import org.jboss.messaging.core.server.ServerMessage;
 import org.jboss.messaging.core.server.cluster.impl.Redistributor;
+import org.jboss.messaging.core.server.replication.impl.StatefulObjectReadWriteLock;
 import org.jboss.messaging.core.settings.HierarchicalRepository;
 import org.jboss.messaging.core.settings.impl.AddressSettings;
 import org.jboss.messaging.core.transaction.Transaction;
@@ -63,7 +63,7 @@
 import org.jboss.messaging.utils.SimpleString;
 
 /**
- * Implementation of a Queue TODO use Java 5 concurrent queue
+ * Implementation of a Queue
  *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @author <a href="ataylor at redhat.com">Andy Taylor</a>
@@ -76,11 +76,9 @@
 
    public static final int REDISTRIBUTOR_BATCH_SIZE = 100;
 
-   private static final boolean trace = log.isTraceEnabled();
-
    public static final int NUM_PRIORITIES = 10;
 
-   private volatile long persistenceID = -1;
+   private final long id;
 
    private final SimpleString name;
 
@@ -114,8 +112,6 @@
 
    private final PagingManager pagingManager;
 
-   private final Semaphore lock = new Semaphore(1);
-
    private volatile PagingStore pagingStore;
 
    private final StorageManager storageManager;
@@ -140,7 +136,9 @@
 
    private final Set<Consumer> consumers = new HashSet<Consumer>();
 
-   public QueueImpl(final long persistenceID,
+   private final Lock lock;
+
+   public QueueImpl(final long id,
                     final SimpleString address,
                     final SimpleString name,
                     final Filter filter,
@@ -151,7 +149,7 @@
                     final StorageManager storageManager,
                     final HierarchicalRepository<AddressSettings> addressSettingsRepository)
    {
-      this.persistenceID = persistenceID;
+      this.id = id;
 
       this.address = address;
 
@@ -183,6 +181,8 @@
       direct = true;
 
       scheduledDeliveryHandler = new ScheduledDeliveryHandlerImpl(scheduledExecutor);
+      
+      lock = new StatefulObjectReadWriteLock(name.toString(), id, 0).writeLock();
    }
 
    // Bindable implementation -------------------------------------------------------------------------------------
@@ -241,6 +241,7 @@
 
       if (tx == null)
       {
+
          if (durableRef)
          {
             if (!message.isStored())
@@ -250,7 +251,7 @@
                message.setStored();
             }
 
-            storageManager.storeReference(ref.getQueue().getPersistenceID(), message.getMessageID());
+            storageManager.storeReference(ref.getQueue().getID(), message.getMessageID());
          }
 
          if (scheduledDeliveryTime != null && durableRef)
@@ -274,7 +275,7 @@
             tx.putProperty(TransactionPropertyIndexes.CONTAINS_PERSISTENT, true);
 
             storageManager.storeReferenceTransactional(tx.getID(),
-                                                       ref.getQueue().getPersistenceID(),
+                                                       ref.getQueue().getID(),
                                                        message.getMessageID());
          }
 
@@ -332,33 +333,6 @@
 
    // Queue implementation ----------------------------------------------------------------------------------------
 
-   public void lockDelivery()
-   {
-      if (backup)
-      {
-         return;
-      }
-      
-      try
-      {
-         lock.acquire();
-      }
-      catch (InterruptedException e)
-      {
-         log.warn(e.getMessage(), e);
-      }
-   }
-
-   public void unlockDelivery()
-   {
-      if (backup)
-      {
-         return;
-      }
-      
-      lock.release();
-   }
-
    public boolean isDurable()
    {
       return durable;
@@ -374,16 +348,11 @@
       return name;
    }
 
-   public long getPersistenceID()
+   public long getID()
    {
-      return persistenceID;
+      return id;
    }
 
-   public void setPersistenceID(final long id)
-   {
-      persistenceID = id;
-   }
-
    public Filter getFilter()
    {
       return filter;
@@ -410,67 +379,100 @@
    }
 
    // Only used in testing - do not call directly!
-   public synchronized void deliverNow()
+   public void deliverNow()
    {
-      deliver();
+      lock.lock();
+      try
+      {
+         deliver();
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized void addConsumer(final Consumer consumer) throws Exception
+   public void addConsumer(final Consumer consumer) throws Exception
    {
-      cancelRedistributor();
+      lock.lock();
+      try
+      {
+         cancelRedistributor();
 
-      distributionPolicy.addConsumer(consumer);
+         distributionPolicy.addConsumer(consumer);
 
-      consumers.add(consumer);
+         consumers.add(consumer);
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean removeConsumer(final Consumer consumer) throws Exception
+   public boolean removeConsumer(final Consumer consumer) throws Exception
    {
-      boolean removed = distributionPolicy.removeConsumer(consumer);
+      lock.lock();
+      try
+      {
+         boolean removed = distributionPolicy.removeConsumer(consumer);
 
-      if (!distributionPolicy.hasConsumers())
+         if (!distributionPolicy.hasConsumers())
+         {
+            promptDelivery = false;
+         }
+
+         consumers.remove(consumer);
+
+         return removed;
+      }
+      finally
       {
-         promptDelivery = false;
+         lock.unlock();
       }
-
-      consumers.remove(consumer);
-
-      return removed;
    }
 
-   public synchronized void addRedistributor(final long delay, final Executor executor, final Channel replicatingChannel)
+   public void addRedistributor(final long delay, final Executor executor)
    {
-      if (future != null)
+      lock.lock();
+
+      try
       {
-         future.cancel(false);
+         if (future != null)
+         {
+            future.cancel(false);
 
-         futures.remove(future);
-      }
+            futures.remove(future);
+         }
 
-      if (redistributor != null)
-      {
-         // Just prompt delivery
-         deliverAsync(executor);
-      }
+         if (redistributor != null)
+         {
+            // Just prompt delivery
+            deliverAsync(executor);
+         }
 
-      if (delay > 0)
-      {
-         if (consumers.size() == 0)
+         if (delay > 0)
          {
-            DelayedAddRedistributor dar = new DelayedAddRedistributor(executor, replicatingChannel);
+            if (consumers.size() == 0)
+            {
+               DelayedAddRedistributor dar = new DelayedAddRedistributor(executor);
 
-            future = scheduledExecutor.schedule(dar, delay, TimeUnit.MILLISECONDS);
+               future = scheduledExecutor.schedule(dar, delay, TimeUnit.MILLISECONDS);
 
-            futures.add(future);
+               futures.add(future);
+            }
          }
+         else
+         {
+            internalAddRedistributor(executor);
+         }
       }
-      else
+      finally
       {
-         internalAddRedistributor(executor, replicatingChannel);
+         lock.unlock();
       }
    }
 
-   public synchronized void cancelRedistributor() throws Exception
+   private void cancelRedistributor() throws Exception
    {
       if (redistributor != null)
       {
@@ -487,129 +489,201 @@
       }
    }
 
-   public synchronized int getConsumerCount()
+   public int getConsumerCount()
    {
-      return consumers.size();
+      lock.lock();
+
+      try
+      {
+         return consumers.size();
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized Set<Consumer> getConsumers()
+   public Set<Consumer> getConsumers()
    {
       return consumers;
    }
 
-   public synchronized List<MessageReference> list(final Filter filter)
+   public List<MessageReference> list(final Filter filter)
    {
-      if (filter == null)
+      lock.lock();
+
+      try
       {
-         return new ArrayList<MessageReference>(messageReferences.getAll());
-      }
-      else
-      {
-         ArrayList<MessageReference> list = new ArrayList<MessageReference>();
+         if (filter == null)
+         {
+            return new ArrayList<MessageReference>(messageReferences.getAll());
+         }
+         else
+         {
+            ArrayList<MessageReference> list = new ArrayList<MessageReference>();
 
-         for (MessageReference ref : messageReferences.getAll())
-         {
-            if (filter.match(ref.getMessage()))
+            for (MessageReference ref : messageReferences.getAll())
             {
-               list.add(ref);
+               if (filter.match(ref.getMessage()))
+               {
+                  list.add(ref);
+               }
             }
+
+            return list;
          }
-
-         return list;
       }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized MessageReference removeReferenceWithID(final long id) throws Exception
+   public MessageReference removeReferenceWithID(final long id) throws Exception
    {
-      Iterator<MessageReference> iterator = messageReferences.iterator();
+      lock.lock();
 
-      MessageReference removed = null;
-
-      while (iterator.hasNext())
+      try
       {
-         MessageReference ref = iterator.next();
+         Iterator<MessageReference> iterator = messageReferences.iterator();
 
-         if (ref.getMessage().getMessageID() == id)
+         MessageReference removed = null;
+
+         while (iterator.hasNext())
          {
-            iterator.remove();
+            MessageReference ref = iterator.next();
 
-            removed = ref;
+            if (ref.getMessage().getMessageID() == id)
+            {
+               iterator.remove();
 
-            removeExpiringReference(removed);
+               removed = ref;
 
-            break;
+               removeExpiringReference(removed);
+
+               break;
+            }
          }
+
+         if (removed == null)
+         {
+            // Look in scheduled deliveries
+            removed = scheduledDeliveryHandler.removeReferenceWithID(id);
+         }
+
+         return removed;
       }
-
-      if (removed == null)
+      finally
       {
-         // Look in scheduled deliveries
-         removed = scheduledDeliveryHandler.removeReferenceWithID(id);
+         lock.unlock();
       }
-
-      return removed;
    }
 
-   public synchronized MessageReference removeFirstReference(final long id) throws Exception
+   public MessageReference removeFirstReference(final long id) throws Exception
    {
-      MessageReference ref = messageReferences.peekFirst();
+      lock.lock();
 
-      if (ref != null && ref.getMessage().getMessageID() == id)
+      try
       {
-         messageReferences.removeFirst();
+         MessageReference ref = messageReferences.peekFirst();
 
+         if (ref != null && ref.getMessage().getMessageID() == id)
+         {
+            messageReferences.removeFirst();
+
+            return ref;
+         }
+         else
+         {
+            ref = scheduledDeliveryHandler.removeReferenceWithID(id);
+         }
+
          return ref;
       }
-      else
+      finally
       {
-         ref = scheduledDeliveryHandler.removeReferenceWithID(id);
+         lock.unlock();
       }
-
-      return ref;
    }
 
-   public synchronized MessageReference getReference(final long id)
+   public MessageReference getReference(final long id)
    {
-      Iterator<MessageReference> iterator = messageReferences.iterator();
+      lock.lock();
 
-      while (iterator.hasNext())
+      try
       {
-         MessageReference ref = iterator.next();
+         Iterator<MessageReference> iterator = messageReferences.iterator();
 
-         if (ref.getMessage().getMessageID() == id)
+         while (iterator.hasNext())
          {
-            return ref;
+            MessageReference ref = iterator.next();
+
+            if (ref.getMessage().getMessageID() == id)
+            {
+               return ref;
+            }
          }
+
+         return null;
       }
-
-      return null;
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized int getMessageCount()
+   public int getMessageCount()
    {
-      int count = messageReferences.size() + getScheduledCount() + getDeliveringCount();
+      lock.lock();
 
-      // log.info(System.identityHashCode(this) + " message count is " +
-      // count +
-      // " ( mr:" +
-      // messageReferences.size() +
-      // " sc:" +
-      // getScheduledCount() +
-      // " dc:" +
-      // getDeliveringCount() +
-      // ")");
+      try
+      {
+         int count = messageReferences.size() + getScheduledCount() + getDeliveringCount();
 
-      return count;
+         // log.info(System.identityHashCode(this) + " message count is " +
+         // count +
+         // " ( mr:" +
+         // messageReferences.size() +
+         // " sc:" +
+         // getScheduledCount() +
+         // " dc:" +
+         // getDeliveringCount() +
+         // ")");
+
+         return count;
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized int getScheduledCount()
+   public int getScheduledCount()
    {
-      return scheduledDeliveryHandler.getScheduledCount();
+      lock.lock();
+
+      try
+      {
+         return scheduledDeliveryHandler.getScheduledCount();
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized List<MessageReference> getScheduledMessages()
+   public List<MessageReference> getScheduledMessages()
    {
-      return scheduledDeliveryHandler.getScheduledReferences();
+      lock.lock();
+
+      try
+      {
+         return scheduledDeliveryHandler.getScheduledReferences();
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
    public int getDeliveringCount()
@@ -625,7 +699,7 @@
 
       if (durableRef)
       {
-         storageManager.storeAcknowledge(persistenceID, message.getMessageID());
+         storageManager.storeAcknowledge(id, message.getMessageID());
       }
 
       postAcknowledge(ref);
@@ -639,7 +713,7 @@
 
       if (durableRef)
       {
-         storageManager.storeAcknowledgeTransactional(tx.getID(), persistenceID, message.getMessageID());
+         storageManager.storeAcknowledgeTransactional(tx.getID(), id, message.getMessageID());
 
          tx.putProperty(TransactionPropertyIndexes.CONTAINS_PERSISTENT, true);
       }
@@ -683,15 +757,24 @@
       getRefsOperation(tx).addAck(reference);
    }
 
-   public synchronized void cancel(final MessageReference reference) throws Exception
+   public void cancel(final MessageReference reference) throws Exception
    {
-      if (checkDLQ(reference))
+      lock.lock();
+
+      try
       {
-         if (!scheduledDeliveryHandler.checkAndSchedule(reference, backup))
+         if (checkDLQ(reference))
          {
-            messageReferences.addFirst(reference, reference.getMessage().getPriority());
+            if (!scheduledDeliveryHandler.checkAndSchedule(reference, backup))
+            {
+               messageReferences.addFirst(reference, reference.getMessage().getPriority());
+            }
          }
       }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
    public void expire(final MessageReference ref) throws Exception
@@ -744,214 +827,294 @@
       return deleteMatchingReferences(null);
    }
 
-   public synchronized int deleteMatchingReferences(final Filter filter) throws Exception
+   public int deleteMatchingReferences(final Filter filter) throws Exception
    {
-      int count = 0;
+      lock.lock();
 
-      Transaction tx = new TransactionImpl(storageManager);
+      try
+      {
+         int count = 0;
 
-      Iterator<MessageReference> iter = messageReferences.iterator();
+         Transaction tx = new TransactionImpl(storageManager);
 
-      while (iter.hasNext())
-      {
-         MessageReference ref = iter.next();
+         Iterator<MessageReference> iter = messageReferences.iterator();
 
-         if (filter == null || filter.match(ref.getMessage()))
+         while (iter.hasNext())
          {
-            deliveringCount.incrementAndGet();
-            acknowledge(tx, ref);
-            iter.remove();
-            count++;
+            MessageReference ref = iter.next();
+
+            if (filter == null || filter.match(ref.getMessage()))
+            {
+               deliveringCount.incrementAndGet();
+               acknowledge(tx, ref);
+               iter.remove();
+               count++;
+            }
          }
-      }
 
-      List<MessageReference> cancelled = scheduledDeliveryHandler.cancel();
-      for (MessageReference messageReference : cancelled)
-      {
-         if (filter == null || filter.match(messageReference.getMessage()))
+         List<MessageReference> cancelled = scheduledDeliveryHandler.cancel();
+         for (MessageReference messageReference : cancelled)
          {
-            deliveringCount.incrementAndGet();
-            acknowledge(tx, messageReference);
-            count++;
+            if (filter == null || filter.match(messageReference.getMessage()))
+            {
+               deliveringCount.incrementAndGet();
+               acknowledge(tx, messageReference);
+               count++;
+            }
          }
-      }
 
-      tx.commit();
+         tx.commit();
 
-      return count;
+         return count;
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean deleteReference(final long messageID) throws Exception
+   public boolean deleteReference(final long messageID) throws Exception
    {
-      boolean deleted = false;
+      lock.lock();
 
-      Transaction tx = new TransactionImpl(storageManager);
+      try
+      {
+         boolean deleted = false;
 
-      Iterator<MessageReference> iter = messageReferences.iterator();
+         Transaction tx = new TransactionImpl(storageManager);
 
-      while (iter.hasNext())
-      {
-         MessageReference ref = iter.next();
-         if (ref.getMessage().getMessageID() == messageID)
+         Iterator<MessageReference> iter = messageReferences.iterator();
+
+         while (iter.hasNext())
          {
-            deliveringCount.incrementAndGet();
-            acknowledge(tx, ref);
-            iter.remove();
-            deleted = true;
-            break;
+            MessageReference ref = iter.next();
+            if (ref.getMessage().getMessageID() == messageID)
+            {
+               deliveringCount.incrementAndGet();
+               acknowledge(tx, ref);
+               iter.remove();
+               deleted = true;
+               break;
+            }
          }
-      }
 
-      tx.commit();
+         tx.commit();
 
-      return deleted;
+         return deleted;
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean expireReference(final long messageID) throws Exception
+   public boolean expireReference(final long messageID) throws Exception
    {
-      Iterator<MessageReference> iter = messageReferences.iterator();
+      lock.lock();
 
-      while (iter.hasNext())
+      try
       {
-         MessageReference ref = iter.next();
-         if (ref.getMessage().getMessageID() == messageID)
+         Iterator<MessageReference> iter = messageReferences.iterator();
+
+         while (iter.hasNext())
          {
-            deliveringCount.incrementAndGet();
-            expire(ref);
-            iter.remove();
-            return true;
+            MessageReference ref = iter.next();
+            if (ref.getMessage().getMessageID() == messageID)
+            {
+               deliveringCount.incrementAndGet();
+               expire(ref);
+               iter.remove();
+               return true;
+            }
          }
+         return false;
       }
-      return false;
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized int expireReferences(final Filter filter) throws Exception
+   public int expireReferences(final Filter filter) throws Exception
    {
-      Transaction tx = new TransactionImpl(storageManager);
+      lock.lock();
 
-      int count = 0;
-      Iterator<MessageReference> iter = messageReferences.iterator();
+      try
+      {
+         Transaction tx = new TransactionImpl(storageManager);
 
-      while (iter.hasNext())
-      {
-         MessageReference ref = iter.next();
-         if (filter == null || filter.match(ref.getMessage()))
+         int count = 0;
+         Iterator<MessageReference> iter = messageReferences.iterator();
+
+         while (iter.hasNext())
          {
-            deliveringCount.incrementAndGet();
-            expire(tx, ref);
-            iter.remove();
-            count++;
+            MessageReference ref = iter.next();
+            if (filter == null || filter.match(ref.getMessage()))
+            {
+               deliveringCount.incrementAndGet();
+               expire(tx, ref);
+               iter.remove();
+               count++;
+            }
          }
-      }
 
-      tx.commit();
+         tx.commit();
 
-      return count;
+         return count;
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized void expireReferences() throws Exception
+   public void expireReferences() throws Exception
    {
-      for (MessageReference expiringMessageReference : expiringMessageReferences)
+      lock.lock();
+
+      try
       {
-         if (expiringMessageReference.getMessage().isExpired())
+         for (MessageReference expiringMessageReference : expiringMessageReferences)
          {
-            expireReference(expiringMessageReference.getMessage().getMessageID());
+            if (expiringMessageReference.getMessage().isExpired())
+            {
+               expireReference(expiringMessageReference.getMessage().getMessageID());
+            }
          }
       }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean sendMessageToDeadLetterAddress(final long messageID) throws Exception
+   public boolean sendMessageToDeadLetterAddress(final long messageID) throws Exception
    {
-      Iterator<MessageReference> iter = messageReferences.iterator();
+      lock.lock();
 
-      while (iter.hasNext())
+      try
       {
-         MessageReference ref = iter.next();
-         if (ref.getMessage().getMessageID() == messageID)
+         Iterator<MessageReference> iter = messageReferences.iterator();
+
+         while (iter.hasNext())
          {
-            deliveringCount.incrementAndGet();
-            sendToDeadLetterAddress(ref);
-            iter.remove();
-            return true;
+            MessageReference ref = iter.next();
+            if (ref.getMessage().getMessageID() == messageID)
+            {
+               deliveringCount.incrementAndGet();
+               sendToDeadLetterAddress(ref);
+               iter.remove();
+               return true;
+            }
          }
+         return false;
       }
-      return false;
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean moveReference(final long messageID, final SimpleString toAddress) throws Exception
+   public boolean moveReference(final long messageID, final SimpleString toAddress) throws Exception
    {
-      Iterator<MessageReference> iter = messageReferences.iterator();
+      lock.lock();
 
-      while (iter.hasNext())
+      try
       {
-         MessageReference ref = iter.next();
-         if (ref.getMessage().getMessageID() == messageID)
+         Iterator<MessageReference> iter = messageReferences.iterator();
+
+         while (iter.hasNext())
          {
-            iter.remove();
-            deliveringCount.incrementAndGet();
-            move(toAddress, ref);
-            return true;
+            MessageReference ref = iter.next();
+            if (ref.getMessage().getMessageID() == messageID)
+            {
+               iter.remove();
+               deliveringCount.incrementAndGet();
+               move(toAddress, ref);
+               return true;
+            }
          }
+         return false;
       }
-      return false;
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized int moveReferences(final Filter filter, final SimpleString toAddress) throws Exception
+   public int moveReferences(final Filter filter, final SimpleString toAddress) throws Exception
    {
-      Transaction tx = new TransactionImpl(storageManager);
+      lock.lock();
 
-      int count = 0;
-      Iterator<MessageReference> iter = messageReferences.iterator();
+      try
+      {
+         Transaction tx = new TransactionImpl(storageManager);
 
-      while (iter.hasNext())
-      {
-         MessageReference ref = iter.next();
-         if (filter == null || filter.match(ref.getMessage()))
+         int count = 0;
+         Iterator<MessageReference> iter = messageReferences.iterator();
+
+         while (iter.hasNext())
          {
-            deliveringCount.incrementAndGet();
-            move(toAddress, tx, ref, false);
-            iter.remove();
-            count++;
+            MessageReference ref = iter.next();
+            if (filter == null || filter.match(ref.getMessage()))
+            {
+               deliveringCount.incrementAndGet();
+               move(toAddress, tx, ref, false);
+               iter.remove();
+               count++;
+            }
          }
-      }
 
-      List<MessageReference> cancelled = scheduledDeliveryHandler.cancel();
-      for (MessageReference ref : cancelled)
-      {
-         if (filter == null || filter.match(ref.getMessage()))
+         List<MessageReference> cancelled = scheduledDeliveryHandler.cancel();
+         for (MessageReference ref : cancelled)
          {
-            deliveringCount.incrementAndGet();
-            move(toAddress, tx, ref, false);
-            acknowledge(tx, ref);
-            count++;
+            if (filter == null || filter.match(ref.getMessage()))
+            {
+               deliveringCount.incrementAndGet();
+               move(toAddress, tx, ref, false);
+               acknowledge(tx, ref);
+               count++;
+            }
          }
-      }
 
-      tx.commit();
+         tx.commit();
 
-      return count;
+         return count;
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean changeReferencePriority(final long messageID, final byte newPriority) throws Exception
+   public boolean changeReferencePriority(final long messageID, final byte newPriority) throws Exception
    {
-      List<MessageReference> refs = list(null);
-      for (MessageReference ref : refs)
+      lock.lock();
+      try
       {
-         ServerMessage message = ref.getMessage();
-         if (message.getMessageID() == messageID)
+         List<MessageReference> refs = list(null);
+         for (MessageReference ref : refs)
          {
-            message.setPriority(newPriority);
-            // delete and add the reference so that it
-            // goes to the right queues for the new priority
+            ServerMessage message = ref.getMessage();
+            if (message.getMessageID() == messageID)
+            {
+               message.setPriority(newPriority);
+               // delete and add the reference so that it
+               // goes to the right queues for the new priority
 
-            // FIXME - why deleting the reference?? This will delete it from storage!!
+               // FIXME - why deleting the reference?? This will delete it from storage!!
 
-            deleteReference(messageID);
-            addLast(ref);
-            return true;
+               deleteReference(messageID);
+               addLast(ref);
+               return true;
+            }
          }
+         return false;
       }
-      return false;
+      finally
+      {
+         lock.unlock();
+      }
    }
 
    public boolean isBackup()
@@ -959,64 +1122,98 @@
       return backup;
    }
 
-   public synchronized void setBackup()
+   public void setBackup()
    {
       backup = true;
 
       direct = false;
    }
 
-   public synchronized boolean activate()
+   public boolean activate()
    {
-      consumersToFailover = consumers.size();
-
-      if (consumersToFailover == 0)
+      lock.lock();
+      try
       {
-         backup = false;
+         consumersToFailover = consumers.size();
 
-         return true;
+         if (consumersToFailover == 0)
+         {
+            backup = false;
+
+            return true;
+         }
+         else
+         {
+            return false;
+         }
       }
-      else
+      finally
       {
-         return false;
+         lock.unlock();
       }
    }
 
-   public synchronized void activateNow(final Executor executor)
+   public void activateNow(final Executor executor)
    {
-      if (backup)
+      lock.lock();
+      try
       {
-         log.info("Timed out waiting for all consumers to reconnect to queue " + name +
-                  " so queue will be activated now");
+         if (backup)
+         {
+            log.info("Timed out waiting for all consumers to reconnect to queue " + name +
+                     " so queue will be activated now");
 
-         backup = false;
+            backup = false;
 
-         scheduledDeliveryHandler.reSchedule();
+            scheduledDeliveryHandler.reSchedule();
 
-         deliverAsync(executor);
+            deliverAsync(executor);
+         }
       }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   public synchronized boolean consumerFailedOver()
+   public boolean consumerFailedOver()
    {
-      consumersToFailover--;
-
-      if (consumersToFailover == 0)
+      lock.lock();
+      try
       {
-         // All consumers for the queue have failed over, can re-activate it now
+         consumersToFailover--;
 
-         backup = false;
+         if (consumersToFailover == 0)
+         {
+            // All consumers for the queue have failed over, can re-activate it now
 
-         scheduledDeliveryHandler.reSchedule();
+            backup = false;
 
-         return true;
+            scheduledDeliveryHandler.reSchedule();
+
+            return true;
+         }
+         else
+         {
+            return false;
+         }
       }
-      else
+      finally
       {
-         return false;
+         lock.unlock();
       }
    }
 
+   public void lock()
+   {
+      lock.lock();
+   }
+
+   public void unlock()
+   {
+      lock.unlock();
+   }
+
    // Public
    // -----------------------------------------------------------------------------
 
@@ -1048,17 +1245,12 @@
    // Private
    // ------------------------------------------------------------------------------
 
-   private void internalAddRedistributor(final Executor executor, final Channel replicatingChannel)
+   private void internalAddRedistributor(final Executor executor)
    {
       // create the redistributor only once if there are no local consumers
       if (consumers.size() == 0 && redistributor == null)
       {
-         redistributor = new Redistributor(this,
-                                           storageManager,
-                                           postOffice,
-                                           executor,
-                                           REDISTRIBUTOR_BATCH_SIZE,
-                                           replicatingChannel);
+         redistributor = new Redistributor(this, storageManager, postOffice, executor, REDISTRIBUTOR_BATCH_SIZE);
 
          distributionPolicy.addConsumer(redistributor);
 
@@ -1228,181 +1420,198 @@
    /*
     * Attempt to deliver all the messages in the queue
     */
-   private synchronized void deliver()
+   private void deliver()
    {
-      // We don't do actual delivery if the queue is on a backup node - this is
-      // because it's async and could get out of step
-      // with the live node. Instead, when we replicate the delivery we remove
-      // the ref from the queue
+      lock.lock();
 
-      if (backup)
+      try
       {
-         return;
-      }
+         // We don't do actual delivery if the queue is on a backup node - this is
+         // because it's async and could get out of step
+         // with the live node. Instead, when we replicate the delivery we remove
+         // the ref from the queue
 
-      direct = false;
+         if (backup)
+         {
+            return;
+         }
 
-      MessageReference reference;
+         direct = false;
 
-      Iterator<MessageReference> iterator = null;
+         MessageReference reference;
 
-      while (true)
-      {
-         if (iterator == null)
+         Iterator<MessageReference> iterator = null;
+
+         while (true)
          {
-            reference = messageReferences.peekFirst();
-         }
-         else
-         {
-            if (iterator.hasNext())
+            if (iterator == null)
             {
-               reference = iterator.next();
+               reference = messageReferences.peekFirst();
             }
             else
             {
-               reference = null;
+               if (iterator.hasNext())
+               {
+                  reference = iterator.next();
+               }
+               else
+               {
+                  reference = null;
+               }
             }
-         }
 
-         if (reference == null)
-         {
-            if (iterator == null)
+            if (reference == null)
             {
-               if (pagingStore != null)
+               if (iterator == null)
                {
-                  // If the queue is empty, we need to check if there are pending messages, and throw a warning
-                  if (pagingStore.isPaging() && !pagingStore.isDropWhenMaxSize())
+                  if (pagingStore != null)
                   {
-                     // This is just a *request* to depage. Depage will only happens if there is space on the Address
-                     // and GlobalSize
-                     pagingStore.startDepaging();
+                     // If the queue is empty, we need to check if there are pending messages, and throw a warning
+                     if (pagingStore.isPaging() && !pagingStore.isDropWhenMaxSize())
+                     {
+                        // This is just a *request* to depage. Depage will only happens if there is space on the Address
+                        // and GlobalSize
+                        pagingStore.startDepaging();
 
-                     log.warn("The Queue " + name +
-                              " is empty, however there are pending messages on Paging for the address " +
-                              pagingStore.getStoreName() +
-                              " waiting message ACK before they could be routed");
+                        log.warn("The Queue " + name +
+                                 " is empty, however there are pending messages on Paging for the address " +
+                                 pagingStore.getStoreName() +
+                                 " waiting message ACK before they could be routed");
+                     }
                   }
+                  // We delivered all the messages - go into direct delivery
+                  direct = true;
+
+                  promptDelivery = false;
                }
-               // We delivered all the messages - go into direct delivery
-               direct = true;
-
-               promptDelivery = false;
+               return;
             }
-            return;
-         }
 
-         // PagingManager would be null only on testcases
-         if (pagingStore == null && pagingManager != null)
-         {
-            // TODO: It would be better if we could initialize the pagingStore during the construction
-            try
+            // PagingManager would be null only on testcases
+            if (pagingStore == null && pagingManager != null)
             {
-               pagingStore = pagingManager.getPageStore(reference.getMessage().getDestination());
+               // TODO: It would be better if we could initialize the pagingStore during the construction
+               try
+               {
+                  pagingStore = pagingManager.getPageStore(reference.getMessage().getDestination());
+               }
+               catch (Exception e)
+               {
+                  // This shouldn't happen, and if it happens, this shouldn't abort the route
+               }
             }
-            catch (Exception e)
-            {
-               // This shouldn't happen, and if it happens, this shouldn't abort the route
-            }
-         }
 
-         HandleStatus status = deliver(reference);
+            HandleStatus status = deliver(reference);
 
-         if (status == HandleStatus.HANDLED)
-         {
-            if (iterator == null)
+            if (status == HandleStatus.HANDLED)
             {
-               messageReferences.removeFirst();
+               if (iterator == null)
+               {
+                  messageReferences.removeFirst();
+               }
+               else
+               {
+                  iterator.remove();
+               }
             }
-            else
+            else if (status == HandleStatus.BUSY)
             {
-               iterator.remove();
+               // All consumers busy - give up
+               break;
             }
+            else if (status == HandleStatus.NO_MATCH && iterator == null)
+            {
+               // Consumers not all busy - but filter not accepting - iterate
+               // back
+               // through the queue
+               iterator = messageReferences.iterator();
+            }
          }
-         else if (status == HandleStatus.BUSY)
-         {
-            // All consumers busy - give up
-            break;
-         }
-         else if (status == HandleStatus.NO_MATCH && iterator == null)
-         {
-            // Consumers not all busy - but filter not accepting - iterate
-            // back
-            // through the queue
-            iterator = messageReferences.iterator();
-         }
       }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
-   private synchronized void add(final MessageReference ref, final boolean first)
+   private void add(final MessageReference ref, final boolean first)
    {
-      if (!first)
+      lock.lock();
+      try
       {
-         messagesAdded.incrementAndGet();
-      }
+         if (!first)
+         {
+            messagesAdded.incrementAndGet();
+         }
 
-      if (scheduledDeliveryHandler.checkAndSchedule(ref, backup))
-      {
-         return;
-      }
+         if (scheduledDeliveryHandler.checkAndSchedule(ref, backup))
+         {
+            return;
+         }
 
-      boolean add = false;
+         boolean add = false;
 
-      if (direct && !backup)
-      {
-         // Deliver directly
+         if (direct && !backup)
+         {
+            // Deliver directly
 
-         HandleStatus status = deliver(ref);
+            HandleStatus status = deliver(ref);
 
-         if (status == HandleStatus.HANDLED)
-         {
-            // Ok
+            if (status == HandleStatus.HANDLED)
+            {
+               // Ok
+            }
+            else if (status == HandleStatus.BUSY)
+            {
+               add = true;
+            }
+            else if (status == HandleStatus.NO_MATCH)
+            {
+               add = true;
+            }
+
+            if (add)
+            {
+               direct = false;
+            }
          }
-         else if (status == HandleStatus.BUSY)
+         else
          {
             add = true;
          }
-         else if (status == HandleStatus.NO_MATCH)
-         {
-            add = true;
-         }
 
          if (add)
          {
-            direct = false;
+            if (ref.getMessage().getExpiration() != 0)
+            {
+               expiringMessageReferences.addIfAbsent(ref);
+            }
+
+            if (first)
+            {
+               messageReferences.addFirst(ref, ref.getMessage().getPriority());
+            }
+            else
+            {
+               messageReferences.addLast(ref, ref.getMessage().getPriority());
+            }
+
+            if (!direct && promptDelivery)
+            {
+               // We have consumers with filters which don't match, so we need
+               // to prompt delivery every time
+               // a new message arrives - this is why you really shouldn't use
+               // filters with queues - in most cases
+               // it's an ant-pattern since it would cause a queue scan on each
+               // message
+               deliver();
+            }
          }
       }
-      else
+      finally
       {
-         add = true;
+         lock.unlock();
       }
-
-      if (add)
-      {
-         if (ref.getMessage().getExpiration() != 0)
-         {
-            expiringMessageReferences.addIfAbsent(ref);
-         }
-
-         if (first)
-         {
-            messageReferences.addFirst(ref, ref.getMessage().getPriority());
-         }
-         else
-         {
-            messageReferences.addLast(ref, ref.getMessage().getPriority());
-         }
-
-         if (!direct && promptDelivery)
-         {
-            // We have consumers with filters which don't match, so we need
-            // to prompt delivery every time
-            // a new message arrives - this is why you really shouldn't use
-            // filters with queues - in most cases
-            // it's an ant-pattern since it would cause a queue scan on each
-            // message
-            deliver();
-         }
-      }
    }
 
    private HandleStatus deliver(final MessageReference reference)
@@ -1474,9 +1683,10 @@
       }
    }
 
-   void postRollback(LinkedList<MessageReference> refs) throws Exception
+   protected void postRollback(LinkedList<MessageReference> refs) throws Exception
    {
-      synchronized (this)
+      lock.lock();
+      try
       {
          for (MessageReference ref : refs)
          {
@@ -1490,6 +1700,10 @@
 
          deliver();
       }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
    // Inner classes
@@ -1502,15 +1716,7 @@
          // Must be set to false *before* executing to avoid race
          waitingToDeliver.set(false);
 
-         QueueImpl.this.lockDelivery();
-         try
-         {
-            deliver();
-         }
-         finally
-         {
-            QueueImpl.this.unlockDelivery();
-         }
+         deliver();
       }
    }
 
@@ -1565,10 +1771,15 @@
 
             QueueImpl queue = entry.getKey();
 
-            synchronized (queue)
+            queue.lock.lock();
+            try
             {
                queue.postRollback(refs);
             }
+            finally
+            {
+               queue.lock.unlock();
+            }
          }
       }
 
@@ -1596,10 +1807,15 @@
 
          for (MessageReference ref : refsToAck)
          {
-            synchronized (ref.getQueue())
+            ref.getQueue().lock();
+            try
             {
                postAcknowledge(ref);
             }
+            finally
+            {
+               ref.getQueue().unlock();
+            }
          }
       }
 
@@ -1635,23 +1851,24 @@
    {
       private final Executor executor;
 
-      private final Channel replicatingChannel;
-
-      DelayedAddRedistributor(final Executor executor, final Channel replicatingChannel)
+      private DelayedAddRedistributor(final Executor executor)
       {
          this.executor = executor;
-
-         this.replicatingChannel = replicatingChannel;
       }
 
       public void run()
       {
-         synchronized (QueueImpl.this)
+         lock.lock();
+         try
          {
-            internalAddRedistributor(executor, replicatingChannel);
+            internalAddRedistributor(executor);
 
             futures.remove(this);
          }
+         finally
+         {
+            lock.unlock();
+         }
       }
    }
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -26,9 +26,7 @@
 import java.util.LinkedList;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
 
 import org.jboss.messaging.core.buffers.ChannelBuffers;
 import org.jboss.messaging.core.client.management.impl.ManagementHelper;
@@ -43,19 +41,17 @@
 import org.jboss.messaging.core.postoffice.Binding;
 import org.jboss.messaging.core.postoffice.QueueBinding;
 import org.jboss.messaging.core.remoting.Channel;
-import org.jboss.messaging.core.remoting.Packet;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionReceiveContinuationMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionReceiveMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.SessionReplicateDeliveryMessage;
 import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
 import org.jboss.messaging.core.server.HandleStatus;
 import org.jboss.messaging.core.server.LargeServerMessage;
 import org.jboss.messaging.core.server.MessageReference;
-import org.jboss.messaging.core.server.MessagingServer;
 import org.jboss.messaging.core.server.Queue;
 import org.jboss.messaging.core.server.ServerConsumer;
 import org.jboss.messaging.core.server.ServerMessage;
 import org.jboss.messaging.core.server.ServerSession;
+import org.jboss.messaging.core.server.replication.impl.StatefulObjectReadWriteLock;
 import org.jboss.messaging.core.transaction.Transaction;
 import org.jboss.messaging.core.transaction.impl.TransactionImpl;
 import org.jboss.messaging.utils.TypedProperties;
@@ -77,19 +73,10 @@
 
    // Static ---------------------------------------------------------------------------------------
 
-   private static final boolean trace = log.isTraceEnabled();
-
-   private static void trace(final String message)
-   {
-      log.trace(message);
-   }
-
    // Attributes -----------------------------------------------------------------------------------
 
    private final long id;
 
-   private final long replicatedSessionID;
-
    private final Queue messageQueue;
 
    private final Filter filter;
@@ -100,17 +87,15 @@
 
    private final Executor executor;
 
-   private final Lock lock = new ReentrantLock();
+   private final Lock lock;
 
-   private AtomicInteger availableCredits = new AtomicInteger(0);
+   private int availableCredits;
 
    private boolean started;
 
    private volatile LargeMessageDeliverer largeMessageDeliverer = null;
 
-   // We will only be sending one largeMessage at any time, however during replication you may have
-   // more than one LargeMessage pending on the replicationBuffer
-   private final AtomicInteger pendingLargeMessagesCounter = new AtomicInteger(0);
+   private volatile boolean hasPendingLargeMessage;
 
    /**
     * if we are a browse only consumer we don't need to worry about acknowledgemenets or being started/stopeed by the session.
@@ -127,8 +112,6 @@
 
    private final Channel channel;
 
-   private final Channel replicatingChannel;
-
    private volatile boolean closed;
 
    private final boolean preAcknowledge;
@@ -137,10 +120,11 @@
 
    private final Binding binding;
 
+   private boolean flowControl = true;
+
    // Constructors ---------------------------------------------------------------------------------
 
    public ServerConsumerImpl(final long id,
-                             final long replicatedSessionID,
                              final ServerSession session,
                              final QueueBinding binding,
                              final Filter filter,
@@ -149,7 +133,6 @@
                              final StorageManager storageManager,
                              final PagingManager pagingManager,
                              final Channel channel,
-                             final Channel replicatingChannel,
                              final boolean preAcknowledge,
                              final boolean updateDeliveries,
                              final Executor executor,
@@ -157,8 +140,6 @@
    {
       this.id = id;
 
-      this.replicatedSessionID = replicatedSessionID;
-
       this.filter = filter;
 
       this.session = session;
@@ -177,8 +158,6 @@
 
       this.channel = channel;
 
-      this.replicatingChannel = replicatingChannel;
-
       this.preAcknowledge = preAcknowledge;
 
       this.pagingManager = pagingManager;
@@ -188,7 +167,9 @@
       this.minLargeMessageSize = session.getMinLargeMessageSize();
 
       this.updateDeliveries = updateDeliveries;
-      
+
+      lock = new StatefulObjectReadWriteLock("consumer " + id, storageManager.generateUniqueID(), 0).writeLock();
+
       binding.getQueue().addConsumer(this);
    }
 
@@ -300,6 +281,7 @@
    public void setStarted(final boolean started)
    {
       lock.lock();
+
       try
       {
          this.started = browseOnly || started;
@@ -315,32 +297,40 @@
          promptDelivery();
       }
    }
-
+   
    public void receiveCredits(final int credits) throws Exception
    {
-      if (credits == -1)
-      {
-         // No flow control
-         availableCredits = null;
-      }
-      else
-      {
-         int previous = availableCredits.getAndAdd(credits);
+      boolean promptDelivery = false;
 
-         if (trace)
+      lock.lock();
+
+      try
+      {
+         if (credits == -1)
          {
-            log.trace("Received " + credits +
-                      " credits, previous value = " +
-                      previous +
-                      " currentValue = " +
-                      availableCredits.get());
+            // No flow control
+            flowControl = false;
          }
-
-         if (previous <= 0 && previous + credits > 0)
+         else
          {
-            promptDelivery();
+            if (availableCredits <= 0 && availableCredits + credits > 0)
+            {
+               promptDelivery = true;
+            }
+            
+            availableCredits += credits;
          }
       }
+      finally
+      {
+         lock.unlock();
+      }
+
+      if (promptDelivery)
+      {
+         promptDelivery();
+      }
+
    }
 
    public Queue getQueue()
@@ -365,7 +355,7 @@
 
          if (ref == null)
          {
-            throw new IllegalStateException(System.identityHashCode(this) + " Could not find reference on consumerID=" +
+            throw new IllegalStateException(System.identityHashCode(this) + " Could not find reference on consumer ID=" +
                                             id +
                                             ", messageId = " +
                                             messageID +
@@ -428,49 +418,6 @@
       return ref;
    }
 
-   public void deliverReplicated(final long messageID) throws Exception
-   {
-      MessageReference ref = messageQueue.removeFirstReference(messageID);
-
-      if (ref == null)
-      {
-         // The order is correct, but it hasn't been depaged yet, so we need to force a depage
-         PagingStore store = pagingManager.getPageStore(binding.getAddress());
-
-         // force a depage
-         if (!store.readPage()) // This returns false if there are no pages
-         {
-            throw new IllegalStateException("Cannot find Reference[" + messageID +
-                                            "] in queue " +
-                                            messageQueue.getName());
-         }
-         else
-         {
-            ref = messageQueue.removeFirstReference(messageID);
-
-            if (ref == null)
-            {
-               throw new IllegalStateException("Cannot find Reference[" + messageID +
-                                               "] after depaging on Queue " +
-                                               messageQueue.getName());
-            }
-         }
-      }
-
-      // We call doHandle rather than handle, since we don't want to check available credits
-      // This is because delivery and receive credits can be processed in different order on live
-      // and backup, and otherwise we could have a situation where the delivery is replicated
-      // but the credits haven't arrived yet, so the delivery gets rejected on backup
-      HandleStatus handled = doHandle(ref);
-
-      if (handled != HandleStatus.HANDLED)
-      {
-         throw new IllegalStateException("Reference " + ref +
-                                         " was not handled on backup node, handleStatus = " +
-                                         handled);
-      }
-   }
-
    public void failedOver()
    {
       if (messageQueue.consumerFailedOver())
@@ -482,50 +429,36 @@
       }
    }
 
-   public void lock()
-   {
-      lock.lock();
-   }
-
-   public void unlock()
-   {
-      lock.unlock();
-   }
-
    // Public ---------------------------------------------------------------------------------------
 
    /** To be used on tests only */
-   public AtomicInteger getAvailableCredits()
+   public int getAvailableCredits()
    {
-      return availableCredits;
+      lock.lock();
+      try
+      {
+         return availableCredits;
+      }
+      finally
+      {
+         lock.unlock();
+      }
    }
 
    // Private --------------------------------------------------------------------------------------
 
    private void promptDelivery()
    {
-      if (trace)
+      // largeMessageDeliverer is aways set inside a lock
+      // if we don't acquire a lock, we will have NPE eventually
+      if (largeMessageDeliverer != null)
       {
-         log.trace("Starting prompt delivery");
+         resumeLargeMessage();
       }
-      lock.lock();
-      try
+      else
       {
-         // largeMessageDeliverer is aways set inside a lock
-         // if we don't acquire a lock, we will have NPE eventually
-         if (largeMessageDeliverer != null)
-         {
-            resumeLargeMessage();
-         }
-         else
-         {
-            session.promptDelivery(messageQueue);
-         }
+         session.promptDelivery(messageQueue);
       }
-      finally
-      {
-         lock.unlock();
-      }
    }
 
    /**
@@ -550,19 +483,11 @@
 
    private HandleStatus doHandle(final MessageReference ref) throws Exception
    {
-      if (availableCredits != null && availableCredits.get() <= 0)
-      {
-         return HandleStatus.BUSY;
-      }
-
       lock.lock();
 
       try
       {
-         // If the consumer is stopped then we don't accept the message, it
-         // should go back into the
-         // queue for delivery later.
-         if (!started)
+         if ((flowControl && availableCredits <= 0) || !started)
          {
             return HandleStatus.BUSY;
          }
@@ -571,15 +496,8 @@
 
          // If there is a pendingLargeMessage we can't take another message
          // This has to be checked inside the lock as the set to null is done inside the lock
-         if (pendingLargeMessagesCounter.get() > 0)
+         if (hasPendingLargeMessage)
          {
-            if (messageQueue.isBackup())
-            {
-               log.warn("doHandle: rejecting message while send is pending, ignoring reference = " + ref +
-                        " backup = " +
-                        messageQueue.isBackup());
-            }
-
             return HandleStatus.BUSY;
          }
 
@@ -603,12 +521,9 @@
 
             // If updateDeliveries = false (set by strict-update),
             // the updateDeliveryCount would still be updated after cancel
-            if (updateDeliveries)
+            if (updateDeliveries && ref.getMessage().isDurable() && ref.getQueue().isDurable())
             {
-               if (ref.getMessage().isDurable() && ref.getQueue().isDurable())
-               {
-                  storageManager.updateDeliveryCount(ref);
-               }
+               storageManager.updateDeliveryCount(ref);
             }
 
             if (preAcknowledge)
@@ -644,44 +559,11 @@
 
    private void deliverLargeMessage(final MessageReference ref, final ServerMessage message)
    {
-      pendingLargeMessagesCounter.incrementAndGet();
+      hasPendingLargeMessage = true;
 
-      final LargeMessageDeliverer localDeliverer = new LargeMessageDeliverer((LargeServerMessage)message, ref);
+      largeMessageDeliverer = new LargeMessageDeliverer((LargeServerMessage)message, ref);
 
-      if (replicatingChannel == null)
-      {
-         // it doesn't need lock because deliverLargeMesasge is already inside the lock()
-         largeMessageDeliverer = localDeliverer;
-         largeMessageDeliverer.deliver();
-      }
-      else
-      {
-         Packet replPacket = new SessionReplicateDeliveryMessage(id, message.getMessageID());
-         replPacket.setChannelID(channel.getID());
-
-         replicatingChannel.replicatePacket(replPacket, replicatedSessionID, new Runnable()
-         {
-            public void run()
-            {
-               // setting & unsetting largeMessageDeliver is done inside the lock,
-               // so this needs to be locked
-               lock.lock();
-               try
-               {
-                  largeMessageDeliverer = localDeliverer;
-                  if (largeMessageDeliverer.deliver())
-                  {
-                     promptDelivery();
-                  }
-               }
-               finally
-               {
-                  lock.unlock();
-               }
-            }
-         });
-      }
-
+      largeMessageDeliverer.deliver();
    }
 
    /**
@@ -692,48 +574,18 @@
    {
       final SessionReceiveMessage packet = new SessionReceiveMessage(id, message, ref.getDeliveryCount());
 
-      if (availableCredits != null)
+      if (flowControl)
       {
-         availableCredits.addAndGet(-packet.getRequiredBufferSize());
-         if (trace)
-         {
-            log.trace("Taking " + packet.getRequiredBufferSize() + " out of flow control");
-         }
+         availableCredits -= packet.getRequiredBufferSize();
       }
 
-      if (replicatingChannel == null)
-      {
-         // Not replicated - just send now
-
-         if (trace)
-         {
-            log.trace("delivering Message " + ref + " on backup");
-         }
-         channel.send(packet);
-      }
-      else
-      {
-         Packet replPacket = new SessionReplicateDeliveryMessage(id, message.getMessageID());
-         replPacket.setChannelID(channel.getID());
-
-         replicatingChannel.replicatePacket(replPacket, replicatedSessionID, new Runnable()
-         {
-            public void run()
-            {
-               if (trace)
-               {
-                  log.trace("delivering Message " + ref + " on live");
-               }
-               channel.send(packet);
-            }
-         });
-      }
+      channel.send(packet);
    }
 
    // Inner classes
    // ------------------------------------------------------------------------
 
-   final Runnable resumeLargeMessageRunnable = new Runnable()
+   private final Runnable resumeLargeMessageRunnable = new Runnable()
    {
       public void run()
       {
@@ -792,7 +644,7 @@
                return true;
             }
 
-            if (availableCredits != null && availableCredits.get() <= 0)
+            if (flowControl && availableCredits <= 0)
             {
                return false;
             }
@@ -818,7 +670,7 @@
 
             int precalculateAvailableCredits;
 
-            if (availableCredits != null)
+            if (flowControl)
             {
                // Flow control needs to be done in advance.
                precalculateAvailableCredits = preCalculateFlowControl(initialMessage);
@@ -832,7 +684,7 @@
             {
                channel.send(initialMessage);
 
-               if (availableCredits != null)
+               if (flowControl)
                {
                   precalculateAvailableCredits -= initialMessage.getRequiredBufferSize();
                }
@@ -840,12 +692,8 @@
 
             while (positionPendingLargeMessage < sizePendingLargeMessage)
             {
-               if (precalculateAvailableCredits <= 0 && availableCredits != null)
+               if (flowControl && precalculateAvailableCredits <= 0)
                {
-                  if (trace)
-                  {
-                     trace("deliverLargeMessage: Leaving loop of send LargeMessage because of credits, backup = " + messageQueue.isBackup());
-                  }
                   return false;
                }
 
@@ -853,7 +701,7 @@
 
                int chunkLen = chunk.getBody().length;
 
-               if (availableCredits != null)
+               if (flowControl)
                {
                   if ((precalculateAvailableCredits -= chunk.getRequiredBufferSize()) < 0)
                   {
@@ -861,15 +709,6 @@
                   }
                }
 
-               if (trace)
-               {
-                  trace("deliverLargeMessage: Sending " + chunk.getRequiredBufferSize() +
-                        " availableCredits now is " +
-                        availableCredits +
-                        " isBackup = " +
-                        messageQueue.isBackup());
-               }
-
                channel.send(chunk);
 
                positionPendingLargeMessage += chunkLen;
@@ -880,11 +719,6 @@
                log.warn("Flowcontrol logic is not working properly... creidts = " + precalculateAvailableCredits);
             }
 
-            if (trace)
-            {
-               trace("Finished deliverLargeMessage isBackup = " + messageQueue.isBackup());
-            }
-
             close();
 
             return true;
@@ -933,43 +767,33 @@
 
          largeMessageDeliverer = null;
 
-         pendingLargeMessagesCounter.decrementAndGet();
+         hasPendingLargeMessage = false;
       }
 
       /**
-       * Credits flow control are calculated in advance.
+       * Credits flow control are calculated in advance. - WHY?
        * @return
        */
-      private int preCalculateFlowControl(SessionReceiveMessage firstPacket)
+      private int preCalculateFlowControl(final SessionReceiveMessage firstPacket)
       {
-         while (true)
+         final int currentCredit = availableCredits;
+         int precalculatedCredits = 0;
+
+         if (firstPacket != null)
          {
-            final int currentCredit = availableCredits.get();
-            int precalculatedCredits = 0;
+            precalculatedCredits = firstPacket.getRequiredBufferSize();
+         }
 
-            if (firstPacket != null)
-            {
-               precalculatedCredits = firstPacket.getRequiredBufferSize();
-            }
+         long chunkLen = 0;
+         for (long i = positionPendingLargeMessage; precalculatedCredits < currentCredit && i < sizePendingLargeMessage; i += chunkLen)
+         {
+            chunkLen = (int)Math.min(sizePendingLargeMessage - i, minLargeMessageSize);
+            precalculatedCredits += chunkLen + SessionReceiveContinuationMessage.SESSION_RECEIVE_CONTINUATION_BASE_SIZE;
+         }
 
-            long chunkLen = 0;
-            for (long i = positionPendingLargeMessage; precalculatedCredits < currentCredit && i < sizePendingLargeMessage; i += chunkLen)
-            {
-               chunkLen = (int)Math.min(sizePendingLargeMessage - i, minLargeMessageSize);
-               precalculatedCredits += chunkLen + SessionReceiveContinuationMessage.SESSION_RECEIVE_CONTINUATION_BASE_SIZE;
-            }
+         availableCredits = currentCredit - precalculatedCredits;
 
-            // The calculation of credits and taking credits out has to be taken atomically.
-            // Since we are not sending anything to the client during this calculation, this is unlikely to happen
-            if (availableCredits.compareAndSet(currentCredit, currentCredit - precalculatedCredits))
-            {
-               if (trace)
-               {
-                  log.trace("Taking " + precalculatedCredits + " credits out on preCalculateFlowControl (largeMessage)");
-               }
-               return precalculatedCredits;
-            }
-         }
+         return precalculatedCredits;
       }
 
       private SessionReceiveContinuationMessage createChunkSend()

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -50,7 +50,6 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.MessagingExceptionMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.NullResponseMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
-import org.jboss.messaging.core.remoting.impl.wireformat.PacketsConfirmedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.RollbackMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionAcknowledgeMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionBindingQueryMessage;
@@ -78,7 +77,6 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXASetTimeoutMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXASetTimeoutResponseMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXAStartMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.SessionReplicateDeliveryMessage;
 import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
 import org.jboss.messaging.core.security.CheckType;
 import org.jboss.messaging.core.security.SecurityStore;
@@ -112,23 +110,12 @@
 
    private static final Logger log = Logger.getLogger(ServerSessionImpl.class);
 
-   private static final boolean trace = log.isTraceEnabled();
-
-   private static void trace(String message)
-   {
-      log.trace(message);
-   }
-
    // Static -------------------------------------------------------------------------------
 
    // Attributes ----------------------------------------------------------------------------
 
    private volatile long id;
 
-   // The id of the opposite channel - i.e. if this is the live then its the id on the backup, if this is the backup
-   // then it's the id on the live, or -1 if non clustered
-   private volatile long oppositeChannelID;
-
    private final String username;
 
    private final String password;
@@ -145,7 +132,7 @@
 
    private RemotingConnection remotingConnection;
 
-   private Channel replicatingChannel;
+   // private Channel replicatingChannel;
 
    private final Map<Long, ServerConsumer> consumers = new ConcurrentHashMap<Long, ServerConsumer>();
 
@@ -181,8 +168,6 @@
 
    private final SimpleString nodeID;
 
-   private boolean backup;
-
    // The current currentLargeMessage being processed
    // In case of replication, currentLargeMessage should only be accessed within the replication callbacks
    private volatile LargeServerMessage currentLargeMessage;
@@ -192,7 +177,7 @@
    // Constructors ---------------------------------------------------------------------------------
 
    public ServerSessionImpl(final String name,
-                            final long oppositeChannelID,
+   // final long oppositeChannelID,
                             final String username,
                             final String password,
                             final int minLargeMessageSize,
@@ -211,13 +196,14 @@
                             final ManagementService managementService,
                             final QueueFactory queueFactory,
                             final MessagingServer server,
-                            final SimpleString managementAddress,
-                            final Channel replicatingChannel,
-                            final boolean backup) throws Exception
+                            final SimpleString managementAddress
+   // final Channel replicatingChannel,
+   // final boolean backup
+   ) throws Exception
    {
       this.id = channel.getID();
 
-      this.oppositeChannelID = oppositeChannelID;
+      // this.oppositeChannelID = oppositeChannelID;
 
       this.username = username;
 
@@ -264,10 +250,10 @@
 
       this.nodeID = server.getNodeID();
 
-      this.replicatingChannel = replicatingChannel;
+      // this.replicatingChannel = replicatingChannel;
 
-      this.backup = backup;
-      
+      // this.backup = backup;
+
       remotingConnection.addFailureListener(this);
 
       remotingConnection.addCloseListener(this);
@@ -363,505 +349,22 @@
       queue.deliverAsync(executor);
    }
 
-   public void handleCreateConsumer(final SessionCreateConsumerMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleCreateConsumer(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleCreateConsumer(packet);
-            }
-         });
-      }
-   }
-
-   public void handleCreateQueue(final CreateQueueMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleCreateQueue(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleCreateQueue(packet);
-            }
-         });
-      }
-   }
-
-   public void handleDeleteQueue(final SessionDeleteQueueMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleDeleteQueue(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleDeleteQueue(packet);
-            }
-         });
-      }
-   }
-
-   public void handleExecuteQueueQuery(final SessionQueueQueryMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleExecuteQueueQuery(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleExecuteQueueQuery(packet);
-            }
-         });
-      }
-   }
-
-   public void handleExecuteBindingQuery(final SessionBindingQueryMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleExecuteBindingQuery(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleExecuteBindingQuery(packet);
-            }
-         });
-      }
-   }
-
-   public void handleAcknowledge(final SessionAcknowledgeMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleAcknowledge(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleAcknowledge(packet);
-            }
-         });
-      }
-   }
-
-   public void handleExpired(final SessionExpiredMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleExpired(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleExpired(packet);
-            }
-         });
-      }
-   }
-
-   public void handleCommit(final Packet packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleCommit(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleCommit(packet);
-            }
-         });
-      }
-   }
-
-   public void handleRollback(final RollbackMessage packet)
-   {
-
-      if (replicatingChannel == null)
-      {
-         doHandleRollback(packet);
-      }
-      else
-      {
-         final HashSet<Queue> queues = lockUsedQueues(null);
-
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               try
-               {
-                  doHandleRollback(packet);
-               }
-               finally
-               {
-                  for (Queue queue : queues)
-                  {
-                     queue.unlockDelivery();
-                  }
-               }
-            }
-         });
-      }
-   }
-
-   public void handleXACommit(final SessionXACommitMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXACommit(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXACommit(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXAEnd(final SessionXAEndMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXAEnd(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXAEnd(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXAForget(final SessionXAForgetMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXAForget(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXAForget(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXAJoin(final SessionXAJoinMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXAJoin(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXAJoin(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXAResume(final SessionXAResumeMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXAResume(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXAResume(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXARollback(final SessionXARollbackMessage packet)
-   {
-
-      if (replicatingChannel == null)
-      {
-         doHandleXARollback(packet);
-      }
-      else
-      {
-         final Set<Queue> queues = lockUsedQueues(packet.getXid());
-
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               try
-               {
-                  doHandleXARollback(packet);
-               }
-               finally
-               {
-                  for (Queue queue : queues)
-                  {
-                     queue.unlockDelivery();
-                  }
-               }
-            }
-         });
-      }
-   }
-
-   public void handleXAStart(final SessionXAStartMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXAStart(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXAStart(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXASuspend(final Packet packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXASuspend(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXASuspend(packet);
-            }
-         });
-      }
-   }
-
-   public void handleXAPrepare(final SessionXAPrepareMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleXAPrepare(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleXAPrepare(packet);
-            }
-         });
-      }
-   }
-
-   public void handleGetInDoubtXids(final Packet packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleGetInDoubtXids(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleGetInDoubtXids(packet);
-            }
-         });
-      }
-   }
-
-   public void handleGetXATimeout(final Packet packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleGetXATimeout(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleGetXATimeout(packet);
-            }
-         });
-      }
-   }
-
-   public void handleSetXATimeout(final SessionXASetTimeoutMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doHandleSetXATimeout(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doHandleSetXATimeout(packet);
-            }
-         });
-      }
-   }
-
-   private void lockConsumers()
-   {
-      for (ServerConsumer consumer : consumers.values())
-      {
-         consumer.lock();
-      }
-   }
-
-   private void unlockConsumers()
-   {
-      for (ServerConsumer consumer : consumers.values())
-      {
-         consumer.unlock();
-      }
-   }
-
    public void handleStart(final Packet packet)
    {
-      if (replicatingChannel == null)
-      {
-         setStarted(true);
+      setStarted(true);
 
-         channel.confirm(packet);
-      }
-      else
-      {
-         lockConsumers();
-
-         try
-         {
-            setStarted(true);
-
-            replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-            {
-               public void run()
-               {
-                  // setStarted(true);
-
-                  channel.confirm(packet);
-               }
-            });
-         }
-         finally
-         {
-            unlockConsumers();
-         }
-      }
+      channel.confirm(packet);
    }
 
    public void handleStop(final Packet packet)
    {
       final Packet response = new NullResponseMessage();
 
-      // We need to stop the session *before* replicating, to avoid this situation:
-      // session stop,
-      // stop is replicated
-      // delivery occurs, local is not stopped yet
-      // stop is processed on backup
-      // backup is stopped
-      // delivery is processed on backup
-      // it's stopped so barfs and cannot process delivery
+      setStarted(false);
 
-      if (replicatingChannel == null)
-      {
-         setStarted(false);
+      channel.confirm(packet);
 
-         channel.confirm(packet);
-
-         channel.send(response);
-      }
-      else
-      {
-         lockConsumers();
-
-         try
-         {
-
-            setStarted(false);
-
-            replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-            {
-               public void run()
-               {
-                  channel.confirm(packet);
-
-                  channel.send(response);
-
-               }
-            });
-         }
-         finally
-         {
-            unlockConsumers();
-         }
-      }
+      channel.send(response);
    }
 
    public void handleFailedOver(final Packet packet)
@@ -874,112 +377,9 @@
       }
    }
 
-   public void handleClose(final Packet packet)
-   {
-
-      if (replicatingChannel == null)
-      {
-         doHandleClose(packet);
-      }
-      else
-      {
-         final HashSet<Queue> queues = lockUsedQueues(null);
-
-         // We need to stop the consumers first before replicating, to ensure no deliveries occur after this,
-         // but we need to process the actual close() when the replication response returns, otherwise things
-         // can happen like acks can come in after close
-
-         for (ServerConsumer consumer : consumers.values())
-         {
-            consumer.setStarted(false);
-         }
-
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               try
-               {
-                  doHandleClose(packet);
-               }
-               finally
-               {
-                  for (Queue queue : queues)
-                  {
-                     queue.unlockDelivery();
-                  }
-               }
-            }
-         });
-      }
-   }
-
-   public void handleCloseConsumer(final SessionConsumerCloseMessage packet)
-   {
-      final ServerConsumer consumer = consumers.get(packet.getConsumerID());
-
-      consumer.setStarted(false);
-
-      if (replicatingChannel == null)
-      {
-         doHandleCloseConsumer(packet, consumer);
-      }
-      else
-      {
-         final Queue queue;
-
-         if (consumer.getCountOfPendingDeliveries() > 0)
-         {
-            queue = consumer.getQueue();
-            queue.lockDelivery();
-         }
-         else
-         {
-            queue = null;
-         }
-
-         // We need to stop the consumer first before replicating, to ensure no deliveries occur after this,
-         // but we need to process the actual close() when the replication response returns, otherwise things
-         // can happen like acks can come in after close
-
-         consumer.setStarted(false);
-
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               try
-               {
-                  doHandleCloseConsumer(packet, consumer);
-               }
-               finally
-               {
-                  if (queue != null)
-                  {
-                     queue.unlockDelivery();
-                  }
-               }
-            }
-         });
-      }
-   }
-
    public void handleReceiveConsumerCredits(final SessionConsumerFlowCreditMessage packet)
    {
-      if (replicatingChannel == null)
-      {
-         doReceiveCredits(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doReceiveCredits(packet);
-            }
-         });
-      }
+      doReceiveCredits(packet);
    }
 
    public void handleSendLargeMessage(final SessionSendLargeMessage packet)
@@ -996,236 +396,24 @@
       // With a send we must make sure it is replicated to backup before being processed on live
       // or can end up with delivery being processed on backup before original send
 
-      if (replicatingChannel == null)
+      if (currentLargeMessage != null)
       {
-         if (currentLargeMessage != null)
-         {
-            log.warn("Replacing incomplete LargeMessage with ID=" + currentLargeMessage.getMessageID());
-         }
-
-         currentLargeMessage = msg;
-
-         doSendLargeMessage(packet);
+         log.warn("Replacing incomplete LargeMessage with ID=" + currentLargeMessage.getMessageID());
       }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               if (trace)
-               {
-                  trace("(Replication) SendLargeMessage, id=" + msg.getMessageID());
-               }
 
-               if (currentLargeMessage != null)
-               {
-                  log.warn("Replacing incomplete LargeMessage with ID=" + currentLargeMessage.getMessageID());
-               }
+      currentLargeMessage = msg;
 
-               currentLargeMessage = msg;
-
-               doSendLargeMessage(packet);
-            }
-         });
-      }
+      doSendLargeMessage(packet);
    }
 
-   public void handleSend(final SessionSendMessage packet)
+   public void handleCloseConsumer(final SessionConsumerCloseMessage packet)
    {
-      if (replicatingChannel == null)
-      {
-         doSend(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doSend(packet);
-            }
-         });
-      }
-   }
-
-   public void handleSendContinuations(final SessionSendContinuationMessage packet)
-   {
-      if (replicatingChannel == null)
-      {
-         doSendContinuations(packet);
-      }
-      else
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, new Runnable()
-         {
-            public void run()
-            {
-               doSendContinuations(packet);
-            }
-         });
-      }
-   }
-
-   public void handleReplicatedDelivery(final SessionReplicateDeliveryMessage packet)
-   {
-      ServerConsumer consumer = consumers.get(packet.getConsumerID());
-
-      if (consumer == null)
-      {
-         throw new IllegalStateException("Cannot handle replicated delivery, consumer is closed " + packet.getConsumerID() +
-                                         " session " +
-                                         id +
-                                         " " +
-                                         System.identityHashCode(this));
-      }
-
-      try
-      {
-         consumer.deliverReplicated(packet.getMessageID());
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to handle replicated delivery", e);
-      }
-   }
-
-   public void handlePacketsConfirmed(final PacketsConfirmedMessage packet)
-   {
-      if (replicatingChannel != null)
-      {
-         replicatingChannel.replicatePacket(packet, oppositeChannelID, null);
-      }
-   }
-
-   public int transferConnection(final RemotingConnection newConnection, final int lastReceivedCommandID)
-   {
-      boolean wasStarted = this.started;
-
-      if (wasStarted)
-      {
-         this.setStarted(false);
-      }
-
-      if (backup)
-      {
-         // Put the id back to the original client session id
-         this.id = this.oppositeChannelID;
-
-         this.oppositeChannelID = -1;
-
-         backup = false;
-      }
-
-      remotingConnection.removeFailureListener(this);
-      remotingConnection.removeCloseListener(this);
-
-      // Note. We do not destroy the replicating connection here. In the case the live server has really crashed
-      // then the connection will get cleaned up anyway when the server ping timeout kicks in.
-      // In the case the live server is really still up, i.e. a split brain situation (or in tests), then closing
-      // the replicating connection will cause the outstanding responses to be be replayed on the live server,
-      // if these reach the client who then subsequently fails over, on reconnection to backup, it will have
-      // received responses that the backup did not know about.
-
-      channel.transferConnection(newConnection, this.id, replicatingChannel);
-
-      newConnection.syncIDGeneratorSequence(remotingConnection.getIDGeneratorSequence());
-
-      remotingConnection = newConnection;
-
-      remotingConnection.addFailureListener(this);
-      remotingConnection.addCloseListener(this);
-
-      int serverLastReceivedCommandID = channel.getLastReceivedCommandID();
-
-      channel.replayCommands(lastReceivedCommandID, this.id);
-
-      if (wasStarted)
-      {
-         this.setStarted(true);
-      }
-
-      return serverLastReceivedCommandID;
-   }
-
-   public Channel getChannel()
-   {
-      return channel;
-   }
-
-   // FailureListener implementation
-   // --------------------------------------------------------------------
-
-   public boolean connectionFailed(final MessagingException me)
-   {
-      try
-      {
-         log.warn("Client connection failed, clearing up resources for session " + name);
-
-         for (Runnable runner : failureRunners)
-         {
-            try
-            {
-               runner.run();
-            }
-            catch (Throwable t)
-            {
-               log.error("Failed to execute failure runner", t);
-            }
-         }
-
-         handleClose(new PacketImpl(PacketImpl.SESS_CLOSE));
-
-         log.warn("Cleared up resources for session " + name);
-      }
-      catch (Throwable t)
-      {
-         log.error("Failed to close connection " + this);
-      }
-
-      return true;
-   }
-
-   public void connectionClosed()
-   {
-      try
-      {
-         for (Runnable runner : failureRunners)
-         {
-            try
-            {
-               runner.run();
-            }
-            catch (Throwable t)
-            {
-               log.error("Failed to execute failure runner", t);
-            }
-         }
-      }
-      catch (Throwable t)
-      {
-         log.error("Failed fire listeners " + this);
-      }
-
-   }
-
-   // Public
-   // ----------------------------------------------------------------------------
-
-   public Transaction getTransaction()
-   {
-      return tx;
-   }
-
-   // Private
-   // ----------------------------------------------------------------------------
-
-   private void doHandleCloseConsumer(final SessionConsumerCloseMessage packet, final ServerConsumer consumer)
-   {
       Packet response;
 
       try
       {
+         final ServerConsumer consumer = consumers.get(packet.getConsumerID());
+
          consumer.close();
 
          response = new NullResponseMessage();
@@ -1249,7 +437,7 @@
       channel.send(response);
    }
 
-   private void doHandleCreateConsumer(final SessionCreateConsumerMessage packet)
+   public void handleCreateConsumer(final SessionCreateConsumerMessage packet)
    {
       SimpleString name = packet.getQueueName();
 
@@ -1263,6 +451,8 @@
       {
          Binding binding = postOffice.getBinding(name);
 
+         log.info("binding is " + binding);
+
          if (binding == null || binding.getType() != BindingType.LOCAL_QUEUE)
          {
             throw new MessagingException(MessagingException.QUEUE_DOES_NOT_EXIST, "Binding " + name + " does not exist");
@@ -1284,7 +474,12 @@
             // We consume a copy of the queue - TODO - this is a temporary measure
             // and will disappear once we can provide a proper iterator on the queue
 
-            theQueue = queueFactory.createQueue(-1, binding.getAddress(), name, filter, false, true);
+            theQueue = queueFactory.createQueue(storageManager.generateUniqueID(),
+                                                binding.getAddress(),
+                                                name,
+                                                filter,
+                                                false,
+                                                true);
 
             // There's no need for any special locking since the list method is synchronized
             List<MessageReference> refs = ((Queue)binding.getBindable()).list(filter);
@@ -1301,8 +496,9 @@
             theQueue = (Queue)binding.getBindable();
          }
 
+         log.info("*********** creating consumer");
+
          ServerConsumer consumer = new ServerConsumerImpl(idGenerator.generateID(),
-                                                          oppositeChannelID,
                                                           this,
                                                           (QueueBinding)binding,
                                                           filter,
@@ -1311,7 +507,6 @@
                                                           storageManager,
                                                           postOffice.getPagingManager(),
                                                           channel,
-                                                          replicatingChannel,
                                                           preAcknowledge,
                                                           updateDeliveries,
                                                           executor,
@@ -1362,11 +557,11 @@
       channel.confirm(packet);
 
       channel.send(response);
-
    }
 
-   private void doHandleCreateQueue(final CreateQueueMessage packet)
+   public void handleCreateQueue(final CreateQueueMessage packet)
    {
+      log.info("processing create queue");
       SimpleString address = packet.getAddress();
 
       final SimpleString name = packet.getQueueName();
@@ -1406,7 +601,7 @@
                public void run()
                {
                   try
-                  {                     
+                  {
                      if (postOffice.getBinding(name) != null)
                      {
                         postOffice.removeBinding(name);
@@ -1424,6 +619,8 @@
       }
       catch (Exception e)
       {
+         log.error("Failed to process action", e);
+
          if (e instanceof MessagingException)
          {
             response = new MessagingExceptionMessage((MessagingException)e);
@@ -1437,9 +634,11 @@
       channel.confirm(packet);
 
       channel.send(response);
+
+      log.info("processed create queue");
    }
 
-   private void doHandleDeleteQueue(final SessionDeleteQueueMessage packet)
+   public void handleDeleteQueue(final SessionDeleteQueueMessage packet)
    {
       SimpleString name = packet.getQueueName();
 
@@ -1477,7 +676,7 @@
       channel.send(response);
    }
 
-   private void doHandleExecuteQueueQuery(final SessionQueueQueryMessage packet)
+   public void handleExecuteQueueQuery(final SessionQueueQueryMessage packet)
    {
       SimpleString name = packet.getQueueName();
 
@@ -1530,7 +729,7 @@
       channel.send(response);
    }
 
-   private void doHandleExecuteBindingQuery(final SessionBindingQueryMessage packet)
+   public void handleExecuteBindingQuery(final SessionBindingQueryMessage packet)
    {
       SimpleString address = packet.getAddress();
 
@@ -1576,7 +775,7 @@
       channel.send(response);
    }
 
-   private void doHandleAcknowledge(final SessionAcknowledgeMessage packet)
+   public void handleAcknowledge(final SessionAcknowledgeMessage packet)
    {
       Packet response = null;
 
@@ -1616,7 +815,7 @@
       }
    }
 
-   private void doHandleExpired(final SessionExpiredMessage packet)
+   public void handleExpired(final SessionExpiredMessage packet)
    {
       try
       {
@@ -1636,7 +835,7 @@
       channel.confirm(packet);
    }
 
-   private void doHandleCommit(final Packet packet)
+   public void handleCommit(final Packet packet)
    {
       Packet response = null;
 
@@ -1669,7 +868,7 @@
       channel.send(response);
    }
 
-   private void doHandleRollback(final RollbackMessage packet)
+   public void handleRollback(final RollbackMessage packet)
    {
       Packet response = null;
 
@@ -1698,7 +897,7 @@
       channel.send(response);
    }
 
-   private void doHandleXACommit(final SessionXACommitMessage packet)
+   public void handleXACommit(final SessionXACommitMessage packet)
    {
       Packet response = null;
 
@@ -1761,7 +960,7 @@
       channel.send(response);
    }
 
-   private void doHandleXAEnd(final SessionXAEndMessage packet)
+   public void handleXAEnd(final SessionXAEndMessage packet)
    {
       Packet response = null;
 
@@ -1835,7 +1034,7 @@
       channel.send(response);
    }
 
-   private void doHandleXAForget(final SessionXAForgetMessage packet)
+   public void handleXAForget(final SessionXAForgetMessage packet)
    {
       // Do nothing since we don't support heuristic commits / rollback from the
       // resource manager
@@ -1847,7 +1046,7 @@
       channel.send(response);
    }
 
-   private void doHandleXAJoin(final SessionXAJoinMessage packet)
+   public void handleXAJoin(final SessionXAJoinMessage packet)
    {
       Packet response = null;
 
@@ -1898,7 +1097,7 @@
       channel.send(response);
    }
 
-   private void doHandleXAResume(final SessionXAResumeMessage packet)
+   public void handleXAResume(final SessionXAResumeMessage packet)
    {
       Packet response = null;
 
@@ -1960,7 +1159,7 @@
       channel.send(response);
    }
 
-   private void doHandleXARollback(final SessionXARollbackMessage packet)
+   public void handleXARollback(final SessionXARollbackMessage packet)
    {
       Packet response = null;
 
@@ -2023,7 +1222,7 @@
       channel.send(response);
    }
 
-   private void doHandleXAStart(final SessionXAStartMessage packet)
+   public void handleXAStart(final SessionXAStartMessage packet)
    {
       Packet response = null;
 
@@ -2074,7 +1273,7 @@
       channel.send(response);
    }
 
-   private void doHandleXASuspend(final Packet packet)
+   public void handleXASuspend(final Packet packet)
    {
       Packet response = null;
 
@@ -2123,7 +1322,7 @@
       channel.send(response);
    }
 
-   private void doHandleXAPrepare(final SessionXAPrepareMessage packet)
+   public void handleXAPrepare(final SessionXAPrepareMessage packet)
    {
       Packet response = null;
 
@@ -2183,7 +1382,7 @@
       channel.send(response);
    }
 
-   private void doHandleGetInDoubtXids(final Packet packet)
+   public void handleGetInDoubtXids(final Packet packet)
    {
       Packet response = new SessionXAGetInDoubtXidsResponseMessage(resourceManager.getPreparedTransactions());
 
@@ -2192,7 +1391,7 @@
       channel.send(response);
    }
 
-   private void doHandleGetXATimeout(final Packet packet)
+   public void handleGetXATimeout(final Packet packet)
    {
       Packet response = new SessionXAGetTimeoutResponseMessage(resourceManager.getTimeoutSeconds());
 
@@ -2201,7 +1400,7 @@
       channel.send(response);
    }
 
-   private void doHandleSetXATimeout(final SessionXASetTimeoutMessage packet)
+   public void handleSetXATimeout(final SessionXASetTimeoutMessage packet)
    {
       Packet response = new SessionXASetTimeoutResponseMessage(resourceManager.setTimeoutSeconds(packet.getTimeoutSeconds()));
 
@@ -2210,113 +1409,12 @@
       channel.send(response);
    }
 
-   private void doHandleClose(final Packet packet)
+   public void handleSend(final SessionSendMessage packet)
    {
       Packet response = null;
 
       try
       {
-         close();
-
-         response = new NullResponseMessage();
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to close", e);
-
-         if (e instanceof MessagingException)
-         {
-            response = new MessagingExceptionMessage((MessagingException)e);
-         }
-         else
-         {
-            response = new MessagingExceptionMessage(new MessagingException(MessagingException.INTERNAL_ERROR));
-         }
-      }
-
-      channel.confirm(packet);
-
-      // We flush the confirmations to make sure any send confirmations get handled on the client side
-      channel.flushConfirmations();
-
-      channel.send(response);
-
-      channel.close();
-   }
-
-   private void setStarted(final boolean s)
-   {
-      Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values());
-
-      for (ServerConsumer consumer : consumersClone)
-      {
-         consumer.setStarted(s);
-      }
-
-      started = s;
-   }
-
-   /**
-    * We need to create the LargeMessage before replicating the packet, or else we won't know how to extract the destination,
-    * which is stored on the header
-    * @param packet
-    * @throws Exception
-    */
-   private LargeServerMessage doCreateLargeMessage(final SessionSendLargeMessage packet)
-   {
-      try
-      {
-         return createLargeMessageStorage(packet.getLargeMessageHeader());
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to create large message", e);
-         Packet response = null;
-
-         channel.confirm(packet);
-         if (response != null)
-         {
-            channel.send(response);
-         }
-         return null;
-      }
-   }
-
-   private void doReceiveCredits(final SessionConsumerFlowCreditMessage packet)
-   {
-      try
-      {
-         consumers.get(packet.getConsumerID()).receiveCredits(packet.getCredits());
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to receive credits", e);
-      }
-      channel.confirm(packet);
-   }
-
-   private void doSendLargeMessage(final SessionSendLargeMessage packet)
-   {
-      try
-      {
-         long id = storageManager.generateUniqueID();
-
-         currentLargeMessage.setMessageID(id);
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to send message", e);
-      }
-
-      channel.confirm(packet);
-   }
-
-   private void doSend(final SessionSendMessage packet)
-   {
-      Packet response = null;
-
-      try
-      {
          ServerMessage message = packet.getServerMessage();
 
          long id = storageManager.generateUniqueID();
@@ -2367,7 +1465,7 @@
    /**
     * @param packet
     */
-   private void doSendContinuations(final SessionSendContinuationMessage packet)
+   public void handleSendContinuations(final SessionSendContinuationMessage packet)
    {
       Packet response = null;
 
@@ -2421,6 +1519,234 @@
       }
    }
 
+   public void handleClose(final Packet packet)
+   {
+      Packet response = null;
+
+      try
+      {
+         close();
+
+         response = new NullResponseMessage();
+      }
+      catch (Exception e)
+      {
+         log.error("Failed to close", e);
+
+         if (e instanceof MessagingException)
+         {
+            response = new MessagingExceptionMessage((MessagingException)e);
+         }
+         else
+         {
+            response = new MessagingExceptionMessage(new MessagingException(MessagingException.INTERNAL_ERROR));
+         }
+      }
+
+      channel.confirm(packet);
+
+      // We flush the confirmations to make sure any send confirmations get handled on the client side
+      channel.flushConfirmations();
+
+      channel.send(response);
+
+      channel.close();
+   }
+
+   public int transferConnection(final RemotingConnection newConnection, final int lastReceivedCommandID)
+   {
+      boolean wasStarted = this.started;
+
+      if (wasStarted)
+      {
+         this.setStarted(false);
+      }
+
+      // backup = false;
+
+      remotingConnection.removeFailureListener(this);
+      remotingConnection.removeCloseListener(this);
+
+      // Note. We do not destroy the replicating connection here. In the case the live server has really crashed
+      // then the connection will get cleaned up anyway when the server ping timeout kicks in.
+      // In the case the live server is really still up, i.e. a split brain situation (or in tests), then closing
+      // the replicating connection will cause the outstanding responses to be be replayed on the live server,
+      // if these reach the client who then subsequently fails over, on reconnection to backup, it will have
+      // received responses that the backup did not know about.
+
+      channel.transferConnection(newConnection);
+
+      newConnection.syncIDGeneratorSequence(remotingConnection.getIDGeneratorSequence());
+
+      remotingConnection = newConnection;
+
+      remotingConnection.addFailureListener(this);
+      remotingConnection.addCloseListener(this);
+
+      int serverLastReceivedCommandID = channel.getLastReceivedCommandID();
+
+      channel.replayCommands(lastReceivedCommandID);
+
+      if (wasStarted)
+      {
+         this.setStarted(true);
+      }
+
+      return serverLastReceivedCommandID;
+   }
+
+   public Channel getChannel()
+   {
+      return channel;
+   }
+
+   // FailureListener implementation
+   // --------------------------------------------------------------------
+
+   public boolean connectionFailed(final MessagingException me)
+   {
+      try
+      {
+         log.warn("Client connection failed, clearing up resources for session " + name);
+
+         for (Runnable runner : failureRunners)
+         {
+            try
+            {
+               runner.run();
+            }
+            catch (Throwable t)
+            {
+               log.error("Failed to execute failure runner", t);
+            }
+         }
+
+         handleClose(new PacketImpl(PacketImpl.SESS_CLOSE));
+
+         log.warn("Cleared up resources for session " + name);
+      }
+      catch (Throwable t)
+      {
+         log.error("Failed to close connection " + this);
+      }
+
+      return true;
+   }
+
+   public void connectionClosed()
+   {
+      try
+      {
+         for (Runnable runner : failureRunners)
+         {
+            try
+            {
+               runner.run();
+            }
+            catch (Throwable t)
+            {
+               log.error("Failed to execute failure runner", t);
+            }
+         }
+      }
+      catch (Throwable t)
+      {
+         log.error("Failed fire listeners " + this);
+      }
+
+   }
+
+   // Public
+   // ----------------------------------------------------------------------------
+
+   public Transaction getTransaction()
+   {
+      return tx;
+   }
+
+   // Private
+   // ----------------------------------------------------------------------------
+
+   private void setStarted(final boolean s)
+   {
+      Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values());
+
+      for (ServerConsumer consumer : consumersClone)
+      {
+         consumer.setStarted(s);
+      }
+
+      started = s;
+   }
+
+   /**
+    * We need to create the LargeMessage before replicating the packet, or else we won't know how to extract the destination,
+    * which is stored on the header
+    * @param packet
+    * @throws Exception
+    */
+   private LargeServerMessage doCreateLargeMessage(final SessionSendLargeMessage packet)
+   {
+      try
+      {
+         LargeServerMessage largeMessage = storageManager.createLargeMessage();
+
+         MessagingBuffer headerBuffer = ChannelBuffers.wrappedBuffer(packet.getLargeMessageHeader());
+
+         largeMessage.decodeProperties(headerBuffer);
+
+         return largeMessage;
+      }
+      catch (Exception e)
+      {
+         Packet response = null;
+
+         channel.confirm(packet);
+
+         if (response != null)
+         {
+            channel.send(response);
+         }
+
+         return null;
+      }
+   }
+
+   private void doReceiveCredits(final SessionConsumerFlowCreditMessage packet)
+   {
+      try
+      {
+         log.info("packet consumer id is "+ packet.getConsumerID());
+         
+         ServerConsumer consumer = consumers.get(packet.getConsumerID());
+         
+         log.info("consumer is " + consumer);
+         
+         consumer.receiveCredits(packet.getCredits());
+      }
+      catch (Exception e)
+      {
+         log.error("Failed to receive credits", e);
+      }
+      channel.confirm(packet);
+   }
+
+   private void doSendLargeMessage(final SessionSendLargeMessage packet)
+   {
+      try
+      {
+         long id = storageManager.generateUniqueID();
+
+         currentLargeMessage.setMessageID(id);
+      }
+      catch (Exception e)
+      {
+         log.error("Failed to send message", e);
+      }
+
+      channel.confirm(packet);
+   }
+
    private void handleManagementMessage(final ServerMessage message) throws Exception
    {
       try
@@ -2448,17 +1774,6 @@
       }
    }
 
-   private LargeServerMessage createLargeMessageStorage(final byte[] header) throws Exception
-   {
-      LargeServerMessage largeMessage = storageManager.createLargeMessage();
-
-      MessagingBuffer headerBuffer = ChannelBuffers.wrappedBuffer(header);
-
-      largeMessage.decodeProperties(headerBuffer);
-
-      return largeMessage;
-   }
-
    private void doRollback(final boolean lastMessageAsDelived, final Transaction theTx) throws Exception
    {
       boolean wasStarted = started;
@@ -2530,39 +1845,4 @@
          postOffice.route(msg, tx);
       }
    }
-
-   /**
-    * We need to avoid delivery when rolling back while doing replication, or the backup node could be on a different order
-    * @return
-    */
-   private HashSet<Queue> lockUsedQueues(Xid xid)
-   {
-      final HashSet<Queue> queues = new HashSet<Queue>();
-
-      for (ServerConsumer consumer : consumers.values())
-      {
-         queues.add(consumer.getQueue());
-      }
-
-      Transaction localTX;
-      if (xid == null)
-      {
-         localTX = tx;
-      }
-      else
-      {
-         localTX = resourceManager.getTransaction(xid);
-      }
-
-      if (localTX != null)
-      {
-         queues.addAll(localTX.getDistinctQueues());
-      }
-
-      for (Queue queue : queues)
-      {
-         queue.lockDelivery();
-      }
-      return queues;
-   }
 }

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -14,6 +14,7 @@
 
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.CREATE_QUEUE;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.DELETE_QUEUE;
+import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.REPLICATE_LOCK_SEQUENCES;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_ACKNOWLEDGE;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_BINDINGQUERY;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_CLOSE;
@@ -24,7 +25,6 @@
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_FAILOVER_COMPLETE;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_FLOWTOKEN;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_QUEUEQUERY;
-import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_REPLICATE_DELIVERY;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_ROLLBACK;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_SEND;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_SEND_CONTINUATION;
@@ -44,12 +44,15 @@
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_XA_START;
 import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_XA_SUSPEND;
 
+import java.util.List;
+
+import org.jboss.messaging.core.config.Configuration;
 import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.core.remoting.Channel;
 import org.jboss.messaging.core.remoting.ChannelHandler;
 import org.jboss.messaging.core.remoting.Packet;
 import org.jboss.messaging.core.remoting.impl.wireformat.CreateQueueMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl;
-import org.jboss.messaging.core.remoting.impl.wireformat.PacketsConfirmedMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.RollbackMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionAcknowledgeMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionBindingQueryMessage;
@@ -71,8 +74,13 @@
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXARollbackMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXASetTimeoutMessage;
 import org.jboss.messaging.core.remoting.impl.wireformat.SessionXAStartMessage;
-import org.jboss.messaging.core.remoting.impl.wireformat.replication.SessionReplicateDeliveryMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateLockSequenceMessage;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicationResponseMessage;
 import org.jboss.messaging.core.server.ServerSession;
+import org.jboss.messaging.core.server.replication.ReplicableAction;
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.core.server.replication.impl.JBMThread;
+import org.jboss.messaging.utils.Pair;
 
 /**
  * A ServerSessionPacketHandler
@@ -81,33 +89,112 @@
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @author <a href="mailto:andy.taylor at jboss.org>Andy Taylor</a>
  */
-public class ServerSessionPacketHandler implements ChannelHandler
+public class ServerSessionPacketHandler implements ChannelHandler, ReplicableAction
 {
    private static final Logger log = Logger.getLogger(ServerSessionPacketHandler.class);
 
    private final ServerSession session;
-
-   public ServerSessionPacketHandler(final ServerSession session)
+   
+   private final Replicator replicator;
+   
+   private Packet packet;
+   
+   //private boolean backup;
+   
+   private Configuration config;
+   
+   private List<Pair<Long, Integer>> sequences;
+   
+   private final Channel channel;
+   
+   public ServerSessionPacketHandler(final ServerSession session, final Replicator replicator, final Configuration config)
    {
       this.session = session;
+      
+      this.replicator = replicator;
+      
+      this.channel = session.getChannel();
+      
+      this.config = config;
    }
 
    public long getID()
    {
       return session.getID();
    }
-
+     
+   public void run()
+   {
+      handlePacket();
+   }
+   
+   public Packet getPacket()
+   {      
+      return packet;
+   }
+   
    public void handlePacket(final Packet packet)
    {
+      this.packet = packet;
+      
+      log.info(System.identityHashCode(this)+ " Handling packet " + packet.getType() + " on backup " + config.isBackup());
+      
+      if (config.isBackup())
+      {         
+         JBMThread thread = JBMThread.currentThread();
+         
+         thread.setReplay(sequences);
+         
+        // thread.setReplay(true);
+         
+         handlePacket();  
+         
+         //send the response message
+         
+         if (packet.getType() != PacketImpl.REPLICATE_LOCK_SEQUENCES)
+         {
+            channel.send(new ReplicationResponseMessage());
+         }                
+      }
+      else
+      {         
+         if (replicator != null)
+         {
+            replicator.execute(this);
+         }
+         else
+         {
+            log.info("replicator is null");
+            handlePacket();
+         }
+      }
+   }
+   
+   private void dumpSequences(List<Pair<Long, Integer>> sequences)
+   {
+      log.info("Sequences size is " + sequences.size());
+      for (Pair<Long, Integer> pair: sequences)
+      {
+         log.info(pair.a + ": " + pair.b);
+      }
+   }
+
+   private void handlePacket()
+   {
       byte type = packet.getType();
 
       try
       {
          switch (type)
          {
-            case PacketImpl.PACKETS_CONFIRMED:
+            case REPLICATE_LOCK_SEQUENCES:
             {
-               session.handlePacketsConfirmed((PacketsConfirmedMessage)packet);
+               ReplicateLockSequenceMessage msg = (ReplicateLockSequenceMessage)packet;
+               sequences = msg.getSequences();
+               
+               log.info("Session, set sequences");
+               dumpSequences(sequences);
+               
                break;
             }
             case SESS_CREATECONSUMER:
@@ -118,6 +205,7 @@
             }
             case CREATE_QUEUE:
             {               
+               log.info("Got create queue message");
                CreateQueueMessage request = (CreateQueueMessage)packet;               
                session.handleCreateQueue(request);             
                break;
@@ -281,12 +369,6 @@
                session.handleSendContinuations(message);
                break;               
             }
-            case SESS_REPLICATE_DELIVERY:
-            {
-               SessionReplicateDeliveryMessage message = (SessionReplicateDeliveryMessage)packet;
-               session.handleReplicatedDelivery(message);
-               break;               
-            }
          }
       }
       catch (Throwable t)

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/ReplicableAction.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/ReplicableAction.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/ReplicableAction.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.messaging.core.server.replication;
+
+import org.jboss.messaging.core.remoting.Packet;
+
+/**
+ * A ReplicableAction
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public interface ReplicableAction extends Runnable
+{
+   Packet getPacket();
+}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/Replicator.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/Replicator.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/Replicator.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package org.jboss.messaging.core.server.replication;
+
+import org.jboss.messaging.core.remoting.Channel;
+
+
+/**
+ * A Replicator
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public interface Replicator
+{
+   void execute(ReplicableAction action);
+   
+   void registerWaitingChannel(Channel channel);
+   
+   boolean isResponseReceived();
+   
+   void replicationResponseReceived();
+}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/JBMThread.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/JBMThread.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/JBMThread.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,134 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.core.server.replication.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.utils.Pair;
+
+/**
+ * A JBMThread
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class JBMThread extends Thread
+{
+   private static enum ThreadState
+   {
+      RECORD, REPLAY, END_RECORD;
+   }
+   
+   private ThreadState state;
+
+   private List<Pair<Long, Integer>> objectSequences;
+
+   private int pos;
+   
+   private Replicator replicator;     
+   
+   public static JBMThread currentThread()
+   {
+      return (JBMThread)Thread.currentThread();
+   }
+   
+   public JBMThread(final ThreadGroup threadGroup, final String name)
+   {
+      super(threadGroup, name);
+   }
+   
+   public JBMThread(final ThreadGroup threadGroup, final Runnable target, final String name)
+   {
+      super(threadGroup, target, name);
+   }
+
+   public boolean isReplay()
+   {
+      return state == ThreadState.REPLAY;
+   }
+   
+   public boolean isRecording()
+   {
+      return state == ThreadState.RECORD;
+   }
+   
+   public void setReplay(final List<Pair<Long, Integer>> objectSequences)
+   {
+      this.objectSequences = objectSequences;
+      
+      this.state = ThreadState.REPLAY;
+      
+      this.pos = 0;
+   }
+   
+   public void setRecord(final Replicator replicator)
+   {
+      if (this.objectSequences == null)
+      {
+         this.objectSequences = new ArrayList<Pair<Long, Integer>>();
+      }
+      else
+      {
+         this.objectSequences.clear();
+      }
+      
+      this.state = ThreadState.RECORD;
+      
+      this.pos = 0;
+      
+      this.replicator = replicator;
+   }
+   
+   public void endRecord()
+   {
+      this.state = ThreadState.END_RECORD;
+   }
+
+   public Pair<Long, Integer> getNextSequence()
+   {
+      return objectSequences.get(pos++);
+   }
+
+   public void addSequence(final Pair<Long, Integer> currentSequence)
+   {
+      objectSequences.add(currentSequence);
+   }
+   
+   public List<Pair<Long, Integer>> getSequences()
+   {
+      return objectSequences;
+   }
+   
+   public Replicator getReplicator()
+   {
+      return replicator;
+   }
+   
+   public void setReplicator(final Replicator replicator)
+   {
+      this.replicator = replicator;
+   }
+}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/PriorityLock.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/PriorityLock.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/PriorityLock.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,138 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.core.server.replication.impl;
+
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.concurrent.locks.LockSupport;
+
+import org.jboss.messaging.core.logging.Logger;
+
+/**
+ * A PriorityLock
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class PriorityLock
+{
+   private static final Logger log = Logger.getLogger(PriorityLock.class);
+
+   private final Queue<QueueEntry> waiting;
+
+   private volatile int currentSequence;
+
+   private Thread owner;
+   
+   public PriorityLock(final int sequence)
+   {
+      waiting = new PriorityQueue<QueueEntry>();
+      
+      this.currentSequence = sequence;
+   }
+
+   public void lock(final int sequence)
+   {
+      //log.info(this + " trying to get lock on backup " + sequence);
+      
+      Thread currentThread = Thread.currentThread();
+
+      if (sequence != currentSequence)
+      {
+         QueueEntry entry = new QueueEntry(sequence, currentThread);
+
+         synchronized (waiting)
+         {
+            waiting.add(entry);
+         }
+
+         while (sequence != currentSequence)
+         {            
+            log.info("parking lock, expected " + sequence + " current " + currentSequence);
+            LockSupport.park();
+         }
+      }
+
+      owner = currentThread;
+      
+      //log.info(this + " got lock om backup " + sequence, new Exception());
+   }
+
+   public void unlock()
+   {
+      if (owner != Thread.currentThread())
+      {
+         throw new IllegalMonitorStateException();
+      }
+
+      currentSequence++;
+
+      QueueEntry entry;
+
+      synchronized (waiting)
+      {
+         entry = waiting.peek();
+         
+         if (entry != null && entry.thread == owner)
+         {
+            waiting.poll();
+         }
+         
+         entry = waiting.peek();
+         
+         log.info("size " + waiting.size());
+      }
+
+      if (entry != null)
+      {
+         LockSupport.unpark(entry.thread);
+      }
+   }
+
+   private static final class QueueEntry implements Comparable<QueueEntry>
+   {
+      private final int sequence;
+
+      private final Thread thread;
+
+      private QueueEntry(final int sequence, final Thread thread)
+      {
+         this.sequence = sequence;
+
+         if (thread == null)
+         {
+            throw new NullPointerException("Null thread");
+         }
+
+         this.thread = thread;
+      }
+
+      public int compareTo(final QueueEntry entry)
+      {
+         int i = entry.sequence;
+
+         return sequence < i ? -1 : (sequence == i ? 0 : 1);
+      }
+   }
+}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/ReplicatorImpl.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/ReplicatorImpl.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/ReplicatorImpl.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.core.server.replication.impl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.core.remoting.Channel;
+import org.jboss.messaging.core.remoting.Packet;
+import org.jboss.messaging.core.remoting.impl.wireformat.replication.ReplicateLockSequenceMessage;
+import org.jboss.messaging.core.server.replication.ReplicableAction;
+import org.jboss.messaging.core.server.replication.Replicator;
+import org.jboss.messaging.utils.Pair;
+
+/**
+ * A ReplicatorImpl
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class ReplicatorImpl implements Replicator
+{
+   private static final Logger log = Logger.getLogger(ReplicatorImpl.class);
+
+   private Channel replicatingChannel;
+
+   private Set<Channel> waitingChannels = new HashSet<Channel>();
+
+   private boolean responseReceived;
+
+   public ReplicatorImpl(final Channel replicatingChannel)
+   {
+      this.replicatingChannel = replicatingChannel;
+   }
+
+   public void registerWaitingChannel(final Channel channel)
+   {
+      this.waitingChannels.add(channel);
+   }
+
+   public synchronized void replicationResponseReceived()
+   {
+      log.info("** got replication response in replicator");
+      
+      for (Channel channel : waitingChannels)
+      {
+         channel.replicationResponseReceived(this);
+      }
+
+      responseReceived = true;
+   }
+
+   public synchronized boolean isResponseReceived()
+   {
+      return responseReceived;
+   }
+
+   public void execute(final ReplicableAction action)
+   {
+      // First we execute the action
+      
+      log.info("Running action locally");
+      
+      JBMThread thread = JBMThread.currentThread();
+      
+      //List<Pair<Long, Integer>> sequences = new ArrayList<Pair<Long, Integer>>(); 
+      
+      thread.setRecord(this);
+
+      action.run();
+      
+      thread.endRecord();
+      
+      log.info("Ran action locally");
+      
+      List<Pair<Long, Integer>> sequences = JBMThread.currentThread().getSequences();
+      
+      dumpSequences(sequences);
+
+      // We then send the sequences to the backup
+
+      log.info("Replicated sequences");
+      
+      Packet packet = new ReplicateLockSequenceMessage(sequences);
+
+      replicatingChannel.send(packet);
+
+      // Next we replicate the actual action
+           
+      replicatingChannel.send(action.getPacket());
+      
+      log.info("replicated packet " + action.getPacket().getType());
+   }
+   
+   private void dumpSequences(List<Pair<Long, Integer>> sequences)
+   {
+      log.info("Sequences size is " + sequences.size());
+      for (Pair<Long, Integer> pair: sequences)
+      {
+         log.info(pair.a + ": " + pair.b);
+      }
+   }
+   
+}

Added: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/StatefulObjectReadWriteLock.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/StatefulObjectReadWriteLock.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/core/server/replication/impl/StatefulObjectReadWriteLock.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,243 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.core.server.replication.impl;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.utils.ConcurrentHashSet;
+import org.jboss.messaging.utils.Pair;
+
+/**
+ * A StatefulObjectReadWriteLock
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class StatefulObjectReadWriteLock implements ReadWriteLock
+{
+   private static final Logger log = Logger.getLogger(StatefulObjectReadWriteLock.class);
+
+   private final Lock readLock = new StatefulObjectReadLock();
+
+   private final Lock writeLock = new StatefulObjectWriteLock();
+   
+   private long objectID;
+   
+   private final ReadWriteLock rwLock;
+   
+   private final AtomicInteger counter;
+   
+   private final PriorityLock sequencedLock;
+   
+   private String name;
+
+   public StatefulObjectReadWriteLock(final String name, final long objectID, final int initialCount)
+   {
+      this.name = name;
+      
+      this.objectID = objectID;
+      
+      rwLock = new ReentrantReadWriteLock();
+      
+      sequencedLock = new PriorityLock(initialCount);
+      
+      counter = new AtomicInteger(initialCount);
+   }
+
+   public Lock readLock()
+   {
+      return readLock;
+   }
+
+   public Lock writeLock()
+   {
+      return writeLock;
+   }
+   
+   //For debug
+   private Set<Thread> owners = new ConcurrentHashSet<Thread>();
+   
+   private boolean doLock(long time, TimeUnit unit, boolean read) throws InterruptedException
+   {
+      JBMThread thread = JBMThread.currentThread();
+      
+      //debug only
+      if (owners.contains(thread))
+      {
+         throw new IllegalStateException("Stateful lock is NOT re-entrant!");
+      }
+      
+      if (thread.isReplay())
+      {
+         Pair<Long, Integer> sequence = thread.getNextSequence();
+         
+         log.info(name + " Attempting to get lock on backup " + sequence.b, new Exception());
+         
+         if (sequence.a != objectID)
+         {
+            throw new IllegalStateException("Invalid object id " + sequence.a + " expected " + objectID);
+         }
+         
+         sequencedLock.lock(sequence.b);
+         
+         owners.add(thread);
+         
+         return true;
+      }
+      else
+      {
+         boolean ok;
+         
+         if (read)
+         {
+            ok = rwLock.readLock().tryLock(time, unit);
+         }
+         else
+         {
+            ok = rwLock.writeLock().tryLock(time, unit);
+         }
+                  
+         if (ok)
+         {
+            log.info(name + " added sequence on live " + counter.get(), new Exception());
+            
+            thread.addSequence(new Pair<Long, Integer>(objectID, counter.getAndIncrement()));
+            
+            owners.add(thread);
+         }
+         
+         return ok;
+      }
+   }
+   
+   private void doUnlock(final boolean read)
+   {
+      JBMThread thread = JBMThread.currentThread();
+      
+      if (thread.isReplay())
+      {
+         sequencedLock.unlock();
+      }
+      else
+      {         
+         if (read)
+         {
+            rwLock.readLock().unlock();
+         }
+         else
+         {
+            rwLock.writeLock().unlock();
+         }
+      }  
+      
+      owners.remove(thread);
+   }
+
+   private class StatefulObjectReadLock implements Lock
+   {
+      public void lock()
+      {
+         //throw new UnsupportedOperationException();
+         try
+         {
+            doLock(10000, TimeUnit.MILLISECONDS, true);
+         }
+         catch (InterruptedException e)
+         {
+         }
+      }
+
+      public void lockInterruptibly() throws InterruptedException
+      {
+         throw new UnsupportedOperationException();
+      }
+
+      public Condition newCondition()
+      {
+         throw new UnsupportedOperationException();
+      }
+
+      public boolean tryLock()
+      {
+         throw new UnsupportedOperationException();
+      }
+
+      public boolean tryLock(long time, TimeUnit unit) throws InterruptedException
+      {
+         return doLock(time, unit, true);
+      }
+
+      public void unlock()
+      {
+         doUnlock(true);
+      }
+   }
+   
+   private class StatefulObjectWriteLock implements Lock
+   {
+      public void lock()
+      {
+         //throw new UnsupportedOperationException();
+         try
+         {
+            doLock(10000, TimeUnit.MILLISECONDS, false);
+         }
+         catch (InterruptedException e)
+         {
+         }
+      }
+
+      public void lockInterruptibly() throws InterruptedException
+      {
+         throw new UnsupportedOperationException();
+      }
+
+      public Condition newCondition()
+      {
+         throw new UnsupportedOperationException();
+      }
+
+      public boolean tryLock()
+      {
+         throw new UnsupportedOperationException();
+      }
+
+      public boolean tryLock(long time, TimeUnit unit) throws InterruptedException
+      {
+         return doLock(time, unit, false);
+      }
+
+      public void unlock()
+      {
+         doUnlock(false);
+      }
+   }
+}

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/integration/logging/JBMLoggerFormatter.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/integration/logging/JBMLoggerFormatter.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/integration/logging/JBMLoggerFormatter.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -41,11 +41,12 @@
       StringBuffer sb = new StringBuffer();
       // Minimize memory allocations here.
       date.setTime(record.getMillis());
+      sb.append("[").append(Thread.currentThread().getName()).append("] ");
       sb.append(dateFormat.format(date)).append(" ");
       sb.append(record.getLevel()). append(" [");
       sb.append(record.getLoggerName()).append("]").append("  ");
       sb.append(record.getMessage());
-      sb.append(" ");
+      
       sb.append(lineSeparator);
       if (record.getThrown() != null)
       {

Modified: branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/utils/JBMThreadFactory.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/utils/JBMThreadFactory.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/src/main/org/jboss/messaging/utils/JBMThreadFactory.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -33,13 +33,13 @@
  */
 public class JBMThreadFactory implements ThreadFactory
 {
-   private final ThreadGroup group;
+   protected final ThreadGroup group;
 
-   private final AtomicInteger threadCount = new AtomicInteger(0);
+   protected final AtomicInteger threadCount = new AtomicInteger(0);
 
-   private final int threadPriority;
+   protected final int threadPriority;
    
-   private final boolean daemon;
+   protected final boolean daemon;
    
    public JBMThreadFactory(final String groupName, final boolean daemon)
    {

Modified: branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/integration/cluster/failover/SimpleAutomaticFailoverTest.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/integration/cluster/failover/SimpleAutomaticFailoverTest.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/integration/cluster/failover/SimpleAutomaticFailoverTest.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -89,13 +89,21 @@
 
       sf.setProducerWindowSize(32 * 1024);
 
+      log.info("creating session");
+      
       ClientSession session = sf.createSession(false, true, true);
+      
+      log.info("created session");
 
       session.createQueue(ADDRESS, ADDRESS, null, false);
+      
+      log.info("created queue");
 
       ClientProducer producer = session.createProducer(ADDRESS);
+      
+      log.info("created producer");
 
-      final int numMessages = 100;
+      final int numMessages = 1;
 
       for (int i = 0; i < numMessages; i++)
       {
@@ -108,10 +116,16 @@
          message.getBody().writeString("aardvarks");
          producer.send(message);
       }
+      
+     // Thread.sleep(30000);
 
       ClientConsumer consumer = session.createConsumer(ADDRESS);
+      
+      log.info("created consumer");
 
       session.start();
+      
+      log.info("started session");
 
       for (int i = 0; i < numMessages; i++)
       {
@@ -122,6 +136,8 @@
 
          message2.acknowledge();
       }
+      
+      log.info("consumed messages");
 
       ClientMessage message3 = consumer.receive(250);
 

Modified: branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/postoffice/impl/BindingImplTest.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/postoffice/impl/BindingImplTest.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/postoffice/impl/BindingImplTest.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -1299,7 +1299,7 @@
       /* (non-Javadoc)
        * @see org.jboss.messaging.core.server.Queue#getPersistenceID()
        */
-      public long getPersistenceID()
+      public long getID()
       {
 
          return 0;

Modified: branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/impl/QueueImplTest.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/impl/QueueImplTest.java	2009-06-26 05:09:10 UTC (rev 7477)
+++ branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/impl/QueueImplTest.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -66,13 +66,13 @@
 
       Queue queue = new QueueImpl(id, address1, queue1, null, false, true, scheduledExecutor, null, null, null);
 
-      assertEquals(id, queue.getPersistenceID());
+      assertEquals(id, queue.getID());
 
       final long id2 = 456;
 
       queue.setPersistenceID(id2);
 
-      assertEquals(id2, queue.getPersistenceID());
+      assertEquals(id2, queue.getID());
    }
 
    public void testName()

Added: branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/replication/impl/NewSequencedLockTest.java
===================================================================
--- branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/replication/impl/NewSequencedLockTest.java	                        (rev 0)
+++ branches/Branch_MultiThreaded_Replication/tests/src/org/jboss/messaging/tests/unit/core/server/replication/impl/NewSequencedLockTest.java	2009-06-26 09:46:34 UTC (rev 7478)
@@ -0,0 +1,215 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005-2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.messaging.tests.unit.core.server.replication.impl;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.TestCase;
+
+import org.jboss.messaging.core.logging.Logger;
+import org.jboss.messaging.core.server.replication.impl.PriorityLock;
+
+/**
+ * A NewSequencedLockTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ *
+ */
+public class NewSequencedLockTest extends TestCase
+{
+   private static final Logger log = Logger.getLogger(NewSequencedLockTest.class);
+
+   public void testAscending() throws Exception
+   {
+      for (int i = 0; i < 1000; i++)
+      {
+         log.info("iter " + i);
+         this.doTestSequences(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+      }
+   }
+
+   public void testDescending() throws Exception
+   {
+      for (int i = 0; i < 1000; i++)
+      {
+         log.info("iter " + i);
+         this.doTestSequences(9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
+      }
+   }
+
+   public void testAlternate() throws Exception
+   {
+      for (int i = 0; i < 1000; i++)
+      {
+         log.info("iter " + i);
+         this.doTestSequences(9, 0, 8, 1, 7, 2, 6, 3, 5, 4);
+      }
+   }
+
+   public void testRandom() throws Exception
+   {
+      for (int i = 0; i < 1000; i++)
+      {
+         log.info("iter " + i);
+         this.doTestSequences(3, 9, 5, 7, 1, 2, 0, 8, 6, 4);
+      }
+   }
+
+   public void testSpeed() throws Exception
+   {
+      PriorityLock lock = new PriorityLock();
+
+      AtomicInteger counter = new AtomicInteger(0);
+      
+      final int numThreads = 10;
+      
+      final int acquires = 10000000;
+      
+      MyThread2[] threads = new MyThread2[numThreads];
+      
+      for (int i = 0; i < numThreads; i++)
+      {
+         threads[i] = new MyThread2(lock, acquires, counter);
+      }
+      
+      long start = System.currentTimeMillis();
+
+      for (int i = 0; i < numThreads; i++)
+      {
+         threads[i].start();
+      }
+
+      for (int i = 0; i < numThreads; i++)
+      {
+         threads[i].join();
+      }
+
+      long end = System.currentTimeMillis();
+      
+      double rate = 1000 * ((double)acquires * numThreads) / (end - start);
+
+      System.out.println("Rate " + rate);
+     
+   }
+
+   class MyThread2 extends Thread
+   {
+      private int acquireCount;
+      
+      private final AtomicInteger counter;
+      
+      private final PriorityLock lock;
+
+      MyThread2(final PriorityLock lock, final int acquires, final AtomicInteger counter)
+      {
+         this.lock= lock;
+         
+         this.acquireCount = acquires;
+         
+         this.counter = counter;
+      }
+      
+      public void run()
+      {
+         for (int i = 0; i < acquireCount; i++)
+         {
+            lock.lock(counter.getAndIncrement());
+            
+            lock.unlock();
+         }
+      }
+   }
+
+   private void doTestSequences(final int... sequences) throws Exception
+   {
+      PriorityLock lock = new PriorityLock();
+
+      AtomicInteger counter = new AtomicInteger(0);
+
+      MyThread[] threads = new MyThread[sequences.length];
+
+      for (int i = 0; i < sequences.length; i++)
+      {
+         threads[i] = new MyThread(sequences[i], counter, lock);
+      }
+
+      for (int i = 0; i < sequences.length; i++)
+      {
+         threads[i].start();
+      }
+
+      for (int i = 0; i < sequences.length; i++)
+      {
+         threads[i].join();
+      }
+
+      for (int i = 0; i < sequences.length; i++)
+      {
+         assertEquals(sequences[i], threads[i].getObtainedSeq());
+      }
+   }
+
+   class MyThread extends Thread
+   {
+      private AtomicInteger counter;
+
+      private PriorityLock lock;
+
+      private final int seq;
+
+      private volatile int obtainedSeq;
+
+      MyThread(final int seq, final AtomicInteger counter, final PriorityLock lock)
+      {
+         this.seq = seq;
+
+         this.counter = counter;
+
+         this.lock = lock;
+      }
+
+      public void run()
+      {
+         // log.info(System.identityHashCode(this) + " Will attempt to obtain lock with sequence " + seq);
+
+         lock.lock(seq);
+
+         // log.info(System.identityHashCode(this) + " Obtained lock with sequence " + seq);
+
+         try
+         {
+            obtainedSeq = counter.getAndIncrement();
+         }
+         finally
+         {
+            lock.unlock();
+         }
+      }
+
+      public int getObtainedSeq()
+      {
+         return this.obtainedSeq;
+      }
+   }
+}




More information about the jboss-cvs-commits mailing list