[jboss-cvs] JBoss Messaging SVN: r2857 - in trunk: src/etc/xmdesc and 24 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Jul 8 09:21:41 EDT 2007


Author: timfox
Date: 2007-07-08 09:21:39 -0400 (Sun, 08 Jul 2007)
New Revision: 2857

Added:
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/AckAllReplicatedDeliveriesMessage.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/AddAllReplicatedDeliveriesMessage.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateAckMessage.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryAckMessage.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryMessage.java
   trunk/src/main/org/jboss/messaging/util/GUIDGenerator.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/ChangeFailoverNodeTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/RecoverDeliveriesTest.java
Removed:
   trunk/src/main/org/jboss/messaging/core/contract/FailoverMapper.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/DefaultFailoverMapper.java
Modified:
   trunk/src/etc/server/default/deploy/messaging-service.xml
   trunk/src/etc/server/default/deploy/mysql-persistence-service.xml
   trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
   trunk/src/main/org/jboss/jms/client/JBossConnectionConsumer.java
   trunk/src/main/org/jboss/jms/client/JBossSession.java
   trunk/src/main/org/jboss/jms/client/container/ClientConsumer.java
   trunk/src/main/org/jboss/jms/client/container/ConnectionAspect.java
   trunk/src/main/org/jboss/jms/client/container/ConsumerAspect.java
   trunk/src/main/org/jboss/jms/client/container/DelegateIdentity.java
   trunk/src/main/org/jboss/jms/client/container/JMSClientVMIdentifier.java
   trunk/src/main/org/jboss/jms/client/container/SessionAspect.java
   trunk/src/main/org/jboss/jms/client/container/StateCreationAspect.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientBrowserDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientClusteredConnectionFactoryDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionFactoryDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientConsumerDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientProducerDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/ClientSessionDelegate.java
   trunk/src/main/org/jboss/jms/client/delegate/DelegateSupport.java
   trunk/src/main/org/jboss/jms/client/remoting/CallbackManager.java
   trunk/src/main/org/jboss/jms/client/remoting/JMSRemotingConnection.java
   trunk/src/main/org/jboss/jms/client/state/ConsumerState.java
   trunk/src/main/org/jboss/jms/client/state/SessionState.java
   trunk/src/main/org/jboss/jms/delegate/DeliveryInfo.java
   trunk/src/main/org/jboss/jms/delegate/SessionDelegate.java
   trunk/src/main/org/jboss/jms/destination/JBossTemporaryQueue.java
   trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java
   trunk/src/main/org/jboss/jms/message/JBossMessage.java
   trunk/src/main/org/jboss/jms/server/ServerPeer.java
   trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java
   trunk/src/main/org/jboss/jms/server/destination/QueueService.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
   trunk/src/main/org/jboss/jms/tx/ClientTransaction.java
   trunk/src/main/org/jboss/jms/tx/LocalTx.java
   trunk/src/main/org/jboss/jms/tx/ResourceManager.java
   trunk/src/main/org/jboss/jms/wireformat/BrowserHasNextMessageRequest.java
   trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageBlockRequest.java
   trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageRequest.java
   trunk/src/main/org/jboss/jms/wireformat/BrowserResetRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ClientDelivery.java
   trunk/src/main/org/jboss/jms/wireformat/CloseRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ClosingRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionCreateSessionDelegateRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryCreateConnectionDelegateRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryGetClientAOPStackRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionGetClientIDRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionGetIDBlockRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionGetPreparedTransactionsRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionSendTransactionRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionSetClientIDRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionStartRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConnectionStopRequest.java
   trunk/src/main/org/jboss/jms/wireformat/ConsumerChangeRateRequest.java
   trunk/src/main/org/jboss/jms/wireformat/Dispatcher.java
   trunk/src/main/org/jboss/jms/wireformat/RequestSupport.java
   trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveriesRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveryRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionAddTemporaryDestinationRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveriesRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveryRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionCreateBrowserDelegateRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionCreateConsumerDelegateRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionCreateQueueRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionCreateTopicRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionDeleteTemporaryDestinationRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionRecoverDeliveriesRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionSendRequest.java
   trunk/src/main/org/jboss/jms/wireformat/SessionUnsubscribeRequest.java
   trunk/src/main/org/jboss/messaging/core/contract/MessageReference.java
   trunk/src/main/org/jboss/messaging/core/contract/PostOffice.java
   trunk/src/main/org/jboss/messaging/core/contract/Queue.java
   trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java
   trunk/src/main/org/jboss/messaging/core/impl/MessagingQueue.java
   trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/ClusterRequest.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/MappingInfo.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/RequestTarget.java
   trunk/src/main/org/jboss/messaging/core/jmx/MessagingPostOfficeService.java
   trunk/src/main/org/jboss/messaging/util/ConcurrentHashSet.java
   trunk/src/main/org/jboss/messaging/util/ExceptionUtil.java
   trunk/tests/src/org/jboss/test/messaging/core/PostOfficeTestBase.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/WireFormatTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteredConnectionFactoryTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteringTestBase.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/FailoverTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/LargeClusterTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/MultipleFailoverTest.java
Log:
JBMESSAGING-883


Modified: trunk/src/etc/server/default/deploy/messaging-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/messaging-service.xml	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/etc/server/default/deploy/messaging-service.xml	2007-07-08 13:21:39 UTC (rev 2857)
@@ -89,6 +89,10 @@
             by a particular consumer from a particular producer? -->
             
       <attribute name="DefaultPreserveOrdering">false</attribute>
+      
+      <!-- Max. time to hold previously delivered messages back waiting for clients to reconnect after failover -->
+      
+      <attribute name="RecoverDeliveriesTimeout">300000</attribute>
 
       <depends optional-attribute-name="PersistenceManager">jboss.messaging:service=PersistenceManager</depends>
       

Modified: trunk/src/etc/server/default/deploy/mysql-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/mysql-persistence-service.xml	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/etc/server/default/deploy/mysql-persistence-service.xml	2007-07-08 13:21:39 UTC (rev 2857)
@@ -1,210 +1,210 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-     MySql persistence deployment descriptor.
-
-     Tested with MySQL 4.1.22
-
-     $Id$
- -->
-
-<server>
-
-   <!-- Persistence Manager MBean configuration
-       ======================================= -->
-   
-   <mbean code="org.jboss.messaging.core.jmx.JDBCPersistenceManagerService"
-      name="jboss.messaging:service=PersistenceManager"
-      xmbean-dd="xmdesc/JDBCPersistenceManager-xmbean.xml">
-      
-      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
-      
-      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
-      
-      <!-- The datasource to use for the persistence manager -->
-                    
-      <attribute name="DataSource">java:/DefaultDS</attribute>      
-      
-      <!-- If true will attempt to create tables and indexes on every start-up -->
-                  
-      <attribute name="CreateTablesOnStartup">true</attribute>
-      
-      <!-- If true then will use JDBC batch updates -->
-                  
-      <attribute name="UsingBatchUpdates">true</attribute>
-      
-      <attribute name="SqlProperties"><![CDATA[
-   CREATE_MESSAGE_REFERENCE=CREATE TABLE JBM_MSG_REF (CHANNEL_ID BIGINT, MESSAGE_ID BIGINT, TRANSACTION_ID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, DELIVERY_COUNT INTEGER, SCHED_DELIVERY BIGINT, PRIMARY KEY(CHANNEL_ID, MESSAGE_ID))
-   CREATE_IDX_MESSAGE_REF_TX=CREATE INDEX JBM_MSG_REF_TX ON JBM_MSG_REF (TRANSACTION_ID)
-   CREATE_IDX_MESSAGE_REF_ORD=CREATE INDEX JBM_MSG_REF_ORD ON JBM_MSG_REF (ORD)
-   CREATE_IDX_MESSAGE_REF_PAGE_ORD=CREATE INDEX JBM_MSG_REF_PAGE_ORD ON JBM_MSG_REF (PAGE_ORD)
-   CREATE_IDX_MESSAGE_REF_MESSAGE_ID=CREATE INDEX JBM_MSG_REF_MESSAGE_ID ON JBM_MSG_REF (MESSAGE_ID)
-   CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY=CREATE INDEX JBM_MSG_REF_SCHED_DELIVERY ON JBM_MSG_REF (SCHED_DELIVERY)
-   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, CHANNEL_COUNT INTEGER, TYPE TINYINT, PRIMARY KEY (MESSAGE_ID))
-   CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER, TRANSACTION_ID BIGINT, BRANCH_QUAL VARBINARY(254), FORMAT_ID INTEGER, GLOBAL_TXID VARBINARY(254), PRIMARY KEY (TRANSACTION_ID))
-   CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME))
-   INSERT_MESSAGE_REF=INSERT INTO JBM_MSG_REF (CHANNEL_ID, MESSAGE_ID, TRANSACTION_ID, STATE, ORD, PAGE_ORD, DELIVERY_COUNT, SCHED_DELIVERY) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
-   DELETE_MESSAGE_REF=DELETE FROM JBM_MSG_REF WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'
-   UPDATE_MESSAGE_REF=UPDATE JBM_MSG_REF SET TRANSACTION_ID=?, STATE='-' WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'
-   UPDATE_PAGE_ORDER=UPDATE JBM_MSG_REF SET PAGE_ORD = ? WHERE MESSAGE_ID=? AND CHANNEL_ID=?
-   COMMIT_MESSAGE_REF1=UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='+'
-   COMMIT_MESSAGE_REF2=DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='-'
-   ROLLBACK_MESSAGE_REF1=DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='+'
-   ROLLBACK_MESSAGE_REF2=UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='-'
-   LOAD_PAGED_REFS=SELECT MESSAGE_ID, DELIVERY_COUNT, PAGE_ORD, SCHED_DELIVERY FROM JBM_MSG_REF WHERE CHANNEL_ID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD
-   LOAD_UNPAGED_REFS=SELECT MESSAGE_ID, DELIVERY_COUNT, SCHED_DELIVERY FROM JBM_MSG_REF WHERE STATE = 'C' AND CHANNEL_ID = ? AND PAGE_ORD IS NULL ORDER BY ORD
-   LOAD_REFS=SELECT MESSAGE_ID, DELIVERY_COUNT, SCHED_DELIVERY FROM JBM_MSG_REF WHERE STATE = 'C' AND CHANNEL_ID = ? ORDER BY ORD     
-   UPDATE_REFS_NOT_PAGED=UPDATE JBM_MSG_REF SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNEL_ID=?
-   SELECT_MIN_MAX_PAGE_ORD=SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JBM_MSG_REF WHERE CHANNEL_ID = ?
-   SELECT_EXISTS_REF_MESSAGE_ID=SELECT MESSAGE_ID FROM JBM_MSG_REF WHERE MESSAGE_ID = ?
-   UPDATE_DELIVERY_COUNT=UPDATE JBM_MSG_REF SET DELIVERY_COUNT = ? WHERE CHANNEL_ID = ? AND MESSAGE_ID = ?
-   UPDATE_CHANNEL_ID=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ?
-   LOAD_MESSAGES=SELECT MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, HEADERS, PAYLOAD, TYPE FROM JBM_MSG
-   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, HEADERS, PAYLOAD, CHANNEL_COUNT, TYPE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INC_CHANNEL_COUNT=UPDATE JBM_MSG SET CHANNEL_COUNT = CHANNEL_COUNT + 1 WHERE MESSAGE_ID=?
-   DEC_CHANNEL_COUNT=UPDATE JBM_MSG SET CHANNEL_COUNT = CHANNEL_COUNT - 1 WHERE MESSAGE_ID=?
-   DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID=? AND CHANNEL_COUNT=0
-   MESSAGE_ID_COLUMN=MESSAGE_ID
-   MESSAGE_EXISTS=SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ? FOR UPDATE
-   INSERT_TRANSACTION=INSERT INTO JBM_TX (NODE_ID, TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID) VALUES(?, ?, ?, ?, ?)
-   DELETE_TRANSACTION=DELETE FROM JBM_TX WHERE NODE_ID = ? AND TRANSACTION_ID = ?
-   SELECT_PREPARED_TRANSACTIONS=SELECT TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID FROM JBM_TX WHERE NODE_ID = ?
-   SELECT_MESSAGE_ID_FOR_REF=SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '+' ORDER BY ORD
-   SELECT_MESSAGE_ID_FOR_ACK=SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '-' ORDER BY ORD
-   UPDATE_COUNTER=UPDATE JBM_COUNTER SET NEXT_ID = ? WHERE NAME=?
-   SELECT_COUNTER=SELECT NEXT_ID FROM JBM_COUNTER WHERE NAME=? FOR UPDATE
-   INSERT_COUNTER=INSERT INTO JBM_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
-   SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNEL_ID) FROM JBM_MSG_REF
-   UPDATE_TX=UPDATE JBM_TX SET NODE_ID=? WHERE NODE_ID=?
-      ]]></attribute>
-      
-      <!-- The maximum number of parameters to include in a prepared statement -->
-                  
-      <attribute name="MaxParams">500</attribute>
-   </mbean>
-
-   <!-- Messaging Post Office MBean configuration
-        ========================================= -->
-   
-   <mbean code="org.jboss.messaging.core.jmx.MessagingPostOfficeService"
-      name="jboss.messaging:service=PostOffice"
-      xmbean-dd="xmdesc/MessagingPostOffice-xmbean.xml">
-      
-      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
-                
-      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
-      
-      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
-      
-      <!-- The name of the post office -->                  
-      
-      <attribute name="PostOfficeName">JMS post office</attribute>
-      
-      <!-- The datasource used by the post office to access it's binding information -->                     
-      
-      <attribute name="DataSource">java:/DefaultDS</attribute>
-      
-      <!-- If true will attempt to create tables and indexes on every start-up -->
-                        
-      <attribute name="CreateTablesOnStartup">true</attribute>
-      
-      <attribute name="SqlProperties"><![CDATA[
-CREATE_POSTOFFICE_TABLE=CREATE TABLE JBM_POSTOFFICE (POSTOFFICE_NAME VARCHAR(255), NODE_ID INTEGER, QUEUE_NAME VARCHAR(255), COND VARCHAR(1023), SELECTOR VARCHAR(1023), CHANNEL_ID BIGINT, CLUSTERED CHAR(1), ALL_NODES CHAR(1), PRIMARY KEY(POSTOFFICE_NAME, NODE_ID, QUEUE_NAME))
-INSERT_BINDING=INSERT INTO JBM_POSTOFFICE (POSTOFFICE_NAME, NODE_ID, QUEUE_NAME, COND, SELECTOR, CHANNEL_ID, CLUSTERED, ALL_NODES) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
-DELETE_BINDING=DELETE FROM JBM_POSTOFFICE WHERE POSTOFFICE_NAME=? AND NODE_ID=? AND QUEUE_NAME=?
-LOAD_BINDINGS=SELECT QUEUE_NAME, COND, SELECTOR, CHANNEL_ID, CLUSTERED, ALL_NODES FROM JBM_POSTOFFICE WHERE POSTOFFICE_NAME=? AND NODE_ID=?
-      ]]></attribute>
-       
-      <!-- This post office is clustered. If you don't want a clustered post office then set to false -->
-      
-      <attribute name="Clustered">true</attribute>
-      
-      <!-- All the remaining properties only have to be specified if the post office is clustered.
-           You can safely comment them out if your post office is non clustered -->
-      
-      <!-- The JGroups group name that the post office will use -->            
-      
-      <attribute name="GroupName">MessagingPostOffice</attribute>
-      
-      <!-- Max time to wait for state to arrive when the post office joins the cluster -->            
-                  
-      <attribute name="StateTimeout">5000</attribute>
-      
-      <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->            
-                  
-      <attribute name="CastTimeout">50000</attribute>
-      
-      <!-- Enable this when the JGroups multiplexer comes of age
-      <attribute name="ChannelFactoryName">jgroups.mux:name=Multiplexer</attribute>      
-      <attribute name="ControlChannelName">udp-sync</attribute>
-      <attribute name="DataChannelName">udp</attribute>
-      <attribute name="ChannelPartitionName">${jboss.partition.name:DefaultPartition}-JMS</attribute>
-      -->
-      
-      <!-- JGroups stack configuration for the data channel - used when casting messages across the cluster -->               
-      
-      <attribute name="DataChannelConfig">
-         <config>
-            <UDP mcast_recv_buf_size="500000" down_thread="false" ip_mcast="true" mcast_send_buf_size="32000"
-           mcast_port="45567" ucast_recv_buf_size="500000" use_incoming_packet_handler="false"
-           mcast_addr="228.8.8.8" use_outgoing_packet_handler="true" loopback="true" ucast_send_buf_size="32000" ip_ttl="32"/>
-            <AUTOCONF down_thread="false" up_thread="false"/>
-            <PING timeout="2000" down_thread="false" num_initial_members="3" up_thread="false"/>
-            <MERGE2 max_interval="10000" down_thread="false" min_interval="5000" up_thread="false"/>
-            <FD_SOCK down_thread="false" up_thread="false"/>
-            <FD timeout="20000" max_tries="3" down_thread="false" up_thread="false" shun="true"/>
-            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
-            <pbcast.NAKACK max_xmit_size="8192" down_thread="false" use_mcast_xmit="true" gc_lag="50" up_thread="false"
-                         retransmit_timeout="100,200,600,1200,2400,4800"/>
-            <UNICAST timeout="1200,2400,3600" down_thread="false" up_thread="false"/>
-            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="20000" down_thread="false" max_bytes="0" up_thread="false"/>
-            <FRAG frag_size="8192" down_thread="false" up_thread="false"/>
-            <VIEW_SYNC avg_send_interval="60000" down_thread="false" up_thread="false" />
-            <pbcast.GMS print_local_addr="true" join_timeout="3000" down_thread="false" join_retry_timeout="2000" up_thread="false" shun="true"/>
-         </config>
-      </attribute>
-      
-      <!-- JGroups stack configuration to use for the control channel - used for bind/unbind requests amongst others -->           
-                  
-      <attribute name="ControlChannelConfig">
-         <config>
-            <UDP mcast_recv_buf_size="500000" down_thread="false" ip_mcast="true" mcast_send_buf_size="32000"
-           mcast_port="45568" ucast_recv_buf_size="500000" use_incoming_packet_handler="false"
-           mcast_addr="228.8.8.8" use_outgoing_packet_handler="true" loopback="true" ucast_send_buf_size="32000" ip_ttl="32"/>
-            <AUTOCONF down_thread="false" up_thread="false"/>
-            <PING timeout="2000" down_thread="false" num_initial_members="3" up_thread="false"/>
-            <MERGE2 max_interval="10000" down_thread="false" min_interval="5000" up_thread="false"/>
-            <FD_SOCK down_thread="false" up_thread="false"/>
-            <FD timeout="20000" max_tries="3" down_thread="false" up_thread="false" shun="true"/>
-            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
-            <pbcast.NAKACK max_xmit_size="8192" down_thread="false" use_mcast_xmit="true" gc_lag="50" up_thread="false"
-                         retransmit_timeout="100,200,600,1200,2400,4800"/>
-            <UNICAST timeout="1200,2400,3600" down_thread="false" up_thread="false"/>
-            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="20000" down_thread="false" max_bytes="0" up_thread="false"/>
-            <FRAG frag_size="8192" down_thread="false" up_thread="false"/>
-            <VIEW_SYNC avg_send_interval="60000" down_thread="false" up_thread="false" />
-            <pbcast.GMS print_local_addr="true" join_timeout="3000" down_thread="false" join_retry_timeout="2000" up_thread="false" shun="true"/>
-            <pbcast.STATE_TRANSFER down_thread="false" up_thread="false"/>
-         </config>
-      </attribute>
-   </mbean>
-   
-   <!-- Messaging JMS User Manager MBean config
-        ======================================= -->
-      
-   <mbean code="org.jboss.jms.server.plugin.JDBCJMSUserManagerService"
-      name="jboss.messaging:service=JMSUserManager"
-      xmbean-dd="xmdesc/JMSUserManager-xmbean.xml">
-      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
-      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
-      <attribute name="DataSource">java:/DefaultDS</attribute>
-      <attribute name="CreateTablesOnStartup">true</attribute>
-      <attribute name="SqlProperties"><![CDATA[
-CREATE_USER_TABLE=CREATE TABLE JBM_USER (USER_ID VARCHAR(32) NOT NULL, PASSWD VARCHAR(32) NOT NULL, CLIENTID VARCHAR(128), PRIMARY KEY(USER_ID))
-CREATE_ROLE_TABLE=CREATE TABLE JBM_ROLE (ROLE_ID VARCHAR(32) NOT NULL, USER_ID VARCHAR(32) NOT NULL, PRIMARY KEY(USER_ID, ROLE_ID))
-SELECT_PRECONF_CLIENTID=SELECT CLIENTID FROM JBM_USER WHERE USER_ID=?
-POPULATE.TABLES.1=INSERT INTO JBM_USER (USER_ID,PASSWD,CLIENTID) VALUES ('dilbert','dogbert','dilbert-id')
-      ]]></attribute>
-   </mbean>
-
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+     MySql persistence deployment descriptor.
+
+     Tested with MySQL 4.1.22
+
+     $Id$
+ -->
+
+<server>
+
+   <!-- Persistence Manager MBean configuration
+       ======================================= -->
+   
+   <mbean code="org.jboss.messaging.core.jmx.JDBCPersistenceManagerService"
+      name="jboss.messaging:service=PersistenceManager"
+      xmbean-dd="xmdesc/JDBCPersistenceManager-xmbean.xml">
+      
+      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
+      
+      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      
+      <!-- The datasource to use for the persistence manager -->
+                    
+      <attribute name="DataSource">java:/DefaultDS</attribute>      
+      
+      <!-- If true will attempt to create tables and indexes on every start-up -->
+                  
+      <attribute name="CreateTablesOnStartup">true</attribute>
+      
+      <!-- If true then will use JDBC batch updates -->
+                  
+      <attribute name="UsingBatchUpdates">true</attribute>
+      
+      <attribute name="SqlProperties"><![CDATA[
+   CREATE_MESSAGE_REFERENCE=CREATE TABLE JBM_MSG_REF (CHANNEL_ID BIGINT, MESSAGE_ID BIGINT, TRANSACTION_ID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, DELIVERY_COUNT INTEGER, SCHED_DELIVERY BIGINT, PRIMARY KEY(CHANNEL_ID, MESSAGE_ID)) ENGINE = INNODB
+   CREATE_IDX_MESSAGE_REF_TX=CREATE INDEX JBM_MSG_REF_TX ON JBM_MSG_REF (TRANSACTION_ID)
+   CREATE_IDX_MESSAGE_REF_ORD=CREATE INDEX JBM_MSG_REF_ORD ON JBM_MSG_REF (ORD)
+   CREATE_IDX_MESSAGE_REF_PAGE_ORD=CREATE INDEX JBM_MSG_REF_PAGE_ORD ON JBM_MSG_REF (PAGE_ORD)
+   CREATE_IDX_MESSAGE_REF_MESSAGE_ID=CREATE INDEX JBM_MSG_REF_MESSAGE_ID ON JBM_MSG_REF (MESSAGE_ID)
+   CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY=CREATE INDEX JBM_MSG_REF_SCHED_DELIVERY ON JBM_MSG_REF (SCHED_DELIVERY)
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, CHANNEL_COUNT INTEGER, TYPE TINYINT, PRIMARY KEY (MESSAGE_ID)) ENGINE = INNODB
+   CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER, TRANSACTION_ID BIGINT, BRANCH_QUAL VARBINARY(254), FORMAT_ID INTEGER, GLOBAL_TXID VARBINARY(254), PRIMARY KEY (TRANSACTION_ID)) ENGINE = INNODB
+   CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME)) ENGINE = INNODB
+   INSERT_MESSAGE_REF=INSERT INTO JBM_MSG_REF (CHANNEL_ID, MESSAGE_ID, TRANSACTION_ID, STATE, ORD, PAGE_ORD, DELIVERY_COUNT, SCHED_DELIVERY) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   DELETE_MESSAGE_REF=DELETE FROM JBM_MSG_REF WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'
+   UPDATE_MESSAGE_REF=UPDATE JBM_MSG_REF SET TRANSACTION_ID=?, STATE='-' WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'
+   UPDATE_PAGE_ORDER=UPDATE JBM_MSG_REF SET PAGE_ORD = ? WHERE MESSAGE_ID=? AND CHANNEL_ID=?
+   COMMIT_MESSAGE_REF1=UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='+'
+   COMMIT_MESSAGE_REF2=DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='-'
+   ROLLBACK_MESSAGE_REF1=DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='+'
+   ROLLBACK_MESSAGE_REF2=UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='-'
+   LOAD_PAGED_REFS=SELECT MESSAGE_ID, DELIVERY_COUNT, PAGE_ORD, SCHED_DELIVERY FROM JBM_MSG_REF WHERE CHANNEL_ID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD
+   LOAD_UNPAGED_REFS=SELECT MESSAGE_ID, DELIVERY_COUNT, SCHED_DELIVERY FROM JBM_MSG_REF WHERE STATE = 'C' AND CHANNEL_ID = ? AND PAGE_ORD IS NULL ORDER BY ORD
+   LOAD_REFS=SELECT MESSAGE_ID, DELIVERY_COUNT, SCHED_DELIVERY FROM JBM_MSG_REF WHERE STATE = 'C' AND CHANNEL_ID = ? ORDER BY ORD     
+   UPDATE_REFS_NOT_PAGED=UPDATE JBM_MSG_REF SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNEL_ID=?
+   SELECT_MIN_MAX_PAGE_ORD=SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JBM_MSG_REF WHERE CHANNEL_ID = ?
+   SELECT_EXISTS_REF_MESSAGE_ID=SELECT MESSAGE_ID FROM JBM_MSG_REF WHERE MESSAGE_ID = ?
+   UPDATE_DELIVERY_COUNT=UPDATE JBM_MSG_REF SET DELIVERY_COUNT = ? WHERE CHANNEL_ID = ? AND MESSAGE_ID = ?
+   UPDATE_CHANNEL_ID=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ?
+   LOAD_MESSAGES=SELECT MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, HEADERS, PAYLOAD, TYPE FROM JBM_MSG
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, HEADERS, PAYLOAD, CHANNEL_COUNT, TYPE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
+   INC_CHANNEL_COUNT=UPDATE JBM_MSG SET CHANNEL_COUNT = CHANNEL_COUNT + 1 WHERE MESSAGE_ID=?
+   DEC_CHANNEL_COUNT=UPDATE JBM_MSG SET CHANNEL_COUNT = CHANNEL_COUNT - 1 WHERE MESSAGE_ID=?
+   DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID=? AND CHANNEL_COUNT=0
+   MESSAGE_ID_COLUMN=MESSAGE_ID
+   MESSAGE_EXISTS=SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ? FOR UPDATE
+   INSERT_TRANSACTION=INSERT INTO JBM_TX (NODE_ID, TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID) VALUES(?, ?, ?, ?, ?)
+   DELETE_TRANSACTION=DELETE FROM JBM_TX WHERE NODE_ID = ? AND TRANSACTION_ID = ?
+   SELECT_PREPARED_TRANSACTIONS=SELECT TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID FROM JBM_TX WHERE NODE_ID = ?
+   SELECT_MESSAGE_ID_FOR_REF=SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '+' ORDER BY ORD
+   SELECT_MESSAGE_ID_FOR_ACK=SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '-' ORDER BY ORD
+   UPDATE_COUNTER=UPDATE JBM_COUNTER SET NEXT_ID = ? WHERE NAME=?
+   SELECT_COUNTER=SELECT NEXT_ID FROM JBM_COUNTER WHERE NAME=? FOR UPDATE
+   INSERT_COUNTER=INSERT INTO JBM_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
+   SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNEL_ID) FROM JBM_MSG_REF
+   UPDATE_TX=UPDATE JBM_TX SET NODE_ID=? WHERE NODE_ID=?
+      ]]></attribute>
+      
+      <!-- The maximum number of parameters to include in a prepared statement -->
+                  
+      <attribute name="MaxParams">500</attribute>
+   </mbean>
+
+   <!-- Messaging Post Office MBean configuration
+        ========================================= -->
+   
+   <mbean code="org.jboss.messaging.core.jmx.MessagingPostOfficeService"
+      name="jboss.messaging:service=PostOffice"
+      xmbean-dd="xmdesc/MessagingPostOffice-xmbean.xml">
+      
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
+                
+      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
+      
+      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      
+      <!-- The name of the post office -->                  
+      
+      <attribute name="PostOfficeName">JMS post office</attribute>
+      
+      <!-- The datasource used by the post office to access it's binding information -->                     
+      
+      <attribute name="DataSource">java:/DefaultDS</attribute>
+      
+      <!-- If true will attempt to create tables and indexes on every start-up -->
+                        
+      <attribute name="CreateTablesOnStartup">true</attribute>
+      
+      <attribute name="SqlProperties"><![CDATA[
+CREATE_POSTOFFICE_TABLE=CREATE TABLE JBM_POSTOFFICE (POSTOFFICE_NAME VARCHAR(255), NODE_ID INTEGER, QUEUE_NAME VARCHAR(255), COND VARCHAR(1023), SELECTOR VARCHAR(1023), CHANNEL_ID BIGINT, CLUSTERED CHAR(1), ALL_NODES CHAR(1), PRIMARY KEY(POSTOFFICE_NAME, NODE_ID, QUEUE_NAME)) ENGINE = INNODB
+INSERT_BINDING=INSERT INTO JBM_POSTOFFICE (POSTOFFICE_NAME, NODE_ID, QUEUE_NAME, COND, SELECTOR, CHANNEL_ID, CLUSTERED, ALL_NODES) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+DELETE_BINDING=DELETE FROM JBM_POSTOFFICE WHERE POSTOFFICE_NAME=? AND NODE_ID=? AND QUEUE_NAME=?
+LOAD_BINDINGS=SELECT QUEUE_NAME, COND, SELECTOR, CHANNEL_ID, CLUSTERED, ALL_NODES FROM JBM_POSTOFFICE WHERE POSTOFFICE_NAME=? AND NODE_ID=?
+      ]]></attribute>
+       
+      <!-- This post office is clustered. If you don't want a clustered post office then set to false -->
+      
+      <attribute name="Clustered">true</attribute>
+      
+      <!-- All the remaining properties only have to be specified if the post office is clustered.
+           You can safely comment them out if your post office is non clustered -->
+      
+      <!-- The JGroups group name that the post office will use -->            
+      
+      <attribute name="GroupName">MessagingPostOffice</attribute>
+      
+      <!-- Max time to wait for state to arrive when the post office joins the cluster -->            
+                  
+      <attribute name="StateTimeout">5000</attribute>
+      
+      <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->            
+                  
+      <attribute name="CastTimeout">50000</attribute>
+      
+      <!-- Enable this when the JGroups multiplexer comes of age
+      <attribute name="ChannelFactoryName">jgroups.mux:name=Multiplexer</attribute>      
+      <attribute name="ControlChannelName">udp-sync</attribute>
+      <attribute name="DataChannelName">udp</attribute>
+      <attribute name="ChannelPartitionName">${jboss.partition.name:DefaultPartition}-JMS</attribute>
+      -->
+      
+      <!-- JGroups stack configuration for the data channel - used when casting messages across the cluster -->               
+      
+      <attribute name="DataChannelConfig">
+         <config>
+            <UDP mcast_recv_buf_size="500000" down_thread="false" ip_mcast="true" mcast_send_buf_size="32000"
+           mcast_port="45567" ucast_recv_buf_size="500000" use_incoming_packet_handler="false"
+           mcast_addr="228.8.8.8" use_outgoing_packet_handler="true" loopback="true" ucast_send_buf_size="32000" ip_ttl="32"/>
+            <AUTOCONF down_thread="false" up_thread="false"/>
+            <PING timeout="2000" down_thread="false" num_initial_members="3" up_thread="false"/>
+            <MERGE2 max_interval="10000" down_thread="false" min_interval="5000" up_thread="false"/>
+            <FD_SOCK down_thread="false" up_thread="false"/>
+            <FD timeout="20000" max_tries="3" down_thread="false" up_thread="false" shun="true"/>
+            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
+            <pbcast.NAKACK max_xmit_size="8192" down_thread="false" use_mcast_xmit="true" gc_lag="50" up_thread="false"
+                         retransmit_timeout="100,200,600,1200,2400,4800"/>
+            <UNICAST timeout="1200,2400,3600" down_thread="false" up_thread="false"/>
+            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="20000" down_thread="false" max_bytes="0" up_thread="false"/>
+            <FRAG frag_size="8192" down_thread="false" up_thread="false"/>
+            <VIEW_SYNC avg_send_interval="60000" down_thread="false" up_thread="false" />
+            <pbcast.GMS print_local_addr="true" join_timeout="3000" down_thread="false" join_retry_timeout="2000" up_thread="false" shun="true"/>
+         </config>
+      </attribute>
+      
+      <!-- JGroups stack configuration to use for the control channel - used for bind/unbind requests amongst others -->           
+                  
+      <attribute name="ControlChannelConfig">
+         <config>
+            <UDP mcast_recv_buf_size="500000" down_thread="false" ip_mcast="true" mcast_send_buf_size="32000"
+           mcast_port="45568" ucast_recv_buf_size="500000" use_incoming_packet_handler="false"
+           mcast_addr="228.8.8.8" use_outgoing_packet_handler="true" loopback="true" ucast_send_buf_size="32000" ip_ttl="32"/>
+            <AUTOCONF down_thread="false" up_thread="false"/>
+            <PING timeout="2000" down_thread="false" num_initial_members="3" up_thread="false"/>
+            <MERGE2 max_interval="10000" down_thread="false" min_interval="5000" up_thread="false"/>
+            <FD_SOCK down_thread="false" up_thread="false"/>
+            <FD timeout="20000" max_tries="3" down_thread="false" up_thread="false" shun="true"/>
+            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
+            <pbcast.NAKACK max_xmit_size="8192" down_thread="false" use_mcast_xmit="true" gc_lag="50" up_thread="false"
+                         retransmit_timeout="100,200,600,1200,2400,4800"/>
+            <UNICAST timeout="1200,2400,3600" down_thread="false" up_thread="false"/>
+            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="20000" down_thread="false" max_bytes="0" up_thread="false"/>
+            <FRAG frag_size="8192" down_thread="false" up_thread="false"/>
+            <VIEW_SYNC avg_send_interval="60000" down_thread="false" up_thread="false" />
+            <pbcast.GMS print_local_addr="true" join_timeout="3000" down_thread="false" join_retry_timeout="2000" up_thread="false" shun="true"/>
+            <pbcast.STATE_TRANSFER down_thread="false" up_thread="false"/>
+         </config>
+      </attribute>
+   </mbean>
+   
+   <!-- Messaging JMS User Manager MBean config
+        ======================================= -->
+      
+   <mbean code="org.jboss.jms.server.plugin.JDBCJMSUserManagerService"
+      name="jboss.messaging:service=JMSUserManager"
+      xmbean-dd="xmdesc/JMSUserManager-xmbean.xml">
+      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
+      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      <attribute name="DataSource">java:/DefaultDS</attribute>
+      <attribute name="CreateTablesOnStartup">true</attribute>
+      <attribute name="SqlProperties"><![CDATA[
+CREATE_USER_TABLE=CREATE TABLE JBM_USER (USER_ID VARCHAR(32) NOT NULL, PASSWD VARCHAR(32) NOT NULL, CLIENTID VARCHAR(128), PRIMARY KEY(USER_ID)) ENGINE = INNODB
+CREATE_ROLE_TABLE=CREATE TABLE JBM_ROLE (ROLE_ID VARCHAR(32) NOT NULL, USER_ID VARCHAR(32) NOT NULL, PRIMARY KEY(USER_ID, ROLE_ID)) ENGINE = INNODB
+SELECT_PRECONF_CLIENTID=SELECT CLIENTID FROM JBM_USER WHERE USER_ID=?
+POPULATE.TABLES.1=INSERT INTO JBM_USER (USER_ID,PASSWD,CLIENTID) VALUES ('dilbert','dogbert','dilbert-id')
+      ]]></attribute>
+   </mbean>
+
 </server>

Modified: trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2007-07-08 13:21:39 UTC (rev 2857)
@@ -194,6 +194,12 @@
       <type>boolean</type>
    </attribute>    
    
+   <attribute access="read-write" getMethod="getRecoverDeliveriesTimeout" setMethod="setRecoverDeliveriesTimeout">
+      <description>When a failover occurs the max. amount of time the server will keep messages in its recovery area. waiting for clients to reconnect</description>
+      <name>RecoverDeliveriesTimeout</name>
+      <type>long</type>
+   </attribute> 
+   
    <attribute access="read-write" getMethod="getDefaultMessageCounterHistoryDayLimit" setMethod="setDefaultMessageCounterHistoryDayLimit">
       <description>The default max number of messages per day in message counter history</description>
       <name>DefaultMessageCounterHistoryDayLimit</name>

Modified: trunk/src/main/org/jboss/jms/client/JBossConnectionConsumer.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/JBossConnectionConsumer.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/JBossConnectionConsumer.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -75,7 +75,7 @@
    
    private SessionDelegate sess;
    
-   private int consumerID;
+   private String consumerID;
    
    /** The ServerSessionPool that is implemented by the AS */
    private ServerSessionPool serverSessionPool;

Modified: trunk/src/main/org/jboss/jms/client/JBossSession.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/JBossSession.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/JBossSession.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -462,7 +462,7 @@
     * This method is used by the JBossConnectionConsumer to load up the session
     * with messages to be processed by the session's run() method
     */
-   void addAsfMessage(MessageProxy m, int consumerID, String queueName, int maxDeliveries,
+   void addAsfMessage(MessageProxy m, String consumerID, String queueName, int maxDeliveries,
                       SessionDelegate connectionConsumerSession, boolean shouldAck)
    {
       delegate.addAsfMessage(m, consumerID, queueName, maxDeliveries, connectionConsumerSession, shouldAck);

Modified: trunk/src/main/org/jboss/jms/client/container/ClientConsumer.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/ClientConsumer.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/ClientConsumer.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -47,7 +47,6 @@
 /**
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox/a>
- * @author <a href="mailto:sergey.koshcheyev at jboss.com">Sergey Koscheyev/a>
  * @version <tt>$Revision: 2774 $</tt>
  *
  * $Id: MessageCallbackHandler.java 2774 2007-06-12 22:43:54Z timfox $
@@ -63,7 +62,8 @@
    private static boolean trace;      
    
    private static final int WAIT_TIMEOUT = 30000;
-      
+   
+   
    static
    {
       log = Logger.getLogger(ClientConsumer.class);
@@ -119,7 +119,7 @@
    //This is static so it can be called by the asf layer too
    public static void callOnMessage(SessionDelegate sess,
                                     MessageListener listener,
-                                    int consumerID,
+                                    String consumerID,
                                     String queueName,
                                     boolean isConnectionConsumer,
                                     MessageProxy m,
@@ -192,13 +192,12 @@
    private PriorityLinkedList buffer;
    private SessionDelegate sessionDelegate;
    private ConsumerDelegate consumerDelegate;
-   private int consumerID;
+   private String consumerID;
    private boolean isConnectionConsumer;
    private volatile Thread receiverThread;
    private MessageListener listener;
    private int ackMode;
    private boolean closed;
-   private volatile boolean paused;
    private Object mainLock;
    private int maxBufferSize;
    private int minBufferSize;
@@ -217,7 +216,7 @@
    // Constructors ---------------------------------------------------------------------------------
 
    public ClientConsumer(boolean isCC, int ackMode,                                
-                         SessionDelegate sess, ConsumerDelegate cons, int consumerID,
+                         SessionDelegate sess, ConsumerDelegate cons, String consumerID,
                          String queueName,
                          int bufferSize, QueuedExecutor sessionExecutor,
                          int maxDeliveries, boolean shouldAck, boolean handleFlowControl,
@@ -288,12 +287,12 @@
          
          this.listener = listener;
                             
-         if (listener != null && isMessageAvailableForConsuming())
+         if (listener != null && !buffer.isEmpty())
          {  
             listenerRunning = true;
             
             this.queueRunner(new ListenerRunner());
-         }
+         }        
       }   
    }
    
@@ -338,15 +337,18 @@
    public void close(long lastDeliveryId) throws JMSException
    {     
    	log.debug(this + " closing");
-      
-      //Wait for the last delivery to arrive
+         	
+   	//Wait for the last delivery to arrive
       waitForLastDelivery(lastDeliveryId);
       
-      //Important! We set paused to true so the next ListenerRunner won't run
-      paused = true;
+      //Important! We set the listener to null so the next ListenerRunner won't run
+      if (listener != null)
+      {
+      	setMessageListener(null);
+      }
       
       //Now we wait for any current listener runners to run.
-      waitForOnMessageToComplete();
+      waitForOnMessageToComplete();   
       
       synchronized (mainLock)
       {         
@@ -368,32 +370,6 @@
                            
       if (trace) { log.trace(this + " closed"); }
    }
-   
-   public void start()
-   {
-      paused = false;
-      synchronized (mainLock)
-      {
-         if (!buffer.isEmpty())
-         {
-            // Messages arrived while the consumer was paused
-            messageAdded();
-         }
-      }
-   }
-   
-   public void stop()
-   {
-      log.debug(this + " stopping");
-      paused = true;
-   }
-
-   public void waitUntilStopped() throws JMSException
-   {
-      log.debug(this + " waiting until paused");
-      waitForOnMessageToComplete();
-      if (trace) { log.trace(this + " stopped"); }
-   }
      
    /**
     * Method used by the client thread to get a Message, if available.
@@ -534,12 +510,12 @@
       return "ClientConsumer[" + consumerID + "]";
    }
    
-   public int getConsumerId()
+   public String getConsumerId()
    {
       return consumerID;
    }
 
-   public void setConsumerId(int consumerId)
+   public void setConsumerId(String consumerId)
    {
        this.consumerID = consumerId;
    }
@@ -592,6 +568,14 @@
    {
       if (trace) { log.trace("Waiting for last delivery id " + id); }
       
+      if (id == -1)
+      {
+      	//No need to wait - nothing to wait for      	
+      	return;
+      }
+      
+      log.info("waiting for last delivery " + id);
+      
       synchronized (mainLock)
       {          
          waitingForLastDelivery = true;
@@ -617,7 +601,7 @@
              
             if (lastDeliveryId != id)
             {
-               log.warn("Timed out waiting for last delivery"); 
+               log.warn("Timed out waiting for last delivery " + id + " got " + lastDeliveryId); 
             }
          }
          finally
@@ -637,11 +621,9 @@
       {
          if (closed)
          {
-            // This should never happen - we should always wait for all deliveries to arrive
+            // Sanity - this should never happen - we should always wait for all deliveries to arrive
             // when closing
-            log.warn(this + " is closed, so ignoring message");
-            
-            return;
+            throw new IllegalStateException(this + " is closed, so ignoring message");
          }
 
          proxy.setSessionDelegate(sessionDelegate, isConnectionConsumer);
@@ -753,30 +735,27 @@
    {
       boolean notified = false;
       
-      if (!paused)
+      // If we have a thread waiting on receive() we notify it
+      if (receiverThread != null)
       {
-         // If we have a thread waiting on receive() we notify it
-         if (receiverThread != null)
+         if (trace) { log.trace(this + " notifying receiver/waiter thread"); }   
+         
+         mainLock.notifyAll();
+         
+         notified = true;
+      }     
+      else if (listener != null)
+      { 
+         // We have a message listener
+         if (!listenerRunning)
          {
-            if (trace) { log.trace(this + " notifying receiver/waiter thread"); }   
-            
-            mainLock.notifyAll();
-   
-            notified = true;
-         }
-         else if (listener != null)
-         {
-            // We have a message listener
-            if (!listenerRunning && !paused)
-            {
-               listenerRunning = true;
-   
-               if (trace) { log.trace(this + " scheduled a new ListenerRunner"); }
-               this.queueRunner(new ListenerRunner());
-            }     
-            
-            //TODO - Execute onMessage on same thread for even better throughput 
-         }
+            listenerRunning = true;
+
+            if (trace) { log.trace(this + " scheduled a new ListenerRunner"); }
+            this.queueRunner(new ListenerRunner());
+         }     
+         
+         //TODO - Execute onMessage on same thread for even better throughput 
       }
       
       // Make sure we notify any thread waiting for last delivery
@@ -820,7 +799,7 @@
             if (timeout == 0)
             {
                // wait for ever potentially
-               while (!closed && !isMessageAvailableForConsuming())
+               while (!closed && buffer.isEmpty())
                {
                   if (trace) { log.trace(this + " waiting on main lock, no timeout"); }
 
@@ -834,7 +813,7 @@
                // wait with timeout
                long toWait = timeout;
              
-               while (!closed && !isMessageAvailableForConsuming() && toWait > 0)
+               while (!closed && buffer.isEmpty() && toWait > 0)
                {
                   if (trace) { log.trace(this + " waiting on main lock, timeout " + toWait + " ms"); }
 
@@ -861,14 +840,6 @@
       return m;
    }
    
-   /**
-    * @return true if the ClientConsumer is not paused and has a message in its buffer.
-    */
-   private boolean isMessageAvailableForConsuming()
-   {
-      return !paused && !buffer.isEmpty();
-   }
-   
    // Inner classes --------------------------------------------------------------------------------
          
    /*
@@ -907,11 +878,11 @@
          
          synchronized (mainLock)
          {
-            if (listener == null || !isMessageAvailableForConsuming())
+            if (listener == null || buffer.isEmpty())
             {
                listenerRunning = false;
                
-               if (trace) { log.trace("no listener or no message available for processing, returning"); }
+               if (trace) { log.trace("no listener or buffer is empty, returning"); }
                
                return;
             }
@@ -922,7 +893,7 @@
 
             mp = (MessageProxy)buffer.removeFirst();
                           
-            if (isMessageAvailableForConsuming())
+            if (!buffer.isEmpty())
             {
             	//Queue up the next runner to run
             	

Modified: trunk/src/main/org/jboss/jms/client/container/ConnectionAspect.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/ConnectionAspect.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/ConnectionAspect.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,10 +21,6 @@
  */
 package org.jboss.jms.client.container;
 
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
 import javax.jms.ExceptionListener;
 import javax.jms.IllegalStateException;
 
@@ -36,8 +32,6 @@
 import org.jboss.jms.client.remoting.ConsolidatedRemotingConnectionListener;
 import org.jboss.jms.client.remoting.JMSRemotingConnection;
 import org.jboss.jms.client.state.ConnectionState;
-import org.jboss.jms.client.state.ConsumerState;
-import org.jboss.jms.client.state.SessionState;
 import org.jboss.jms.message.MessageIdGeneratorFactory;
 import org.jboss.jms.tx.ResourceManagerFactory;
 
@@ -66,7 +60,7 @@
    protected ConnectionState state;
 
    // The identity of the delegate this interceptor is associated with
-   private Integer id;
+   private String id;
 
    // Constructors --------------------------------------------------
    
@@ -151,15 +145,6 @@
       ConnectionState currentState = getConnectionState(invocation);
       currentState.setStarted(true);
       currentState.setJustCreated(false);
-      
-      // Start all consumers
-      forEachConsumer(currentState, new ConsumerAction() {
-         public void run(ClientConsumer consumer) throws Exception
-         {
-            consumer.start();
-         }
-      });
-
       return invocation.invokeNext();
    }
    
@@ -168,27 +153,7 @@
       ConnectionState currentState = getConnectionState(invocation);
       currentState.setStarted(false);
       currentState.setJustCreated(false);
-      
-      Object ret = invocation.invokeNext();
-      
-      // Stop all consumers - in two steps, first tell each one to stop,
-      // then actually wait until all have stopped.
-
-      forEachConsumer(currentState, new ConsumerAction() {
-         public void run(ClientConsumer consumer) throws Exception
-         {
-            consumer.stop();
-         }
-      });
-      
-      forEachConsumer(currentState, new ConsumerAction() {
-         public void run(ClientConsumer consumer) throws Exception
-         {
-            consumer.waitUntilStopped();
-         }
-      });
-
-      return ret;
+      return invocation.invokeNext();
    }
    
    public Object handleCreateSessionDelegate(Invocation invocation) throws Throwable
@@ -286,37 +251,12 @@
             ((ClientConnectionDelegate)invocation.getTargetObject());
          
          state = (ConnectionState)currentDelegate.getState();
-         id = new Integer(state.getDelegate().getID());
+         id = state.getDelegate().getID();
 
       }
       return state;
    }
-      
-   private static void forEachConsumer(ConnectionState connectionState, ConsumerAction action) throws Exception
-   {
-      Set sessions = connectionState.getChildren();
-      
-      for (Iterator sessionsIter = sessions.iterator(); sessionsIter.hasNext();)
-      {
-         SessionState sessionState = (SessionState) sessionsIter.next();
-         
-         for (Iterator childrenIter = sessionState.getChildren().iterator(); childrenIter.hasNext();)
-         {
-            Object childState = childrenIter.next();
-            if (!(childState instanceof ConsumerState))
-            {
-               continue;
-            }
-            ClientConsumer consumer = ((ConsumerState) childState).getClientConsumer();
-            action.run(consumer);
-         }
-      }
-   }
    
+   
    // Inner classes -------------------------------------------------
-
-   private interface ConsumerAction
-   {
-      void run(ClientConsumer consumer) throws Exception;
-   }
 }

Modified: trunk/src/main/org/jboss/jms/client/container/ConsumerAspect.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/ConsumerAspect.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/ConsumerAspect.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -75,7 +75,7 @@
       ConnectionState connectionState = (ConnectionState)sessionState.getParent();
       SessionDelegate sessionDelegate = (SessionDelegate)invocation.getTargetObject();
       ConsumerState consumerState = (ConsumerState)((DelegateSupport)consumerDelegate).getState();
-      int consumerID = consumerState.getConsumerID();
+      String consumerID = consumerState.getConsumerID();
       int prefetchSize = consumerState.getBufferSize();
       QueuedExecutor sessionExecutor = sessionState.getExecutor();
       int maxDeliveries = consumerState.getMaxDeliveries();

Modified: trunk/src/main/org/jboss/jms/client/container/DelegateIdentity.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/DelegateIdentity.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/DelegateIdentity.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -24,7 +24,7 @@
    {
       DelegateSupport ds = (DelegateSupport)i.getTargetObject();
 
-      Integer id = new Integer(ds.getID());
+      String id = ds.getID();
       String type = ds.getClass().getName();
 
       type = type.substring(type.lastIndexOf('.') + 1);
@@ -34,12 +34,12 @@
 
    // Attributes ----------------------------------------------------
 
-   private Integer id;
+   private String id;
    private String type;
 
    // Constructors --------------------------------------------------
 
-   public DelegateIdentity(Integer id, String type)
+   public DelegateIdentity(String id, String type)
    {
       this.id = id;
       this.type = type;
@@ -47,7 +47,7 @@
 
    // Public --------------------------------------------------------
 
-   public Integer getID()
+   public String getID()
    {
       return id;
    }

Modified: trunk/src/main/org/jboss/jms/client/container/JMSClientVMIdentifier.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/JMSClientVMIdentifier.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/JMSClientVMIdentifier.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,7 +21,7 @@
   */
 package org.jboss.jms.client.container;
 
-import org.jboss.util.id.GUID;
+import org.jboss.messaging.util.GUIDGenerator;
 
 /**
  * 
@@ -34,5 +34,5 @@
  */
 public class JMSClientVMIdentifier
 {
-   public static String instance = new GUID().toString();
+   public static String instance = GUIDGenerator.generateGUID();
 }

Modified: trunk/src/main/org/jboss/jms/client/container/SessionAspect.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/SessionAspect.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/SessionAspect.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -287,7 +287,7 @@
             ClientSessionDelegate connectionConsumerDelegate =
                (ClientSessionDelegate)info.getConnectionConsumerSession();
             
-            int sessionId = connectionConsumerDelegate != null ?
+            String sessionId = connectionConsumerDelegate != null ?
                connectionConsumerDelegate.getID() : state.getSessionID();
             
             connState.getResourceManager().addAck(txID, sessionId, info);
@@ -753,7 +753,7 @@
       // Load the session with a message to be processed during a subsequent call to run()
 
       MessageProxy m = (MessageProxy)mi.getArguments()[0];
-      int theConsumerID = ((Integer)mi.getArguments()[1]).intValue();
+      String theConsumerID = (String)mi.getArguments()[1];
       String queueName = (String)mi.getArguments()[2];
       int maxDeliveries = ((Integer)mi.getArguments()[3]).intValue();
       SessionDelegate connectionConsumerDelegate = ((SessionDelegate)mi.getArguments()[4]);
@@ -920,7 +920,7 @@
    private static class AsfMessageHolder
    {
       private MessageProxy msg;
-      private int consumerID;
+      private String consumerID;
       private String queueName;
       private int maxDeliveries;
       private SessionDelegate connectionConsumerDelegate;

Modified: trunk/src/main/org/jboss/jms/client/container/StateCreationAspect.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/StateCreationAspect.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/container/StateCreationAspect.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -157,7 +157,7 @@
       String subscriptionName = (String)mi.getArguments()[3];
       boolean connectionConsumer = ((Boolean)mi.getArguments()[4]).booleanValue();
 
-      int consumerID = consumerDelegate.getID();
+      String consumerID = consumerDelegate.getID();
       int bufferSize = consumerDelegate.getBufferSize();
       int maxDeliveries = consumerDelegate.getMaxDeliveries();
       long redeliveryDelay = consumerDelegate.getRedeliveryDelay();

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientBrowserDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientBrowserDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientBrowserDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -60,7 +60,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-	public ClientBrowserDelegate(int objectID)
+	public ClientBrowserDelegate(String objectID)
    {
       super(objectID);
    }

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientClusteredConnectionFactoryDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientClusteredConnectionFactoryDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientClusteredConnectionFactoryDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -174,6 +174,7 @@
    public synchronized void updateFailoverInfo(ClientConnectionFactoryDelegate[] delegates,
                                                Map failoverMap)
    {	
+   	log.info(this  +"  **** UPDATING FAILOVER INFO");
       this.delegates = delegates;
       this.failoverMap = failoverMap;
 

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -86,7 +86,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   public ClientConnectionDelegate(int objectID, int serverID)
+   public ClientConnectionDelegate(String objectID, int serverID)
    {
       super(objectID);
 

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionFactoryDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionFactoryDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientConnectionFactoryDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -99,7 +99,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   public ClientConnectionFactoryDelegate(int objectID, int serverID, String serverLocatorURI,
+   public ClientConnectionFactoryDelegate(String objectID, int serverID, String serverLocatorURI,
                                           Version serverVersion, boolean clientPing)
    {
       super(objectID);

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientConsumerDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientConsumerDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientConsumerDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -66,7 +66,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   public ClientConsumerDelegate(int objectID, int bufferSize, int maxDeliveries, long redeliveryDelay)
+   public ClientConsumerDelegate(String objectID, int bufferSize, int maxDeliveries, long redeliveryDelay)
    {
       super(objectID);
       this.bufferSize = bufferSize;

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientProducerDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientProducerDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientProducerDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -50,11 +50,6 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   public ClientProducerDelegate()
-   {
-      super(-1);
-   }
-
    // DelegateSupport overrides --------------------------------------------------------------------
 
    public void synchronizeWith(DelegateSupport nd) throws Exception

Modified: trunk/src/main/org/jboss/jms/client/delegate/ClientSessionDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/ClientSessionDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/ClientSessionDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -94,7 +94,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   public ClientSessionDelegate(int objectID, int dupsOKBatchSize)
+   public ClientSessionDelegate(String objectID, int dupsOKBatchSize)
    {
       super(objectID);
 
@@ -434,7 +434,7 @@
     * This invocation should either be handled by the client-side interceptor chain or by the
     * server-side endpoint.
     */
-   public void addAsfMessage(MessageProxy m, int consumerID, String queueName, int maxDeliveries,
+   public void addAsfMessage(MessageProxy m, String consumerID, String queueName, int maxDeliveries,
                              SessionDelegate connectionConsumerSession, boolean shouldAck)
    {
       throw new IllegalStateException("This invocation should not be handled here!");

Modified: trunk/src/main/org/jboss/jms/client/delegate/DelegateSupport.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/delegate/DelegateSupport.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/delegate/DelegateSupport.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -71,7 +71,7 @@
    // Attributes -----------------------------------------------------------------------------------
 
    // This is set on the server.
-   protected int id;
+   protected String id;
 
    // This is set on the client.
    // The reason we don't use the meta-data to store the state for the delegate is to avoid the
@@ -87,7 +87,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   public DelegateSupport(int id)
+   public DelegateSupport(String id)
    {
       this.id = id;
       this.state = null;
@@ -95,7 +95,7 @@
 
    public DelegateSupport()
    {
-      this(Integer.MIN_VALUE);
+      this("NO_ID_SET");
    }
 
    // Interceptor implementation -------------------------------------------------------------------
@@ -110,12 +110,12 @@
    
    public void read(DataInputStream in) throws Exception
    {
-      id = in.readInt();
+      id = in.readUTF();
    }
 
    public void write(DataOutputStream out) throws Exception
    {
-      out.writeInt(id);
+      out.writeUTF(id);
    }
 
    // Public ---------------------------------------------------------------------------------------
@@ -132,7 +132,7 @@
       this.version = state.getVersionToUse().getProviderIncrementingVersion();
    }
 
-   public int getID()
+   public String getID()
    {
       return id;
    }

Modified: trunk/src/main/org/jboss/jms/client/remoting/CallbackManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/remoting/CallbackManager.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/remoting/CallbackManager.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -93,16 +93,14 @@
             createThinDelegate(dr.getDeliveryId(), (JBossMessage)msg, dr.getDeliveryCount());
 
          ClientConsumer handler =
-            (ClientConsumer)callbackHandlers.get(new Integer(dr.getConsumerId()));
+            (ClientConsumer)callbackHandlers.get(dr.getConsumerId());
 
          if (handler == null)
          {
             // This should never happen since we wait for all deliveries to arrive before closing
             // the consumer
 
-            log.warn(this + " callback handler not found, message arrived after consumer is closed. Cancelling it bacdk to queue");
-            
-            return;
+            throw new IllegalStateException(this + " callback handler not found, message arrived after consumer is closed.");
          }
 
          try
@@ -134,20 +132,20 @@
 
    // Public ---------------------------------------------------------------------------------------
 
-   public void registerHandler(int consumerID, ClientConsumer handler)
+   public void registerHandler(String consumerID, ClientConsumer handler)
    {
-      callbackHandlers.put(new Integer(consumerID), handler);
+      callbackHandlers.put(consumerID, handler);
    }
 
-   public void setConnectionDelegate (ClientConnectionDelegate connectionDelegate)
+   public void setConnectionDelegate(ClientConnectionDelegate connectionDelegate)
    {
       this.connectionfactoryCallbackHandler =
          new ConnectionFactoryCallbackHandler(connectionDelegate);
    }
 
-   public ClientConsumer unregisterHandler(int consumerID)
+   public ClientConsumer unregisterHandler(String consumerID)
    { 
-      return (ClientConsumer)callbackHandlers.remove(new Integer(consumerID));
+      return (ClientConsumer)callbackHandlers.remove(consumerID);
    }
 
    public String toString()

Modified: trunk/src/main/org/jboss/jms/client/remoting/JMSRemotingConnection.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/remoting/JMSRemotingConnection.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/remoting/JMSRemotingConnection.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -27,6 +27,7 @@
 import org.jboss.jms.server.ServerPeer;
 import org.jboss.jms.wireformat.JMSWireFormat;
 import org.jboss.logging.Logger;
+import org.jboss.messaging.util.GUIDGenerator;
 import org.jboss.remoting.Client;
 import org.jboss.remoting.InvokerLocator;
 import org.jboss.remoting.ServerInvoker;
@@ -140,7 +141,7 @@
                {
                   if (hash == 0)
                   {
-                     guid = new GUID().toString();
+                     guid = GUIDGenerator.generateGUID();
                      hash = guid.hashCode();
                   }
                   if (hash < 0)

Modified: trunk/src/main/org/jboss/jms/client/state/ConsumerState.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/state/ConsumerState.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/state/ConsumerState.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -50,7 +50,7 @@
 
    // Attributes -----------------------------------------------------------------------------------
 
-   private int consumerID;
+   private String consumerID;
    private JBossDestination destination;
    private String selector;
    private String subscriptionName;
@@ -69,7 +69,7 @@
    // Constructors ---------------------------------------------------------------------------------
 
    public ConsumerState(SessionState parent, ConsumerDelegate delegate, JBossDestination dest,
-                        String selector, boolean noLocal, String subscriptionName, int consumerID,
+                        String selector, boolean noLocal, String subscriptionName, String consumerID,
                         boolean isCC, int bufferSize, int maxDeliveries, long redeliveryDelay)
    {
       super(parent, (DelegateSupport)delegate);
@@ -129,7 +129,7 @@
    {
       ConsumerState newState = (ConsumerState)ns;
 
-      int oldConsumerID = consumerID;
+      String oldConsumerID = consumerID;
       consumerID = newState.consumerID;
       
       CallbackManager oldCallbackManager = ((ClientConnectionDelegate)getParent().getParent().
@@ -163,7 +163,7 @@
       return noLocal;
    }
 
-   public int getConsumerID()
+   public String getConsumerID()
    {
       return consumerID;
    }

Modified: trunk/src/main/org/jboss/jms/client/state/SessionState.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/state/SessionState.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/client/state/SessionState.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -76,7 +76,7 @@
    private ConnectionState parent;
    private SessionDelegate delegate;
 
-   private int sessionID;
+   private String sessionID;
    private int acknowledgeMode;
    private boolean transacted;
    private boolean xa;
@@ -196,7 +196,7 @@
    {
       SessionState newState = (SessionState)ns;
 
-      int oldSessionID = sessionID;
+      String oldSessionID = sessionID;
       sessionID = newState.sessionID;
       
       // We need to clear anything waiting in the session executor - since there may be messages
@@ -419,22 +419,22 @@
       this.recoverCalled = recoverCalled;
    }
 
-   public ClientConsumer getCallbackHandler(int consumerID)
+   public ClientConsumer getCallbackHandler(String consumerID)
    {
-      return (ClientConsumer)callbackHandlers.get(new Integer(consumerID));
+      return (ClientConsumer)callbackHandlers.get(consumerID);
    }
 
    public void addCallbackHandler(ClientConsumer handler)
    {
-      callbackHandlers.put(new Integer(handler.getConsumerId()), handler);
+      callbackHandlers.put(handler.getConsumerId(), handler);
    }
 
    public void removeCallbackHandler(ClientConsumer handler)
    {
-      callbackHandlers.remove(new Integer(handler.getConsumerId()));
+      callbackHandlers.remove(handler.getConsumerId());
    }
 
-   public int getSessionID()
+   public String getSessionID()
    {
       return sessionID;
    }

Modified: trunk/src/main/org/jboss/jms/delegate/DeliveryInfo.java
===================================================================
--- trunk/src/main/org/jboss/jms/delegate/DeliveryInfo.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/delegate/DeliveryInfo.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -43,7 +43,7 @@
    
    //This is needed when doing local redelivery of messages, since we need to know which
    //consumer gets the message
-   private int consumerId;      
+   private String consumerId;      
 
    private MessageProxy msg;
    
@@ -63,7 +63,7 @@
    
    // Constructors --------------------------------------------------
    
-   public DeliveryInfo(MessageProxy msg, int consumerId, String queueName,
+   public DeliveryInfo(MessageProxy msg, String consumerId, String queueName,
                        SessionDelegate connectionConsumerSession, boolean shouldAck)
    {      
       this.msg = msg;
@@ -84,7 +84,7 @@
       return queueName;
    }
    
-   public int getConsumerId()
+   public String getConsumerId()
    {
       return consumerId;
    }

Modified: trunk/src/main/org/jboss/jms/delegate/SessionDelegate.java
===================================================================
--- trunk/src/main/org/jboss/jms/delegate/SessionDelegate.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/delegate/SessionDelegate.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -76,7 +76,7 @@
 
    XAResource getXAResource();
 
-   void addAsfMessage(MessageProxy m, int consumerID, String queueName,
+   void addAsfMessage(MessageProxy m, String consumerID, String queueName,
                       int maxDeliveries, SessionDelegate connectionConsumerDelegate,
                       boolean shouldAck);
 

Modified: trunk/src/main/org/jboss/jms/destination/JBossTemporaryQueue.java
===================================================================
--- trunk/src/main/org/jboss/jms/destination/JBossTemporaryQueue.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/destination/JBossTemporaryQueue.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -25,7 +25,7 @@
 import javax.jms.TemporaryQueue;
 
 import org.jboss.jms.delegate.SessionDelegate;
-import org.jboss.util.id.GUID;
+import org.jboss.messaging.util.GUIDGenerator;
 
 
 /**
@@ -51,7 +51,7 @@
    
    public JBossTemporaryQueue(SessionDelegate delegate)
    {
-      super(new GUID().toString());
+      super(GUIDGenerator.generateGUID());
       this.delegate = delegate;
    }
    

Modified: trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java
===================================================================
--- trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -25,7 +25,7 @@
 import javax.jms.TemporaryTopic;
 
 import org.jboss.jms.delegate.SessionDelegate;
-import org.jboss.util.id.GUID;
+import org.jboss.messaging.util.GUIDGenerator;
 
 /**
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
@@ -49,7 +49,7 @@
    
    public JBossTemporaryTopic(SessionDelegate delegate)
    {
-      super(new GUID().toString());
+      super(GUIDGenerator.generateGUID());
       this.delegate = delegate;
    }
     

Modified: trunk/src/main/org/jboss/jms/message/JBossMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossMessage.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/message/JBossMessage.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -270,7 +270,7 @@
 
    // Attributes ----------------------------------------------------
 
-   protected transient int connectionID;
+   protected transient String connectionID;
    
    protected transient String jmsMessageID;
    
@@ -951,12 +951,12 @@
    {      
    }
    
-   public int getConnectionID()
+   public String getConnectionID()
    {
       return connectionID;
    }
    
-   public void setConnectionID(int connectionID)
+   public void setConnectionID(String connectionID)
    {
       this.connectionID = connectionID;
    }

Modified: trunk/src/main/org/jboss/jms/server/ServerPeer.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ServerPeer.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/ServerPeer.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -22,8 +22,8 @@
 package org.jboss.jms.server;
 
 import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
 import java.io.InputStream;
-import java.io.CharArrayWriter;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
@@ -45,8 +45,8 @@
 import org.jboss.jms.server.connectionmanager.SimpleConnectionManager;
 import org.jboss.jms.server.connectormanager.SimpleConnectorManager;
 import org.jboss.jms.server.destination.ManagedQueue;
+import org.jboss.jms.server.endpoint.ServerConnectionEndpoint;
 import org.jboss.jms.server.endpoint.ServerSessionEndpoint;
-import org.jboss.jms.server.endpoint.ServerConnectionEndpoint;
 import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.server.messagecounter.MessageCounterManager;
 import org.jboss.jms.server.plugin.contract.JMSUserManager;
@@ -69,6 +69,7 @@
 import org.jboss.messaging.core.impl.clusterconnection.ClusterConnectionManager;
 import org.jboss.messaging.core.impl.memory.SimpleMemoryManager;
 import org.jboss.messaging.core.impl.message.SimpleMessageStore;
+import org.jboss.messaging.core.impl.postoffice.MessagingPostOffice;
 import org.jboss.messaging.core.impl.tx.TransactionRepository;
 import org.jboss.messaging.util.ExceptionUtil;
 import org.jboss.messaging.util.Util;
@@ -116,8 +117,6 @@
 
    private boolean started;
 
-   private int objectIDSequence = 1;
-
    private boolean supportsFailover = true;
 
    // The default maximum number of delivery attempts before sending to DLQ - can be overridden on
@@ -143,6 +142,8 @@
    private boolean useXAForMessagePull;
    
    private boolean defaultPreserveOrdering;
+   
+   private long recoverDeliveriesTimeout = 5 * 60 * 1000;
       
    // wired components
 
@@ -619,6 +620,16 @@
    	this.defaultPreserveOrdering = preserve;
    }
    
+   public long getRecoverDeliveriesTimeout()
+   {
+   	return this.recoverDeliveriesTimeout;
+   }
+   
+   public void setRecoverDeliveriesTimeout(long timeout)
+   {
+   	this.recoverDeliveriesTimeout = timeout;
+   }
+   
    public synchronized void setServerPeerID(int serverPeerID)
    {
       if (started)
@@ -1051,17 +1062,22 @@
       return channelIDManager;
    }
    
-   public ServerSessionEndpoint getSession(Integer sessionID)
+   public ServerSessionEndpoint getSession(String sessionID)
    {
       return (ServerSessionEndpoint)sessions.get(sessionID);
    }
    
-   public void addSession(Integer id, ServerSessionEndpoint session)
+   public Collection getSessions()
    {
+   	return sessions.values();
+   }
+   
+   public void addSession(String id, ServerSessionEndpoint session)
+   {
       sessions.put(id, session);      
    }
    
-   public void removeSession(Integer id)
+   public void removeSession(String id)
    {
       if (sessions.remove(id) == null)
       {
@@ -1233,6 +1249,8 @@
             this.clusterConnectionManager.injectReplicator((Replicator)postOffice);
             
             this.connectionManager.injectReplicator((Replicator)postOffice);
+            
+            ((MessagingPostOffice)postOffice).injectServerPeer(this);
          }
          
          // Also need to inject into txRepository
@@ -1251,12 +1269,12 @@
    	return failoverWaiter;
    }
 
-   public synchronized int getNextObjectID()
-   {
-      return objectIDSequence++;
-   }
+//   public synchronized int getNextObjectID()
+//   {
+//      return objectIDSequence++;
+//   }
+//
 
-
    public boolean isSupportsFailover()
    {
       return supportsFailover;

Modified: trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -51,6 +51,7 @@
 import org.jboss.messaging.core.contract.ClusterNotification;
 import org.jboss.messaging.core.contract.ClusterNotificationListener;
 import org.jboss.messaging.core.contract.Replicator;
+import org.jboss.messaging.util.GUIDGenerator;
 import org.jboss.messaging.util.JNDIUtil;
 import org.jboss.messaging.util.Version;
 
@@ -130,7 +131,7 @@
                                             "registered with name " + uniqueName);
       }
 
-      int id = serverPeer.getNextObjectID();
+      String id = GUIDGenerator.generateGUID();
       Version version = serverPeer.getVersion();
 
       ServerConnectionFactoryEndpoint endpoint =
@@ -139,7 +140,8 @@
                                              defaultTempQueueFullSize,
                                              defaultTempQueuePageSize,
                                              defaultTempQueueDownCacheSize,
-                                             dupsOKBatchSize);
+                                             dupsOKBatchSize,
+                                             supportsFailover);
       endpoints.put(uniqueName, endpoint);
 
       ConnectionFactoryDelegate delegate = null;
@@ -376,6 +378,7 @@
 		
 		            rebindConnectionFactory(initialContext, endpoint.getJNDIBindings(), del);
 
+		            log.info("**** Updating clustered clients");
 		            endpoint.updateClusteredClients(delArr, failoverMap);
                }
             }

Modified: trunk/src/main/org/jboss/jms/server/destination/QueueService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -105,7 +105,8 @@
                                        true,
                                        destination.getMaxSize(), null,
                                        destination.getFullSize(), destination.getPageSize(),
-                                       destination.getDownCacheSize(), destination.isClustered());
+                                       destination.getDownCacheSize(), destination.isClustered(),
+                                       serverPeer.getRecoverDeliveriesTimeout());
             po.addBinding(new Binding(queueCond, queue, false), false);         
             
             queue.activate();

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -58,7 +58,7 @@
 
    // Attributes -----------------------------------------------------------------------------------
 
-   private int id;
+   private String id;
    private boolean closed;
    private ServerSessionEndpoint session;
    private Channel destination;
@@ -67,7 +67,7 @@
 
    // Constructors ---------------------------------------------------------------------------------
 
-   ServerBrowserEndpoint(ServerSessionEndpoint session, int id,
+   ServerBrowserEndpoint(ServerSessionEndpoint session, String id,
                          Channel destination, String messageSelector) throws JMSException
    {     
       this.session = session;

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,6 +21,7 @@
   */
 package org.jboss.jms.server.endpoint;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -28,7 +29,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.ArrayList;
 
 import javax.jms.Destination;
 import javax.jms.IllegalStateException;
@@ -63,9 +63,11 @@
 import org.jboss.messaging.core.impl.tx.Transaction;
 import org.jboss.messaging.core.impl.tx.TransactionRepository;
 import org.jboss.messaging.util.ExceptionUtil;
+import org.jboss.messaging.util.GUIDGenerator;
 import org.jboss.messaging.util.Util;
 import org.jboss.remoting.Client;
 import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
+import org.jboss.util.id.GUID;
 
 /**
  * Concrete implementation of ConnectionEndpoint.
@@ -88,7 +90,7 @@
 
    // Attributes -----------------------------------------------------------------------------------
 
-   private int id;
+   private String id;
 
    private volatile boolean closed;
    private volatile boolean started;
@@ -161,7 +163,7 @@
  
       started = false;
 
-      this.id = serverPeer.getNextObjectID();
+      this.id = GUIDGenerator.generateGUID();
       this.clientID = clientID;
       this.prefetchSize = prefetchSize;
       
@@ -234,7 +236,7 @@
             throw new IllegalStateException("Connection is closed");
          }
                   
-         int sessionID = serverPeer.getNextObjectID();
+         String sessionID = GUIDGenerator.generateGUID();
            
          // create the corresponding server-side session endpoint and register it with this
          // connection endpoint instance
@@ -242,7 +244,7 @@
          
          synchronized (sessions)
          {
-            sessions.put(new Integer(sessionID), ep);
+            sessions.put(sessionID, ep);
          }
          
          SessionAdvised advised;
@@ -256,11 +258,9 @@
          
          SessionAdvised sessionAdvised = advised;
          
-         Integer iSessionID = new Integer(sessionID);
-         
-         serverPeer.addSession(iSessionID, ep);
+         serverPeer.addSession(sessionID, ep);
 
-         Dispatcher.instance.registerTarget(iSessionID, sessionAdvised);
+         Dispatcher.instance.registerTarget(sessionID, sessionAdvised);
 
          log.debug("created and registered " + ep);
 
@@ -594,7 +594,7 @@
       return defaultTempQueueDownCacheSize;
    }
    
-   int getConnectionID()
+   String getConnectionID()
    {
       return id;
    }
@@ -604,14 +604,13 @@
       return started;    
    }
    
-   void removeSession(int sessionId) throws Exception
+   void removeSession(String sessionId) throws Exception
    {
       synchronized (sessions)
       {
-         if (sessions.remove(new Integer(sessionId)) == null)
+         if (sessions.remove(sessionId) == null)
          {
-            throw new IllegalStateException("Cannot find session with id " +
-               sessionId + " to remove");
+            throw new IllegalStateException("Cannot find session with id " + sessionId + " to remove");
          }
       }
    }
@@ -810,8 +809,7 @@
             // of a connection consumer, the message might be delivered through one connection and
             // the transaction committed/rolledback through another. ConnectionConsumers suck.
             
-            ServerSessionEndpoint session =
-               serverPeer.getSession(new Integer(sessionState.getSessionId()));
+            ServerSessionEndpoint session = serverPeer.getSession(sessionState.getSessionId());
             
             if (session == null)
             {               

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -66,34 +66,37 @@
 
    private String clientID;
 
-   private int id;
+   private String id;
 
    private JNDIBindings jndiBindings;
 
    private int prefetchSize;
 
-   protected int defaultTempQueueFullSize;
+   private int defaultTempQueueFullSize;
 
-   protected int defaultTempQueuePageSize;
+   private int defaultTempQueuePageSize;
 
-   protected int defaultTempQueueDownCacheSize;
+   private int defaultTempQueueDownCacheSize;
 
-   protected int dupsOKBatchSize;
+   private int dupsOKBatchSize;
    
+   private boolean supportsFailover;
+   
    // Constructors ---------------------------------------------------------------------------------
 
    /**
     * @param jndiBindings - names under which the corresponding JBossConnectionFactory is bound in
     *        JNDI.
     */
-   public ServerConnectionFactoryEndpoint(int id, ServerPeer serverPeer,
+   public ServerConnectionFactoryEndpoint(String id, ServerPeer serverPeer,
                                           String defaultClientID,
                                           JNDIBindings jndiBindings,
                                           int preFetchSize,
                                           int defaultTempQueueFullSize,
                                           int defaultTempQueuePageSize,
                                           int defaultTempQueueDownCacheSize,
-                                          int dupsOKBatchSize)
+                                          int dupsOKBatchSize,
+                                          boolean supportsFailover)
    {
       this.serverPeer = serverPeer;
       this.clientID = defaultClientID;
@@ -104,6 +107,7 @@
       this.defaultTempQueuePageSize = defaultTempQueuePageSize;
       this.defaultTempQueueDownCacheSize = defaultTempQueueDownCacheSize;
       this.dupsOKBatchSize = dupsOKBatchSize;
+      this.supportsFailover = supportsFailover;
    }
 
    // ConnectionFactoryDelegate implementation -----------------------------------------------------
@@ -224,7 +228,7 @@
                                       remotingSessionID, clientVMID, versionToUse,
                                       callbackHandler, dupsOKBatchSize);
 
-      int connectionID = endpoint.getConnectionID();
+      String connectionID = endpoint.getConnectionID();
 
       ConnectionAdvised connAdvised;
       
@@ -261,7 +265,7 @@
 
    // Public ---------------------------------------------------------------------------------------
    
-   public int getID()
+   public String getID()
    {
       return id;
    }
@@ -321,6 +325,11 @@
 
    // Package protected ----------------------------------------------------------------------------
    
+   boolean isSupportsFailover()
+   {
+   	return supportsFailover;
+   }
+   
    // Protected ------------------------------------------------------------------------------------
    
    // Private --------------------------------------------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -33,7 +33,6 @@
 import org.jboss.jms.server.destination.TopicService;
 import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.server.selector.Selector;
-import org.jboss.jms.wireformat.ClientDelivery;
 import org.jboss.jms.wireformat.Dispatcher;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.Delivery;
@@ -47,9 +46,6 @@
 import org.jboss.messaging.core.impl.SimpleDelivery;
 import org.jboss.messaging.core.impl.tx.Transaction;
 import org.jboss.messaging.util.ExceptionUtil;
-import org.jboss.remoting.Client;
-import org.jboss.remoting.callback.Callback;
-import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
 
 /**
  * Concrete implementation of ConsumerEndpoint. Lives on the boundary between Messaging Core and the
@@ -71,7 +67,7 @@
 
    private boolean trace = log.isTraceEnabled();
 
-   private int id;
+   private String id;
 
    private Queue messageQueue;
 
@@ -79,8 +75,6 @@
 
    private ServerSessionEndpoint sessionEndpoint;
 
-   private ServerInvokerCallbackHandler callbackHandler;
-
    private boolean noLocal;
 
    private Selector messageSelector;
@@ -111,13 +105,15 @@
    
    private boolean preserveOrdering;
    
+   private boolean replicating;
+   
    // Constructors ---------------------------------------------------------------------------------
 
-   ServerConsumerEndpoint(int id, Queue messageQueue, String queueName,
+   ServerConsumerEndpoint(String id, Queue messageQueue, String queueName,
 					           ServerSessionEndpoint sessionEndpoint, String selector,
 					           boolean noLocal, JBossDestination dest, Queue dlq,
 					           Queue expiryQueue, long redeliveryDelay, int maxDeliveryAttempts,
-					           boolean remote) throws InvalidSelectorException
+					           boolean remote, boolean replicating) throws InvalidSelectorException
    {
       if (trace)
       {
@@ -132,8 +128,6 @@
 
       this.sessionEndpoint = sessionEndpoint;
 
-      this.callbackHandler = sessionEndpoint.getConnectionEndpoint().getCallbackHandler();
-
       this.noLocal = noLocal;
 
       this.destination = dest;
@@ -155,6 +149,8 @@
 
       this.preserveOrdering = sessionEndpoint.getConnectionEndpoint().getServerPeer().isDefaultPreserveOrdering();
       
+      this.replicating = replicating;
+      
       if (dest.isTopic() && !messageQueue.isRecoverable())
       {
          // This is a consumer of a non durable topic subscription. We don't need to store
@@ -197,8 +193,7 @@
     * The queue ensures that handle is never called concurrently by more than
     * one thread.
     */
-   public Delivery handle(DeliveryObserver observer, MessageReference ref,
-            Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
       if (trace)
       {
@@ -265,96 +260,21 @@
             return delivery;
          }
          
-         long deliveryId;
-
-         if (retainDeliveries)
-         {
-            deliveryId = sessionEndpoint.addDelivery(delivery, id, dlq, expiryQueue, redeliveryDelay, maxDeliveryAttempts);
-         }
-         else
-         {
-            deliveryId = -1;
-         	//Acknowledge it now
-         	try
-         	{
-         		//This basically just releases the memory reference
-         		delivery.acknowledge(null);
-         	}
-         	catch (Throwable t)
-         	{
-         		log.error("Failed to acknowledge delivery", t);
-         	}
-         }
-
-         // We send the message to the client on the current thread. The message is written onto the
-         // transport and then the thread returns immediately without waiting for a response.
-
-         Client callbackClient = callbackHandler.getCallbackClient();
-
-         ClientDelivery del = new ClientDelivery(message, id, deliveryId, ref.getDeliveryCount());
-
-         Callback callback = new Callback(del);
-
          try
          {
-            // FIXME - due a design (flaw??) in the socket based transports, they use a pool of TCP
-            // connections, so subsequent invocations can end up using different underlying
-            // connections meaning that later invocations can overtake earlier invocations, if there
-            // are more than one user concurrently invoking on the same transport. We need someway
-            // of pinning the client object to the underlying invocation. For now we just serialize
-            // all access so that only the first connection in the pool is ever used - bit this is
-            // far from ideal!!!
-            // See http://jira.jboss.com/jira/browse/JBMESSAGING-789
-
-            Object invoker = null;
-
-            if (callbackClient != null)
-            {
-               invoker = callbackClient.getInvoker();                              
-            }
-            else
-            {
-               // TODO: dummy synchronization object, in case there's no clientInvoker. This will
-               // happen during the first invocation anyway. It's a kludge, I know, but this whole
-               // synchronization thing is a huge kludge. Needs to be reviewed.
-               invoker = new Object();
-            }
-            
-            synchronized (invoker)
-            {
-               // one way invocation, no acknowledgment sent back by the client
-               if (trace) { log.trace(this + " submitting message " + message + " to the remoting layer to be sent asynchronously"); }
-               
-               callbackHandler.handleCallbackOneway(callback);
-               
-               //We store the delivery id so we know to wait for any deliveries in transit on close
-               this.lastDeliveryID = deliveryId;
-            }
+         	sessionEndpoint.handleDelivery(delivery, this);
          }
-         catch (Throwable t)
+         catch (Exception e)
          {
-            // it's an oneway callback, so exception could only have happened on the server, while
-            // trying to send the callback. This is a good reason to smack the whole connection.
-            // I trust remoting to have already done its own cleanup via a CallbackErrorHandler,
-            // I need to do my own cleanup at ConnectionManager level.
-
-            log.debug(this + " failed to handle callback", t);
-            
-            //We stop the consumer - some time later the lease will expire and the connection will be closed        
-            //which will remove the consumer
-            
-            started = false;
-
-            //** IMPORTANT NOTE! We must return the delivery NOT null. **
-            //This is because if we return NULL then message will remain in the queue, but later
-            //the connection checker will cleanup and close this consumer which will cancel all the deliveries in it
-            //including this one, so the message will go back on the queue twice!
+         	log.error("Failed to handle delivery", e);
+         	
+         	this.started = false; // DO NOT return null or the message might get delivered more than once
          }
-
+                                  
          return delivery;
       }
    }
-
+   
    // Filter implementation ------------------------------------------------------------------------
 
    public boolean accept(Message msg)
@@ -377,11 +297,11 @@
       {
          if (noLocal)
          {
-            int conId = ((JBossMessage) msg).getConnectionID();
+            String conId = ((JBossMessage) msg).getConnectionID();
 
             if (trace) { log.trace("message connection id: " + conId + " current connection connection id: " + sessionEndpoint.getConnectionEndpoint().getConnectionID()); }
 
-            accept = conId != sessionEndpoint.getConnectionEndpoint().getConnectionID();
+            accept = !conId.equals(sessionEndpoint.getConnectionEndpoint().getConnectionID());
 
             if (trace) { log.trace("accepting? " + accept); }
          }
@@ -488,7 +408,32 @@
    }
 
    // Package protected ----------------------------------------------------------------------------
+   
+   boolean isReplicating()
+   {
+   	return replicating;
+   }
+   
+   String getID()
+   {
+   	return this.id;
+   }
 
+   boolean isRetainDeliveries()
+   {
+   	return this.retainDeliveries;
+   }
+   
+   void setLastDeliveryID(long id)
+   {
+   	this.lastDeliveryID = id;
+   }
+   
+   void setStarted(boolean started)
+   {
+   	this.started = started;
+   }
+   
    Queue getDLQ()
    {
       return dlq;
@@ -503,6 +448,16 @@
    {
       return redeliveryDelay;
    }
+   
+   int getMaxDeliveryAttempts()
+   {
+   	return maxDeliveryAttempts;
+   }
+   
+   String getQueueName()
+   {
+   	return queueName;
+   }
 
    void localClose() throws Throwable
    {
@@ -620,6 +575,11 @@
          // 9) Remoting connection listener is removed and remoting connection stopped.
 
       }
+      
+      if (replicating)
+      {      	
+      	sessionEndpoint.waitForDeliveriesFromConsumer(id);
+      }
    }
 
    // Protected ------------------------------------------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,6 +21,7 @@
   */
 package org.jboss.jms.server.endpoint;
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -60,6 +61,7 @@
 import org.jboss.jms.server.endpoint.advised.ConsumerAdvised;
 import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.server.selector.Selector;
+import org.jboss.jms.wireformat.ClientDelivery;
 import org.jboss.jms.wireformat.Dispatcher;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.Binding;
@@ -67,6 +69,7 @@
 import org.jboss.messaging.core.contract.Condition;
 import org.jboss.messaging.core.contract.Delivery;
 import org.jboss.messaging.core.contract.DeliveryObserver;
+import org.jboss.messaging.core.contract.Message;
 import org.jboss.messaging.core.contract.MessageReference;
 import org.jboss.messaging.core.contract.MessageStore;
 import org.jboss.messaging.core.contract.PersistenceManager;
@@ -80,8 +83,11 @@
 import org.jboss.messaging.core.impl.tx.TransactionRepository;
 import org.jboss.messaging.core.impl.tx.TxCallback;
 import org.jboss.messaging.util.ExceptionUtil;
+import org.jboss.messaging.util.GUIDGenerator;
 import org.jboss.messaging.util.MessageQueueNameHelper;
-import org.jboss.util.id.GUID;
+import org.jboss.remoting.Client;
+import org.jboss.remoting.callback.Callback;
+import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
 import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
@@ -119,17 +125,21 @@
    
    static final String TEMP_QUEUE_MESSAGECOUNTER_PREFIX = "TempQueue.";
    
+   private static final long CLOSE_TIMEOUT = 10 * 10000;
+   
+   
    // Static ---------------------------------------------------------------------------------------
 
    // Attributes -----------------------------------------------------------------------------------
 
    private boolean trace = log.isTraceEnabled();
 
-   private int id;
+   private String id;
 
    private volatile boolean closed;
 
    private ServerConnectionEndpoint connectionEndpoint;
+   private ServerInvokerCallbackHandler callbackHandler;
    
    private ServerPeer sp;
 
@@ -148,7 +158,10 @@
    private long defaultRedeliveryDelay;
    private Queue defaultDLQ;
    private Queue defaultExpiryQueue;
+   private boolean supportsFailover;
    
+   private Object deliveryLock = new Object();
+      
    // Map <deliveryID, Delivery>
    private Map deliveries;
    
@@ -159,30 +172,44 @@
    
    // Constructors ---------------------------------------------------------------------------------
 
-   ServerSessionEndpoint(int sessionID, ServerConnectionEndpoint connectionEndpoint)
-      throws Exception
+   ServerSessionEndpoint(String sessionID, ServerConnectionEndpoint connectionEndpoint) throws Exception
    {
       this.id = sessionID;
 
       this.connectionEndpoint = connectionEndpoint;
-
+      
+      callbackHandler = connectionEndpoint.getCallbackHandler();
+      
       sp = connectionEndpoint.getServerPeer();
 
       pm = sp.getPersistenceManagerInstance();
+      
       ms = sp.getMessageStore();
+      
       dm = sp.getDestinationManager();
-      postOffice = sp.getPostOfficeInstance();     
+      
+      postOffice = sp.getPostOfficeInstance(); 
+      
+      supportsFailover = connectionEndpoint.getConnectionFactoryEndpoint().isSupportsFailover() && postOffice.isClustered();
+      
       idm = sp.getChannelIDManager();
+      
       nodeId = sp.getServerPeerID();
+      
       tr = sp.getTxRepository();
-
+      
       consumers = new HashMap();
+      
 		browsers = new HashMap();
       
       defaultDLQ = sp.getDefaultDLQInstance();
+      
       defaultExpiryQueue = sp.getDefaultExpiryQueueInstance();
+      
       tr = sp.getTxRepository();
+      
       defaultMaxDeliveryAttempts = sp.getDefaultMaxDeliveryAttempts();
+      
       defaultRedeliveryDelay = sp.getDefaultRedeliveryDelay();
       
       deliveries = new ConcurrentHashMap();
@@ -503,8 +530,15 @@
                if (trace) { log.trace(this + " Recovered delivery " + deliveryId + ", " + del); }
                
                deliveries.put(new Long(deliveryId),
-                              new DeliveryRecord(del, -1, dlqToUse,
-                                                 expiryQueueToUse, dest.getRedeliveryDelay(), maxDeliveryAttemptsToUse));
+                              new DeliveryRecord(del, dlqToUse, expiryQueueToUse, dest.getRedeliveryDelay(), maxDeliveryAttemptsToUse, queueName, supportsFailover));
+               
+               //We want to replicate the deliveries to the new backup, but we don't want a response since that would cause actual delivery
+               //to occur, which we don't want since the client already has the deliveries
+               
+               if (supportsFailover)
+               {
+               	postOffice.sendReplicateDeliveryMessage(queueName, id, del.getReference().getMessage().getMessageID(), deliveryId, false, true);
+               }
             }
          }
          
@@ -559,7 +593,8 @@
          {            
             Queue coreQueue = new MessagingQueue(nodeId, dest.getName(),
             												 idm.getID(), ms, pm, false, -1, null,
-										                   fullSize, pageSize, downCacheSize, postOffice.isClustered());
+										                   fullSize, pageSize, downCacheSize, postOffice.isClustered(),
+										                   sp.getRecoverDeliveriesTimeout());
 
         
             Condition cond = new JMSCondition(true, dest.getName());
@@ -752,22 +787,22 @@
       }
    }
       
-   void removeBrowser(int browserId) throws Exception
+   void removeBrowser(String browserId) throws Exception
    {
       synchronized (browsers)
       {
-         if (browsers.remove(new Integer(browserId)) == null)
+         if (browsers.remove(browserId) == null)
          {
             throw new IllegalStateException("Cannot find browser with id " + browserId + " to remove");
          }
       }
    }
 
-   void removeConsumer(int consumerId) throws Exception
+   void removeConsumer(String consumerId) throws Exception
    {
       synchronized (consumers)
       {
-         if (consumers.remove(new Integer(consumerId)) == null)
+         if (consumers.remove(consumerId) == null)
          {
             throw new IllegalStateException("Cannot find consumer with id " + consumerId + " to remove");
          }
@@ -866,7 +901,7 @@
 
       deliveries.clear();
       
-      sp.removeSession(new Integer(id));
+      sp.removeSession(id);
             
       Dispatcher.instance.unregisterTarget(id, this);
       
@@ -885,17 +920,270 @@
       rec.del.cancel();
    }
    
-   long addDelivery(Delivery del, int consumerId, Queue dlq, Queue expiryQueue, long redeliveryDelay, int maxDeliveryAttempts)
+   public void collectDeliveries(Map map)
    {
-      long deliveryId = deliveryIdSequence.increment();
-      
-      deliveries.put(new Long(deliveryId), new DeliveryRecord(del, consumerId, dlq, expiryQueue, redeliveryDelay, maxDeliveryAttempts));
-      
-      if (trace) { log.trace(this + " added delivery " + deliveryId + ": " + del); }
-      
-      return deliveryId;      
-   }      
+   	Iterator iter = deliveries.entrySet().iterator();
+   	
+   	while (iter.hasNext())
+   	{
+   		Map.Entry entry = (Map.Entry)iter.next();
+   		
+   		Long l = (Long)entry.getKey();
+   		
+   		long deliveryID = l.longValue();
+   		
+   		DeliveryRecord rec = (DeliveryRecord)entry.getValue();
+   		
+   		if (rec.replicating)
+   		{
+   			Set ids = (Set)map.get(rec.queueName);
+   			
+   			if (ids == null)
+   			{
+   				ids = new HashSet();
+   				
+   				map.put(rec.queueName, ids);
+   			}
+   			
+   			ids.add(new Long(rec.del.getReference().getMessage().getMessageID()));
+   			
+   			if (rec.waitingForResponse)
+   			{
+   				//Do the delivery now
+   				
+   				performDelivery(rec.del.getReference(), deliveryID, rec.getConsumer());   	   	
+   		   	
+   		   	rec.waitingForResponse = false;
+   		   	
+   		   	synchronized (deliveryLock)
+   		   	{
+   		   		deliveryLock.notifyAll();
+   		   	}   				
+   			}
+   		}
+   	}
+   }
    
+   public void replicateDeliveryResponseReceived(long deliveryID)
+   {
+   	//We look up the delivery in the list and actually perform the delivery
+   	
+   	if (trace) { log.trace(this + " replicate delivery response received for delivery " + deliveryID); }
+   	
+   	DeliveryRecord rec = (DeliveryRecord)this.deliveries.get(new Long(deliveryID));
+   	
+   	if (rec == null)
+   	{
+   		throw new java.lang.IllegalStateException("Cannot find delivery with id " + deliveryID);
+   	}
+   	
+   	performDelivery(rec.del.getReference(), deliveryID, rec.getConsumer());   	   	
+   	
+   	rec.waitingForResponse = false;
+   	
+   	synchronized (deliveryLock)
+   	{
+   		deliveryLock.notifyAll();
+   	}
+   }
+   
+   /*
+    * When a consumer closes there may be deliveries where the replication messages has gone out to the backup
+    * but the response hasn't been received yet so the messages hasn't actually been delivered.
+    * When closing we must wait for these to be delivered before closing, or the message will be "lost" until
+    * the session is closed.
+    */
+   void waitForDeliveriesFromConsumer(String consumerID)
+   {   
+   	log.info("Waiting for deliveries for consumer " + consumerID);
+   	
+		long toWait = CLOSE_TIMEOUT;
+		
+		boolean wait;
+		
+   	synchronized (deliveryLock)
+   	{   		
+   		do
+   		{
+   			wait = false;
+   			
+   			long start = System.currentTimeMillis();
+   			
+	   		Iterator iter = deliveries.values().iterator();
+	   		
+	   		while (iter.hasNext())
+	   		{
+	   			DeliveryRecord rec = (DeliveryRecord)iter.next();
+	   			
+	   			ServerConsumerEndpoint consumer = rec.getConsumer();
+	   			
+	   			if (consumer != null && consumer.getID().equals(consumerID) && rec.waitingForResponse)
+	   			{
+	   				wait = true;
+	   				
+	   				break;
+	   			}
+	   		}
+	   		
+	   		if (wait)
+	   		{
+	   			try
+	   			{
+	   				deliveryLock.wait(toWait);
+	   			}
+	   			catch (InterruptedException e)
+	   			{
+	   				//Ignore
+	   			}
+	   			toWait -= (System.currentTimeMillis() - start);
+	   		}
+   		}
+   		while (wait && toWait > 0);
+   		
+   		if (toWait <= 0)
+   		{
+   			log.warn("Timed out waiting for response to arrive");
+   		}
+   	}
+   	log.info("Done Waiting for deliveries for consumer " + consumerID);
+   }
+   
+   void handleDelivery(Delivery delivery, ServerConsumerEndpoint consumer) throws Exception
+   {
+   	 long deliveryId = -1;
+   	 
+   	 if (trace) { log.trace(this + " handling delivery " + delivery); }
+   	 
+   	 DeliveryRecord rec = null;
+   	 
+       if (consumer.isRetainDeliveries())
+       {
+      	 // Add a delivery
+      	 deliveryId = deliveryIdSequence.increment();
+      	 
+      	 rec = new DeliveryRecord(delivery, consumer);
+          
+          deliveries.put(new Long(deliveryId), rec);
+          
+          if (trace) { log.trace(this + " added delivery " + deliveryId + ": " + delivery); }
+       }
+       else
+       {
+       	//Acknowledge it now
+       	try
+       	{
+       		//This basically just releases the memory reference
+       		delivery.acknowledge(null);
+       	}
+       	catch (Throwable t)
+       	{
+       		log.error("Failed to acknowledge delivery", t);
+       	}
+       }
+       
+       Message message = delivery.getReference().getMessage();
+       
+       if (!consumer.isReplicating() || !message.isReliable())
+       {
+      	 if (trace) { log.trace(this + " doing the delivery straight away"); }
+      	 
+      	 //Actually do the delivery now
+      	 performDelivery(delivery.getReference(), deliveryId, consumer); 	           
+       }
+       else
+       {
+      	 //We wait for the replication response to come back before actually performing delivery
+      	 
+      	 if (trace) { log.trace(this + " deferring delivery until we know it's been replicated"); }
+      	 
+      	 if (rec != null)
+      	 {
+      		 rec.waitingForResponse = true;
+      	 }
+      	 
+      	 postOffice.sendReplicateDeliveryMessage(consumer.getQueueName(), id,
+      			                                   delivery.getReference().getMessage().getMessageID(), deliveryId, true, false);
+       }
+
+   }
+   
+   void performDelivery(MessageReference ref, long deliveryID, ServerConsumerEndpoint consumer)
+   {
+   	if (consumer == null)
+   	{
+   		if (trace) { log.trace(this + " consumer is null, cannot perform delivery"); }
+   		
+   		return;
+   	}
+   	
+   	if (trace) { log.trace(this + " performing delivery for " + ref); }
+   	   	
+      // We send the message to the client on the current thread. The message is written onto the
+      // transport and then the thread returns immediately without waiting for a response.
+
+      Client callbackClient = callbackHandler.getCallbackClient();
+
+      ClientDelivery del = new ClientDelivery(ref.getMessage(), consumer.getID(), deliveryID, ref.getDeliveryCount());
+
+      Callback callback = new Callback(del);
+
+      try
+      {
+         // FIXME - due a design (flaw??) in the socket based transports, they use a pool of TCP
+         // connections, so subsequent invocations can end up using different underlying
+         // connections meaning that later invocations can overtake earlier invocations, if there
+         // are more than one user concurrently invoking on the same transport. We need someway
+         // of pinning the client object to the underlying invocation. For now we just serialize
+         // all access so that only the first connection in the pool is ever used - bit this is
+         // far from ideal!!!
+         // See http://jira.jboss.com/jira/browse/JBMESSAGING-789
+
+         Object invoker = null;
+
+         if (callbackClient != null)
+         {
+            invoker = callbackClient.getInvoker();                              
+         }
+         else
+         {
+            // TODO: dummy synchronization object, in case there's no clientInvoker. This will
+            // happen during the first invocation anyway. It's a kludge, I know, but this whole
+            // synchronization thing is a huge kludge. Needs to be reviewed.
+            invoker = new Object();
+         }
+         
+         synchronized (invoker)
+         {
+            // one way invocation, no acknowledgment sent back by the client
+            if (trace) { log.trace(this + " submitting message " + ref.getMessage() + " to the remoting layer to be sent asynchronously"); }
+            
+            callbackHandler.handleCallbackOneway(callback);
+                                    
+            //We store the delivery id so we know to wait for any deliveries in transit on close
+            consumer.setLastDeliveryID(deliveryID);
+         }
+      }
+      catch (Throwable t)
+      {
+         // it's an oneway callback, so exception could only have happened on the server, while
+         // trying to send the callback. This is a good reason to smack the whole connection.
+         // I trust remoting to have already done its own cleanup via a CallbackErrorHandler,
+         // I need to do my own cleanup at ConnectionManager level.
+
+         log.debug(this + " failed to handle callback", t);
+         
+         //We stop the consumer - some time later the lease will expire and the connection will be closed        
+         //which will remove the consumer
+         
+         consumer.setStarted(false);
+
+         //** IMPORTANT NOTE! We must return the delivery NOT null. **
+         //This is because if we return NULL then message will remain in the queue, but later
+         //the connection checker will cleanup and close this consumer which will cancel all the deliveries in it
+         //including this one, so the message will go back on the queue twice!
+      }
+   }
+   
    void acknowledgeTransactionally(List acks, Transaction tx) throws Throwable
    {
       if (trace) { log.trace(this + " acknowledging transactionally " + acks.size() + " messages for " + tx); }
@@ -1034,6 +1322,9 @@
          }
       }      
       
+      //Need to send a message to the replicant to remove the id
+      postOffice.sendReplicateAckMessage(rec.queueName, del.getReference().getMessage().getMessageID());
+      
       return rec.del;
    }      
    
@@ -1134,8 +1425,16 @@
          return;
       }
       
-      rec.del.acknowledge(null);    
+      rec.del.acknowledge(null);  
       
+      //Now replicate the ack
+      
+      if (rec.replicating)
+      {
+      	//this.sendReplicateAckMessage(rec.del.getReference().getMessage().getMessageID());
+      	postOffice.sendReplicateAckMessage(rec.queueName, rec.del.getReference().getMessage().getMessageID());
+      }
+      
       if (trace) { log.trace(this + " acknowledged delivery " + ack); }
    }
    
@@ -1167,7 +1466,7 @@
       	throw new IllegalArgumentException("Cannot find queue with name " + queueName);
       }
       
-      int consumerID = connectionEndpoint.getServerPeer().getNextObjectID();
+      String consumerID = GUIDGenerator.generateGUID();
             
       int prefetchSize = connectionEndpoint.getPrefetchSize();
       
@@ -1178,7 +1477,7 @@
       ServerConsumerEndpoint ep =
          new ServerConsumerEndpoint(consumerID, binding.queue,
                                     binding.queue.getName(), this, selectorString, false,
-                                    dest, null, null, 0, -1, true);
+                                    dest, null, null, 0, -1, true, false);
       
       ConsumerAdvised advised;
       
@@ -1196,7 +1495,7 @@
       
       synchronized (consumers)
       {
-         consumers.put(new Integer(consumerID), ep);
+         consumers.put(consumerID, ep);
       }
          
       log.debug(this + " created and registered " + ep);    
@@ -1247,7 +1546,7 @@
          }
       }
       
-      int consumerID = connectionEndpoint.getServerPeer().getNextObjectID();
+      String consumerID = GUIDGenerator.generateGUID();
       
       // Always validate the selector first
       Selector selector = null;
@@ -1268,13 +1567,14 @@
             
             // Create the non durable sub
             
-            queue = new MessagingQueue(nodeId, new GUID().toString(),
+            queue = new MessagingQueue(nodeId, GUIDGenerator.generateGUID(),
 							                  idm.getID(), ms, pm, false,
 							                  mDest.getMaxSize(), selector,
 							                  mDest.getFullSize(),
 							                  mDest.getPageSize(),
 							                  mDest.getDownCacheSize(),
-							                  mDest.isClustered());
+							                  mDest.isClustered(),
+							                  sp.getRecoverDeliveriesTimeout());
             
             JMSCondition topicCond = new JMSCondition(false, jmsDestination.getName());
                         
@@ -1331,7 +1631,8 @@
                                           mDest.getFullSize(),
                                           mDest.getPageSize(),
                                           mDest.getDownCacheSize(),
-                                          mDest.isClustered());
+                                          mDest.isClustered(),
+                                          sp.getRecoverDeliveriesTimeout());
                
                // Durable subs must be bound on ALL nodes of the cluster (if clustered)
                
@@ -1419,7 +1720,8 @@
 					                              mDest.getFullSize(),
 					                              mDest.getPageSize(),
 					                              mDest.getDownCacheSize(),
-					                              mDest.isClustered());
+					                              mDest.isClustered(),
+					                              sp.getRecoverDeliveriesTimeout());
                   
                   // Durable subs must be bound on ALL nodes of the cluster
                   
@@ -1469,10 +1771,18 @@
           
       long redeliveryDelayToUse = mDest.getRedeliveryDelay() == -1 ? defaultRedeliveryDelay : mDest.getRedeliveryDelay();
       
+      //Is the consumer going to have its session state replicated onto a backup node?
+      //We don't replicate temp destinations or non durable topic subscribers
+      boolean replicating = supportsFailover && !jmsDestination.isTemporary() &&
+                            ((jmsDestination.isTopic() && subscriptionName != null) ||
+                             jmsDestination.isQueue()) &&
+                            mDest.isClustered(); 
+                                 
       ServerConsumerEndpoint ep =
          new ServerConsumerEndpoint(consumerID, queue,
                                     queue.getName(), this, selectorString, noLocal,
-                                    jmsDestination, dlqToUse, expiryQueueToUse, redeliveryDelayToUse, maxDeliveryAttemptsToUse, false);
+                                    jmsDestination, dlqToUse, expiryQueueToUse, redeliveryDelayToUse,
+                                    maxDeliveryAttemptsToUse, false, replicating);
       
       if (queue.isClustered() && postOffice.isClustered() && jmsDestination.isTopic() && subscriptionName != null)
       {
@@ -1504,7 +1814,7 @@
       
       synchronized (consumers)
       {
-         consumers.put(new Integer(consumerID), ep);
+         consumers.put(consumerID, ep);
       }
          
       log.debug(this + " created and registered " + ep);
@@ -1545,14 +1855,14 @@
       	throw new IllegalStateException("Cannot find queue with name " + jmsDestination.getName());
       }
       
-      int browserID = connectionEndpoint.getServerPeer().getNextObjectID();
+      String browserID = GUIDGenerator.generateGUID();
 
       ServerBrowserEndpoint ep = new ServerBrowserEndpoint(this, browserID, binding.queue, selector);
 
       // still need to synchronized since close() can come in on a different thread
       synchronized (browsers)
       {
-         browsers.put(new Integer(browserID), ep);
+         browsers.put(browserID, ep);
       }
 
       BrowserAdvised advised;
@@ -1602,10 +1912,10 @@
     */
    private static class DeliveryRecord
    {
+   	// We need to cache the attributes here  since the consumer may get gc'd BEFORE the delivery is acked
+   	
       Delivery del;
-      
-      int consumerId;
-      
+        
       Queue dlq;
       
       Queue expiryQueue;
@@ -1614,19 +1924,50 @@
       
       int maxDeliveryAttempts;
       
-      DeliveryRecord(Delivery del, int consumerId, Queue dlq, Queue expiryQueue, long redeliveryDelay, int maxDeliveryAttempts)
+      WeakReference consumerRef;
+      
+      String queueName;
+      
+      boolean replicating;
+      
+      volatile boolean waitingForResponse;
+      
+      ServerConsumerEndpoint getConsumer()
       {
-         this.del = del;
+      	return (ServerConsumerEndpoint)consumerRef.get();
+      }
+            
+      DeliveryRecord(Delivery del, Queue dlq, Queue expiryQueue, long redeliveryDelay, int maxDeliveryAttempts,
+      		         String queueName, boolean replicating)
+      {
+      	this.del = del;
+      	
+      	this.dlq = dlq;
+      	
+      	this.expiryQueue = expiryQueue;
+      	
+      	this.redeliveryDelay = redeliveryDelay;
+      	
+      	this.maxDeliveryAttempts = maxDeliveryAttempts;
+      	
+      	this.queueName = queueName;
+      	
+      	this.replicating = replicating;
+      }
+      
+      DeliveryRecord(Delivery del, ServerConsumerEndpoint consumer)
+      {
+      	this (del, consumer.getDLQ(), consumer.getExpiryQueue(), consumer.getRedliveryDelay(), consumer.getMaxDeliveryAttempts(),
+      			consumer.getQueueName(), consumer.isReplicating());
+
+      	// We need to cache the attributes here  since the consumer may get gc'd BEFORE the delivery is acked
          
-         this.consumerId = consumerId;
-         
-         this.dlq = dlq;
-         
-         this.expiryQueue = expiryQueue;
-         
-         this.redeliveryDelay = redeliveryDelay;
-         
-         this.maxDeliveryAttempts = maxDeliveryAttempts;
+      	
+         //We hold a WeakReference to the consumer - this is only needed when replicating - where we store the delivery then wait
+         //for the response to come back from the replicant before actually performing delivery
+         //We need a weak ref since when the consumer closes deliveries may still and remain and we don't want that to prevent
+         //the consumer being gc'd
+         this.consumerRef = new WeakReference(consumer);
       }            
    }
    
@@ -1668,7 +2009,20 @@
          {
             Long deliveryId = (Long)iter.next();
             
-            deliveries.remove(deliveryId);
+            DeliveryRecord del = (DeliveryRecord)deliveries.remove(deliveryId);
+            
+            if (del != null && del.replicating)
+            {
+            	//TODO - we could batch this in one message
+            	try
+            	{
+            		postOffice.sendReplicateAckMessage(del.queueName, del.del.getReference().getMessage().getMessageID());
+            	}
+            	catch (Exception e)
+            	{            		
+            		throw new TransactionException("Failed to handle send ack", e);
+            	}
+            }
          }
       }
       

Modified: trunk/src/main/org/jboss/jms/tx/ClientTransaction.java
===================================================================
--- trunk/src/main/org/jboss/jms/tx/ClientTransaction.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/tx/ClientTransaction.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -91,7 +91,7 @@
       return state;
    }
 
-   public void addMessage(int sessionId, JBossMessage msg)
+   public void addMessage(String sessionId, JBossMessage msg)
    {
       if (!clientSide)
       {
@@ -102,7 +102,7 @@
       sessionTxState.addMessage(msg);
    }
    
-   public void addAck(int sessionId, DeliveryInfo info)
+   public void addAck(String sessionId, DeliveryInfo info)
    {
       if (!clientSide)
       {
@@ -177,7 +177,7 @@
    /*
    * Substitute newSessionID for oldSessionID
    */
-   public void handleFailover(int newServerID, int oldSessionID, int newSessionID)
+   public void handleFailover(int newServerID, String oldSessionID, String newSessionID)
    {
       if (!clientSide)
       {
@@ -193,15 +193,15 @@
       {
          for(Iterator i = sessionStatesMap.values().iterator(); i.hasNext();)
          {
-
             SessionTxState state = (SessionTxState)i.next();
+            
             state.handleFailover(newServerID, oldSessionID, newSessionID);
 
             if (tmpMap == null)
             {
                tmpMap = new LinkedHashMap();
             }
-            tmpMap.put(new Integer(newSessionID), state);
+            tmpMap.put(newSessionID, state);
          }
       }
 
@@ -217,7 +217,7 @@
    /**
     * May return an empty list, but never null.
     */
-   public List getDeliveriesForSession(int sessionID)
+   public List getDeliveriesForSession(String sessionID)
    {
       if (!clientSide)
       {
@@ -230,7 +230,7 @@
       }
       else
       {         
-         SessionTxState state = (SessionTxState)sessionStatesMap.get(new Integer(sessionID));
+         SessionTxState state = (SessionTxState)sessionStatesMap.get(sessionID);
    
          if (state != null)
          {
@@ -302,7 +302,7 @@
          {
             SessionTxState state = (SessionTxState)iter.next();
 
-            out.writeInt(state.getSessionId());
+            out.writeUTF(state.getSessionId());
 
             List msgs = state.getMsgs();
 
@@ -351,7 +351,7 @@
 
       for (int i = 0; i < numSessions; i++)
       {
-         int sessionId = in.readInt();
+         String sessionId = in.readUTF();
 
          SessionTxState sessionState = new SessionTxState(sessionId);
 
@@ -387,19 +387,20 @@
 
    // Private -------------------------------------------------------
 
-   private SessionTxState getSessionTxState(int sessionID)
+   private SessionTxState getSessionTxState(String sessionID)
    {
       if (sessionStatesMap == null)
       {
          sessionStatesMap = new LinkedHashMap();
       }
 
-      SessionTxState sessionTxState = (SessionTxState)sessionStatesMap.get(new Integer(sessionID));
+      SessionTxState sessionTxState = (SessionTxState)sessionStatesMap.get(sessionID);
 
       if (sessionTxState == null)
       {
          sessionTxState = new SessionTxState(sessionID);
-         sessionStatesMap.put(new Integer(sessionID), sessionTxState);
+         
+         sessionStatesMap.put(sessionID, sessionTxState);
       }
 
       return sessionTxState;
@@ -409,7 +410,7 @@
 
    public class SessionTxState
    {
-      private int sessionID;
+      private String sessionID;
 
       // We record the server id when doing failover to avoid overwriting the sesion ID again if
       // multiple connections fail on the same resource mamanger but fail onto old values of the
@@ -419,7 +420,7 @@
       private List msgs = new ArrayList();
       private List acks = new ArrayList();
 
-      SessionTxState(int sessionID)
+      SessionTxState(String sessionID)
       {
          this.sessionID = sessionID;
       }
@@ -444,7 +445,7 @@
          return acks;
       }
 
-      public int getSessionId()
+      public String getSessionId()
       {
          return sessionID;
       }
@@ -454,9 +455,9 @@
       	this.acks = acks;
       }
 
-      void handleFailover(int newServerID, int oldSessionID, int newSessionID)
+      void handleFailover(int newServerID, String oldSessionID, String newSessionID)
       {
-         if (sessionID == oldSessionID && serverID != newServerID)
+         if (sessionID.equals(oldSessionID) && serverID != newServerID)
          {
             sessionID = newSessionID;
             serverID = newServerID;

Modified: trunk/src/main/org/jboss/jms/tx/LocalTx.java
===================================================================
--- trunk/src/main/org/jboss/jms/tx/LocalTx.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/tx/LocalTx.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,7 +21,7 @@
   */
 package org.jboss.jms.tx;
 
-import org.jboss.util.id.GUID;
+import org.jboss.messaging.util.GUIDGenerator;
 
 /**
  * 
@@ -34,7 +34,7 @@
  */
 public class LocalTx
 {
-   private String id = new GUID().toString();
+   private String id = GUIDGenerator.generateGUID();
    
    public String toString()
    {

Modified: trunk/src/main/org/jboss/jms/tx/ResourceManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/tx/ResourceManager.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/tx/ResourceManager.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -126,7 +126,7 @@
     * @param xid - The id of the transaction to add the message to
     * @param m The message
     */
-   public void addMessage(Object xid, int sessionId, JBossMessage m)
+   public void addMessage(Object xid, String sessionId, JBossMessage m)
    {
       if (trace) { log.trace("addding message " + m + " for xid " + xid); }
       
@@ -138,7 +138,7 @@
    /*
     * Failover session from old session ID -> new session ID
     */
-   public void handleFailover(int newServerID, int oldSessionID, int newSessionID)
+   public void handleFailover(int newServerID, String oldSessionID, String newSessionID)
    {
       for(Iterator i = this.transactions.values().iterator(); i.hasNext(); )
       {
@@ -150,7 +150,7 @@
    /*
     * Get all the deliveries corresponding to the session ID
     */
-   public List getDeliveriesForSession(int sessionID)
+   public List getDeliveriesForSession(String sessionID)
    {
       List ackInfos = new ArrayList();
 
@@ -172,7 +172,7 @@
     * @param xid - The id of the transaction to add the message to
     * @param ackInfo Information describing the acknowledgement
     */
-   public void addAck(Object xid, int sessionId, DeliveryInfo ackInfo) throws JMSException
+   public void addAck(Object xid, String sessionId, DeliveryInfo ackInfo) throws JMSException
    {
       if (trace) { log.trace("adding " + ackInfo + " to transaction " + xid); }
       
@@ -192,8 +192,6 @@
       
       ClientTransaction tx = this.getTxInternal(xid);
       
-      checkAndRollbackJMS(tx, xid);
-      
       // Invalid xid
       if (tx == null)
       {
@@ -260,7 +258,7 @@
    }
       
    
-   public boolean checkForAcksInSession(int sessionId)
+   public boolean checkForAcksInSession(String sessionId)
    {         
       Iterator iter = transactions.entrySet().iterator();
       
@@ -330,8 +328,6 @@
          throw new MessagingXAException(XAException.XAER_NOTA, "Cannot find transaction with xid:" + xid);
       } 
       
-      checkAndRollbackXA(state, xid);
-      
       TransactionRequest request =
          new TransactionRequest(TransactionRequest.TWO_PHASE_PREPARE_REQUEST, xid, state);
       
@@ -360,8 +356,6 @@
             throw new MessagingXAException(XAException.XAER_NOTA, "Cannot find transaction with xid:" + xid);
          }
          
-         checkAndRollbackXA(tx, xid);
-         
          TransactionRequest request =
             new TransactionRequest(TransactionRequest.ONE_PHASE_COMMIT_REQUEST, null, tx);
          
@@ -659,60 +653,6 @@
       }
    }
    
-   private void checkAndRollbackJMS(ClientTransaction state, Object xid) throws JMSException
-   {
-      Exception e = checkAndRollback(state, xid, false);
-      if (e != null)
-      {
-         throw (JMSException)e;
-      }
-   }
-   
-   private void checkAndRollbackXA(ClientTransaction state, Object xid) throws XAException
-   {
-      Exception e = checkAndRollback(state, xid, true);
-      if (e != null)
-      {
-         throw (XAException)e;
-      }
-   }
-   
-   private Exception checkAndRollback(ClientTransaction state, Object xid, boolean xa)
-   {
-      if (state.isFailedOver() && state.hasPersistentAcks())
-      {
-         // http://jira.jboss.org/jira/browse/JBMESSAGING-883
-         // If a transaction has persistent acks in it and it has failed over from another server
-         // then it's possible that on failover another consumer got the messages that we have already
-         // received. Therfore to be strict and avoid any possibility of duplicate delivery we must
-         // doom the transaction
-         removeTx(xid);
-         
-         try
-         {
-            redeliverMessages(state);
-         }
-         catch (JMSException e)
-         {
-            log.error("Failed to redeliver messages", e);
-         }
-          
-         
-         final String msg = "Rolled back tx branch to avoid possibility of duplicates http://jira.jboss.org/jira/browse/JBMESSAGING-883";
-         
-         if (xa)
-         {
-            return new MessagingXAException(XAException.XA_HEURRB, msg);
-         }
-         else
-         {
-            return new MessagingTransactionRolledBackException(msg);
-         }            
-      }
-      
-      return null;
-   }
-   
    // Inner Classes --------------------------------------------------------------------------------
   
 }

Modified: trunk/src/main/org/jboss/jms/wireformat/BrowserHasNextMessageRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/BrowserHasNextMessageRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/BrowserHasNextMessageRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -39,7 +39,7 @@
    {      
    }
    
-   public BrowserHasNextMessageRequest(int objectId,
+   public BrowserHasNextMessageRequest(String objectId,
                                        byte version)
    {
       super(objectId, PacketSupport.REQ_BROWSER_HASNEXTMESSAGE, version);

Modified: trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageBlockRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageBlockRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageBlockRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -45,7 +45,7 @@
    {      
    }
    
-   public BrowserNextMessageBlockRequest(int objectId,
+   public BrowserNextMessageBlockRequest(String objectId,
                                          byte version,
                                          int maxMessages)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/BrowserNextMessageRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -43,7 +43,7 @@
    {      
    }
    
-   public BrowserNextMessageRequest(int objectId,
+   public BrowserNextMessageRequest(String objectId,
                                     byte version)
    {
       super(objectId, PacketSupport.REQ_BROWSER_NEXTMESSAGE, version);

Modified: trunk/src/main/org/jboss/jms/wireformat/BrowserResetRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/BrowserResetRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/BrowserResetRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -30,7 +30,7 @@
    {
    }
 
-   public BrowserResetRequest(int objectId, byte version)
+   public BrowserResetRequest(String objectId, byte version)
    {
       super(objectId, PacketSupport.REQ_BROWSER_RESET, version);
    }

Modified: trunk/src/main/org/jboss/jms/wireformat/ClientDelivery.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ClientDelivery.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ClientDelivery.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -48,7 +48,7 @@
    
    private Message msg;
          
-   private int consumerId;
+   private String consumerId;
    
    private long deliveryId;
    
@@ -60,7 +60,7 @@
    {      
    }
 
-   public ClientDelivery(Message msg, int consumerId, long deliveryId, int deliveryCount)
+   public ClientDelivery(Message msg, String consumerId, long deliveryId, int deliveryCount)
    {
       super (PacketSupport.CLIENT_DELIVERY);
       
@@ -80,7 +80,7 @@
 
       super.write(out);
       
-      out.writeInt(consumerId);
+      out.writeUTF(consumerId);
 
       out.writeInt(deliveryCount);
  
@@ -95,9 +95,8 @@
 
    public void read(DataInputStream in) throws Exception
    {
-      consumerId = in.readInt();
+      consumerId = in.readUTF();
       
-
       deliveryCount = in.readInt();
        
       deliveryId = in.readLong();
@@ -116,7 +115,7 @@
       return msg;
    }
    
-   public int getConsumerId()
+   public String getConsumerId()
    {
       return consumerId;
    }

Modified: trunk/src/main/org/jboss/jms/wireformat/CloseRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/CloseRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/CloseRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -43,7 +43,7 @@
    {      
    }
    
-   public CloseRequest(int objectId, byte version)
+   public CloseRequest(String objectId, byte version)
    {
       super(objectId, PacketSupport.REQ_CLOSE, version);
    }

Modified: trunk/src/main/org/jboss/jms/wireformat/ClosingRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ClosingRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ClosingRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -40,7 +40,7 @@
    {      
    }
    
-   public ClosingRequest(int objectId, byte version)
+   public ClosingRequest(String objectId, byte version)
    {
       super(objectId, PacketSupport.REQ_CLOSING, version);
    }

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionCreateSessionDelegateRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionCreateSessionDelegateRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionCreateSessionDelegateRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -49,7 +49,7 @@
    {      
    }
    
-   public ConnectionCreateSessionDelegateRequest(int objectId,
+   public ConnectionCreateSessionDelegateRequest(String objectId,
                                                  byte version,
                                                  boolean transacted, int ackMode,
                                                  boolean xa)

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryCreateConnectionDelegateRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryCreateConnectionDelegateRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryCreateConnectionDelegateRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -55,7 +55,7 @@
    {      
    }
 
-   public ConnectionFactoryCreateConnectionDelegateRequest(int objectId,
+   public ConnectionFactoryCreateConnectionDelegateRequest(String objectId,
                                                            byte version,
                                                            String remotingSessionId,
                                                            String clientVMId,

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryGetClientAOPStackRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryGetClientAOPStackRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionFactoryGetClientAOPStackRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -47,7 +47,7 @@
    {
    }
 
-   public ConnectionFactoryGetClientAOPStackRequest(int objectId, byte version)
+   public ConnectionFactoryGetClientAOPStackRequest(String objectId, byte version)
    {
       super(objectId, PacketSupport.REQ_CONNECTIONFACTORY_GETCLIENTAOPSTACK, version);
    }

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionGetClientIDRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionGetClientIDRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionGetClientIDRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -43,7 +43,7 @@
    {      
    }
    
-   public ConnectionGetClientIDRequest(int objectId,
+   public ConnectionGetClientIDRequest(String objectId,
                                        byte version)
    {
       super(objectId, PacketSupport.REQ_CONNECTION_GETCLIENTID, version);

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionGetIDBlockRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionGetIDBlockRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionGetIDBlockRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -34,7 +34,7 @@
    {      
    }
 
-   public ConnectionGetIDBlockRequest(int objectId,
+   public ConnectionGetIDBlockRequest(String objectId,
                                       byte version,
                                       int size)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionGetPreparedTransactionsRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionGetPreparedTransactionsRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionGetPreparedTransactionsRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -43,7 +43,7 @@
    {      
    }
    
-   public ConnectionGetPreparedTransactionsRequest(int objectId,
+   public ConnectionGetPreparedTransactionsRequest(String objectId,
                                                    byte version)
    {
       super(objectId, PacketSupport.REQ_CONNECTION_GETPREPAREDTRANSACTIONS, version);

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionSendTransactionRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionSendTransactionRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionSendTransactionRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -47,7 +47,7 @@
    {      
    }
    
-   public ConnectionSendTransactionRequest(int objectId,
+   public ConnectionSendTransactionRequest(String objectId,
                                            byte version,
                                            TransactionRequest req,
                                            boolean checkForDuplicates)

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionSetClientIDRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionSetClientIDRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionSetClientIDRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -44,7 +44,7 @@
    {      
    }
    
-   public ConnectionSetClientIDRequest(int objectId,
+   public ConnectionSetClientIDRequest(String objectId,
                                        byte version,
                                        String clientID)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionStartRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionStartRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionStartRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -44,7 +44,7 @@
    {      
    }
    
-   public ConnectionStartRequest(int objectId,
+   public ConnectionStartRequest(String objectId,
                                  byte version)
    {
       super(objectId, PacketSupport.REQ_CONNECTION_START, version);

Modified: trunk/src/main/org/jboss/jms/wireformat/ConnectionStopRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConnectionStopRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConnectionStopRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -43,7 +43,7 @@
    {      
    }
    
-   public ConnectionStopRequest(int objectId,
+   public ConnectionStopRequest(String objectId,
                                 byte version)
    {
       super(objectId, PacketSupport.REQ_CONNECTION_STOP, version);

Modified: trunk/src/main/org/jboss/jms/wireformat/ConsumerChangeRateRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/ConsumerChangeRateRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/ConsumerChangeRateRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -45,7 +45,7 @@
    {      
    }
    
-   public ConsumerChangeRateRequest(int objectId,
+   public ConsumerChangeRateRequest(String objectId,
                                     byte version,
                                     float newRate)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/Dispatcher.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/Dispatcher.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/Dispatcher.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -50,28 +50,18 @@
       targets = new ConcurrentReaderHashMap();
    }
    
-   public Object getTarget(int id)
+   public Object getTarget(String id)
    {
-      return getTarget(new Integer(id));
-   }
-   
-   public Object getTarget(Integer id)
-   {
       return targets.get(id);
    }
-   
-   public void registerTarget(Integer id, AdvisedSupport obj)
+      
+   public void registerTarget(String id, AdvisedSupport obj)
    {
       targets.put(id, obj);
    }
-   
-   public void registerTarget(int id, AdvisedSupport obj)
+      
+   public boolean unregisterTarget(String id, Object endpoint)
    {
-      registerTarget(new Integer(id), obj);
-   }
-   
-   public boolean unregisterTarget(Integer id, Object endpoint)
-   {
       // Note that we pass the object id in, this is as a sanity check to ensure the object we are
       // deregistering is the correct one since there have been bugs related to deregistering the
       // wrong object. This can happen if an earlier test opens a connection then the test ends
@@ -100,10 +90,5 @@
          return targets.remove(id) != null;
       }
    }
-   
-   public boolean unregisterTarget(int id, Object obj)
-   {      
-      return unregisterTarget(new Integer(id), obj);
-   }
-   
+     
 }

Modified: trunk/src/main/org/jboss/jms/wireformat/RequestSupport.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/RequestSupport.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/RequestSupport.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -36,7 +36,7 @@
  */
 public abstract class RequestSupport extends PacketSupport
 {    
-   protected int objectId;
+   protected String objectId;
   
    protected byte version;
    
@@ -44,7 +44,7 @@
    {      
    }  
    
-   public RequestSupport(int objectId, int methodId, byte version)
+   public RequestSupport(String objectId, int methodId, byte version)
    {
       super(methodId);
       
@@ -68,7 +68,7 @@
       return methodId;
    }
 
-   public int getObjectId()
+   public String getObjectId()
    {
       return objectId;
    }
@@ -86,14 +86,14 @@
       
       os.writeByte(version);
 
-      os.writeInt(objectId);
+      os.writeUTF(objectId);
    }
    
    public void read(DataInputStream is) throws Exception
    {     
       version = is.readByte();
       
-      objectId = is.readInt();
+      objectId = is.readUTF();
    }
    
 }

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveriesRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveriesRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveriesRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -50,7 +50,7 @@
    {      
    }
    
-   public SessionAcknowledgeDeliveriesRequest(int objectId,
+   public SessionAcknowledgeDeliveriesRequest(String objectId,
                                               byte version,
                                               List acks)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveryRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveryRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionAcknowledgeDeliveryRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -47,7 +47,7 @@
    {      
    }
    
-   public SessionAcknowledgeDeliveryRequest(int objectId,
+   public SessionAcknowledgeDeliveryRequest(String objectId,
                                             byte version,
                                             Ack ack)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionAddTemporaryDestinationRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionAddTemporaryDestinationRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionAddTemporaryDestinationRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -46,7 +46,7 @@
    {      
    }
    
-   public SessionAddTemporaryDestinationRequest(int objectId,
+   public SessionAddTemporaryDestinationRequest(String objectId,
                                                 byte version,
                                                 JBossDestination dest)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveriesRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveriesRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveriesRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -50,7 +50,7 @@
    {      
    }
    
-   public SessionCancelDeliveriesRequest(int objectId,
+   public SessionCancelDeliveriesRequest(String objectId,
                                          byte version,
                                          List cancels)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveryRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveryRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionCancelDeliveryRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -47,7 +47,7 @@
    {      
    }
    
-   public SessionCancelDeliveryRequest(int objectId,
+   public SessionCancelDeliveryRequest(String objectId,
                                        byte version,
                                        Cancel cancel)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionCreateBrowserDelegateRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionCreateBrowserDelegateRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionCreateBrowserDelegateRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -49,7 +49,7 @@
    {      
    }
    
-   public SessionCreateBrowserDelegateRequest(int objectId,
+   public SessionCreateBrowserDelegateRequest(String objectId,
                                                byte version,
                                                JBossDestination destination,
                                                String selector)

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionCreateConsumerDelegateRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionCreateConsumerDelegateRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionCreateConsumerDelegateRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -53,7 +53,7 @@
    {      
    }
    
-   public SessionCreateConsumerDelegateRequest(int objectId,
+   public SessionCreateConsumerDelegateRequest(String objectId,
                                                byte version,
                                                JBossDestination destination,
                                                String selector, boolean noLocal,

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionCreateQueueRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionCreateQueueRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionCreateQueueRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -45,7 +45,7 @@
    {      
    }
    
-   public SessionCreateQueueRequest(int objectId,
+   public SessionCreateQueueRequest(String objectId,
                                     byte version,
                                     String queueName)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionCreateTopicRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionCreateTopicRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionCreateTopicRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -45,7 +45,7 @@
    {      
    }
    
-   public SessionCreateTopicRequest(int objectId,
+   public SessionCreateTopicRequest(String objectId,
                                     byte version,
                                     String topicName)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionDeleteTemporaryDestinationRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionDeleteTemporaryDestinationRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionDeleteTemporaryDestinationRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -46,7 +46,7 @@
    {      
    }
    
-   public SessionDeleteTemporaryDestinationRequest(int objectId,
+   public SessionDeleteTemporaryDestinationRequest(String objectId,
                                        byte version,
                                        JBossDestination dest)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionRecoverDeliveriesRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionRecoverDeliveriesRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionRecoverDeliveriesRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -49,7 +49,7 @@
    {      
    }
    
-   public SessionRecoverDeliveriesRequest(int objectId,
+   public SessionRecoverDeliveriesRequest(String objectId,
                                           byte version,
                                           List dels)
    {

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionSendRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionSendRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionSendRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -49,7 +49,7 @@
    {      
    }
    
-   public SessionSendRequest(int objectId,
+   public SessionSendRequest(String objectId,
                              byte version,
                              JBossMessage msg,
                              boolean checkForDuplicates)

Modified: trunk/src/main/org/jboss/jms/wireformat/SessionUnsubscribeRequest.java
===================================================================
--- trunk/src/main/org/jboss/jms/wireformat/SessionUnsubscribeRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/jms/wireformat/SessionUnsubscribeRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -45,7 +45,7 @@
    {      
    }
    
-   public SessionUnsubscribeRequest(int objectId,
+   public SessionUnsubscribeRequest(String objectId,
                                     byte version,
                                     String subName)
    {

Deleted: trunk/src/main/org/jboss/messaging/core/contract/FailoverMapper.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/FailoverMapper.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/contract/FailoverMapper.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -1,44 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.messaging.core.contract;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A FailoverMapper
- * 
- * Determines the mapping between a set of nodes and their failover nodes
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1917 $</tt>
- *
- * $Id: FailoverMapper.java 1917 2007-01-08 20:26:12Z clebert.suconic at jboss.com $
- *
- */
-public interface FailoverMapper
-{
-   /**
-    * @param nodes Set<Integer>.
-    */
-   Map generateMapping(Set nodes);
-}

Modified: trunk/src/main/org/jboss/messaging/core/contract/MessageReference.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/MessageReference.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/contract/MessageReference.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -60,8 +60,5 @@
     */
    int getDeliveryCount();
    
-   void setDeliveryCount(int deliveryCount);
-   
-   
-
+   void setDeliveryCount(int deliveryCount);     
 }

Modified: trunk/src/main/org/jboss/messaging/core/contract/PostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/PostOffice.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/contract/PostOffice.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -140,4 +140,12 @@
     * @return
     */
    Set nodeIDView();
+   
+   //FIXME - these do not belong here - only here temporarily until we implement generic Handler/Message abstraction
+   
+   void sendReplicateDeliveryMessage(String queueName, String sessionID, long messageID, long deliveryID, boolean reply, boolean sync)
+   	throws Exception;
+
+	void sendReplicateAckMessage(String queueName, long messageID) throws Exception;
 }
+

Modified: trunk/src/main/org/jboss/messaging/core/contract/Queue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/Queue.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/contract/Queue.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,6 +21,8 @@
  */
 package org.jboss.messaging.core.contract;
 
+import java.util.Set;
+
 import org.jboss.messaging.core.impl.clusterconnection.MessageSucker;
 
 
@@ -42,7 +44,7 @@
     * over to another node, but a queue with the same name already exists. In this case we merge the
     * two queues.
     */
-   void mergeIn(long channelID) throws Exception;
+   void mergeIn(long channelID, int nodeID) throws Exception;
    
    /* 
     * TODO - this method does not really belong here - the only reason it is, is because we create the 
@@ -62,6 +64,8 @@
    
    int getNodeID();
    
+   long getRecoverDeliveriesTimeout();
+   
    Distributor getLocalDistributor();
    
    Distributor getRemoteDistributor();   
@@ -69,4 +73,12 @@
    void registerSucker(MessageSucker sucker);
    
    boolean unregisterSucker(MessageSucker sucker);
+   
+   void addToRecoveryArea(int nodeID, long messageID);
+   
+   void removeFromRecoveryArea(int nodeID, long messageID);
+   
+   void removeAllFromRecoveryArea(int nodeID);
+   
+   void addAllToRecoveryArea(int nodeID, Set ids);
 }

Modified: trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -366,53 +366,8 @@
       {
          return active;         
       }
-   }
+   }   
    
-   public List recoverDeliveries(List messageIds)
-   {
-      //debug
-      Iterator iter = messageIds.iterator();
-                  
-      List dels = new ArrayList();
-
-      synchronized (lock)
-      {
-         ListIterator liter = messageRefs.iterator();
-                           
-         while (iter.hasNext())
-         {
-            Long id = (Long)iter.next();
-            
-            //Scan the queue
-            while (true)
-            {               
-               if (!liter.hasNext())
-               {
-                  // TODO we need to look in paging state too - currently not supported
-                  //http://jira.jboss.com/jira/browse/JBMESSAGING-839
-                  log.warn(this + " cannot find reference " + id + " (Might be paged!)");
-                  break;
-               }
-
-               MessageReference ref = (MessageReference)liter.next();
-               
-               if (ref.getMessage().getMessageID() == id.longValue())
-               {
-                  liter.remove();
-                  
-                  Delivery del = new SimpleDelivery(this, ref);
-                  
-                  dels.add(del);
-                                 
-                  break;
-               }
-            }
-         }           
-      }
-            
-      return dels;
-   }
-   
    public int getMaxSize()
    {
       synchronized (lock)

Modified: trunk/src/main/org/jboss/messaging/core/impl/MessagingQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/MessagingQueue.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/MessagingQueue.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -21,15 +21,23 @@
   */
 package org.jboss.messaging.core.impl;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import org.jboss.jms.server.MessagingTimeoutFactory;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.Delivery;
 import org.jboss.messaging.core.contract.DeliveryObserver;
 import org.jboss.messaging.core.contract.Distributor;
 import org.jboss.messaging.core.contract.Filter;
+import org.jboss.messaging.core.contract.Message;
 import org.jboss.messaging.core.contract.MessageReference;
 import org.jboss.messaging.core.contract.MessageStore;
 import org.jboss.messaging.core.contract.PersistenceManager;
@@ -37,7 +45,12 @@
 import org.jboss.messaging.core.contract.Receiver;
 import org.jboss.messaging.core.impl.clusterconnection.MessageSucker;
 import org.jboss.messaging.core.impl.tx.Transaction;
+import org.jboss.messaging.util.ConcurrentHashSet;
+import org.jboss.util.timeout.Timeout;
+import org.jboss.util.timeout.TimeoutTarget;
 
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
+
 /**
  * 
  * A MessagingQueue
@@ -58,7 +71,9 @@
    // Static --------------------------------------------------------
 	
 	private static final Logger log = Logger.getLogger(MessagingQueue.class);
-      
+	
+   private static final long DEFAULT_RECOVER_DELIVERIES_TIMEOUT = 5 * 60 * 10000;
+         
    // Attributes ----------------------------------------------------
    
    private int nodeID;
@@ -79,18 +94,25 @@
    
    private boolean handleFlowControlForConsumers;
    
+   private Map recoveryArea;
+   
+   private Map recoveryMap;
+   
+   private long recoverDeliveriesTimeout;
+   
    // Constructors --------------------------------------------------
        
    public MessagingQueue(int nodeID, String name, long id, MessageStore ms, PersistenceManager pm,             
                          boolean recoverable, int maxSize, Filter filter,
-                         int fullSize, int pageSize, int downCacheSize, boolean clustered)
+                         int fullSize, int pageSize, int downCacheSize, boolean clustered,
+                         long recoverDeliveriesTimeout)
    {
       super(id, ms, pm, recoverable, maxSize, fullSize, pageSize, downCacheSize);
             
-      setup(nodeID, name, filter, clustered);
+      setup(nodeID, name, filter, clustered, recoverDeliveriesTimeout);
    }
    
-   /** This constructor is used when loading queue from storage - the paging params, maxSize and preserveOrdering don't matter
+   /** This constructor is used when loading queue from storage - the paging params, maxSize and recoverDeliveriesTimeout don't matter
     * they are injected when the queue or topic service is started
     */
    public MessagingQueue(int nodeID, String name, long id, MessageStore ms, PersistenceManager pm,             
@@ -99,7 +121,7 @@
 	{
 		super(id, ms, pm, recoverable, -1, 100000, 2000, 2000); //paging params etc are actually ignored
 		
-		setup(nodeID, name, filter, clustered);
+		setup(nodeID, name, filter, clustered, DEFAULT_RECOVER_DELIVERIES_TIMEOUT);
 	}
    
    /* This constructor is only used in tests - should we remove it? */
@@ -108,7 +130,7 @@
    {
    	super(id, ms, pm, recoverable, maxSize);
 
-   	setup(nodeID, name, filter, clustered);
+   	setup(nodeID, name, filter, clustered, DEFAULT_RECOVER_DELIVERIES_TIMEOUT);
    }
    
    /* Constructor for a remote queue representation in a cluster */
@@ -117,10 +139,10 @@
    {
    	super(id, null, null, recoverable, -1);
    	
-   	setup(nodeID, name, filter, clustered);   	
+   	setup(nodeID, name, filter, clustered, DEFAULT_RECOVER_DELIVERIES_TIMEOUT);   	
    }
    
-   private void setup(int nodeID, String name, Filter filter, boolean clustered)
+   private void setup(int nodeID, String name, Filter filter, boolean clustered, long recoverDeliveriesTimeout)
    {
    	this.nodeID = nodeID;
 
@@ -130,6 +152,8 @@
 
    	this.clustered = clustered;
    	
+   	this.recoverDeliveriesTimeout = recoverDeliveriesTimeout;
+   	
    	localDistributor = new DistributorWrapper(new RoundRobinDistributor());
    	
    	remoteDistributor = new DistributorWrapper(new RoundRobinDistributor());
@@ -137,6 +161,10 @@
    	distributor = new ClusterRoundRobinDistributor(localDistributor, remoteDistributor);
    	
    	suckers = new HashSet();
+   	
+   	recoveryArea = new ConcurrentReaderHashMap();
+   	
+   	recoveryMap = Collections.synchronizedMap(new LinkedHashMap());
    }
    
    // Queue implementation
@@ -177,9 +205,9 @@
     * over to another node, but a queue with the same name already exists. In this case we merge the
     * two queues.
     */
-   public void mergeIn(long theChannelID) throws Exception
+   public void mergeIn(long theChannelID, int nodeID) throws Exception
    {
-      if (trace) { log.trace("Merging queue " + channelID + " into " + this); }
+      if (trace) { log.trace("Merging queue " + channelID + " node id " + nodeID + " into " + this); }
            
       synchronized (lock)
       {
@@ -193,10 +221,82 @@
 
          doLoad(ili);         
          
+         Set toRecover = (Set)this.recoveryArea.remove(new Integer(nodeID));
+         
+         LinkedList toTimeout = new LinkedList();
+         
+         if (toRecover != null)
+         {         	
+            //TODO this can be optimised to avoid a second scan
+         
+         	if (trace) { log.trace("Recovery area is not empty, putting refs in recovery map"); }
+         	
+         	Iterator iter = messageRefs.iterator();
+         	
+         	while (iter.hasNext())
+         	{
+         		MessageReference ref = (MessageReference)iter.next();
+         		
+         		Message message = ref.getMessage();
+         		
+         		boolean exists = toRecover.remove(new Long(message.getMessageID()));
+         		
+         		if (exists)
+         		{
+         			if (trace) { log.trace("Added ref " + ref + " to recovery map"); }
+         			
+         			recoveryMap.put(new Long(message.getMessageID()), ref);
+         			
+         			iter.remove();
+         			
+         			toTimeout.addLast(ref);
+         		}
+         	}
+         	         	
+         	//Note!
+      		//It is possible there are message ids in the toRecover that are not in the queue
+      		//This can happen if a delivery is replicated, the message delivered, then acked, then the node crashes
+      		//before the ack is replicated.      		
+      		//This is ok
+         	
+         	
+         	//Set up a timeout to put the refs back in the queue if they don't get claimed by failed over consumers
+         	         	                   
+            MessagingTimeoutFactory.instance.getFactory().
+            	schedule(System.currentTimeMillis() + recoverDeliveriesTimeout, new ClearRecoveryMapTimeoutTarget(toTimeout));       
+            
+            if (trace) { log.trace("Set timeout to fire in " + recoverDeliveriesTimeout); }
+         }
+                           
          deliverInternal();
       }
+   }  
+   
+   public List recoverDeliveries(List messageIds)
+   {
+   	List refs = new ArrayList();
+   	
+   	Iterator iter = messageIds.iterator();
+   	
+   	while (iter.hasNext())
+   	{
+   		Long messageID = (Long)iter.next();
+   		
+   		MessageReference ref = (MessageReference)recoveryMap.get(messageID);
+   		
+   		if (ref == null)
+   		{
+   			throw new IllegalStateException("Cannot find ref in recovery map " + messageID);
+   		}
+   		
+   		Delivery del = new SimpleDelivery(this, ref);
+   		
+   		refs.add(del);
+   	}
+            
+      return refs;
    }
-   
+
    public void registerSucker(MessageSucker sucker)
    {
    	if (trace) { log.trace(this + " Registering sucker " + sucker); }
@@ -249,6 +349,85 @@
    	return downCacheSize;
    }
    
+   public void addToRecoveryArea(int nodeID, long messageID)
+   {
+   	if (trace) { log.trace("Adding message id " + messageID + " to recovery area from node " + nodeID); }
+   	
+   	//Note. The add might find the id already there
+      //This could happen after the failover node has moved
+   	//When the batch add happens, then an add comes in shortly after but has already been taken into account
+   	
+   	Integer nid = new Integer(nodeID);
+   	
+   	Set ids = (Set)recoveryArea.get(nid);
+   	
+   	if (ids == null)
+   	{
+   		ids = new ConcurrentHashSet();
+   		
+   		recoveryArea.put(nid, ids);
+   	}
+   	
+   	ids.add(new Long(messageID));
+   }
+   
+   public void removeFromRecoveryArea(int nodeID, long messageID)
+   {
+   	if (trace) { log.trace("Removing message id " + messageID + " to recovery area from node " + nodeID); }
+   	
+   	Integer nid = new Integer(nodeID);
+   	
+   	Set ids = (Set)recoveryArea.get(nid);
+   	
+   	//The remove might fail to find the id
+      //This can happen if the removal has already be done - this could happen after the failover node has moved
+   	//When the batch add happens, then an ack comes in shortly after but has already been taken into account
+
+   	if (ids != null && ids.remove(new Long(messageID)))
+   	{
+   		if (ids.isEmpty())
+      	{
+      		recoveryArea.remove(nid);
+      	}
+   	}
+   }
+   
+   public void removeAllFromRecoveryArea(int nodeID)
+   {
+   	if (trace) { log.trace("Removing all from recovery area for node " + nodeID); }
+   	
+   	boolean removed = recoveryArea.remove(new Integer(nodeID)) != null;
+   		
+   	if (trace) { log.trace("Removed:" + removed); }
+   }
+   
+   public void addAllToRecoveryArea(int nodeID, Set ids)
+   {
+   	if (trace) { log.trace("Adding all from recovery area for node " + nodeID +" set " + ids); }
+   	
+   	Integer nid = new Integer(nodeID);
+   	
+   	//Sanity check
+   	if (recoveryArea.get(nid) != null)
+   	{
+   		throw new IllegalStateException("There are already message ids for node " + nodeID);
+   	}
+   	   	
+   	if (!(ids instanceof ConcurrentHashSet))
+   	{
+   		ids = new ConcurrentHashSet(ids);
+   	}
+   	
+   	recoveryArea.put(nid, ids);
+   	
+   	if (trace) { log.trace("Added"); }
+   }
+   
+   public long getRecoverDeliveriesTimeout()
+   {
+   	return recoverDeliveriesTimeout;
+   }
+   
    // ChannelSupport overrides --------------------------------------
    
    protected void deliverInternal()
@@ -405,4 +584,37 @@
 	   	}
 		}   	
    }
+   
+   private class ClearRecoveryMapTimeoutTarget implements TimeoutTarget
+   {
+   	private List ids;
+   	
+   	ClearRecoveryMapTimeoutTarget(List ids)
+   	{
+   		this.ids = ids;
+   	}
+   	
+		public void timedOut(Timeout timeout)
+		{
+			if (trace) { log.trace("ClearRecoveryMap timeout fired"); }
+			
+			Iterator iter = ids.iterator();
+			
+			while (iter.hasNext())
+			{
+				MessageReference ref = (MessageReference)iter.next();
+				
+				Object obj = recoveryMap.remove(new Long(ref.getMessage().getMessageID()));
+				
+				if (obj != null)
+				{
+					if (trace) { log.trace("Adding ref " + ref + " back into queue"); }
+					
+					messageRefs.addFirst(ref, ref.getMessage().getPriority());					
+					
+					deliverInternal();
+				}
+			}
+		}   	
+   }
 }

Modified: trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -86,7 +86,8 @@
 		return "MessageSucker:" + System.identityHashCode(this) + " queue:" + localQueue.getName();
 	}
 			
-	MessageSucker(Queue localQueue, JBossConnection sourceConnection, JBossConnection localConnection, boolean xa, boolean preserveOrdering)
+	MessageSucker(Queue localQueue, JBossConnection sourceConnection, JBossConnection localConnection,
+			        boolean xa, boolean preserveOrdering)
 	{	
 		this.localQueue = localQueue;
 		
@@ -236,6 +237,19 @@
 		
 		if (trace) { log.trace(this + " sucked message " + msg); }
 		
+//		org.jboss.messaging.core.contract.Message m = ((MessageProxy)msg).getMessage();
+//		
+//		String hdr = (String)m.getHeader("eeek");
+//				
+//		if (hdr == null)
+//		{
+//			hdr = "";
+//		}
+//		
+//		hdr = hdr + "-sucked";
+//		
+//		m.putHeader("eeek", hdr);
+		
 		try
 		{
 			boolean startTx = xa && msg.getJMSDeliveryMode() == DeliveryMode.PERSISTENT;

Added: trunk/src/main/org/jboss/messaging/core/impl/postoffice/AckAllReplicatedDeliveriesMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/AckAllReplicatedDeliveriesMessage.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/AckAllReplicatedDeliveriesMessage.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.impl.postoffice;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>6 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class AckAllReplicatedDeliveriesMessage extends ClusterRequest
+{
+	private int nodeID;
+	
+	public AckAllReplicatedDeliveriesMessage()
+	{		
+	}
+	
+	public AckAllReplicatedDeliveriesMessage(int nodeID)
+	{
+		this.nodeID = nodeID;
+	}
+		
+	Object execute(RequestTarget office) throws Throwable
+	{		
+		office.handleAckAllReplicatedDeliveries(nodeID);
+		
+		return "ok";
+	}
+
+	byte getType()
+	{
+		return ClusterRequest.ACK_ALL_REPLICATED_DELIVERIES_REQUEST;
+	}
+
+	public void read(DataInputStream in) throws Exception
+	{
+		nodeID = in.readInt();
+	}
+
+	public void write(DataOutputStream out) throws Exception
+	{		
+		out.writeInt(nodeID);
+	}
+
+}

Added: trunk/src/main/org/jboss/messaging/core/impl/postoffice/AddAllReplicatedDeliveriesMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/AddAllReplicatedDeliveriesMessage.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/AddAllReplicatedDeliveriesMessage.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.impl.postoffice;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.messaging.util.ConcurrentHashSet;
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>6 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class AddAllReplicatedDeliveriesMessage extends ClusterRequest
+{
+	private int nodeID;
+	
+	private Map deliveries;
+	
+	public AddAllReplicatedDeliveriesMessage()
+	{		
+	}
+	
+	public AddAllReplicatedDeliveriesMessage(int nodeID, Map deliveries)
+	{
+		this.nodeID = nodeID;
+		
+		this.deliveries = deliveries;		
+	}
+		
+	Object execute(RequestTarget office) throws Throwable
+	{		
+		office.handleAddAllReplicatedDeliveries(deliveries, nodeID);
+		
+		return "ok";
+	}
+
+	byte getType()
+	{
+		return ClusterRequest.ADD_ALL_REPLICATED_DELIVERIES_REQUEST;
+	}
+
+	public void read(DataInputStream in) throws Exception
+	{
+		nodeID = in.readInt();
+		
+		int size = in.readInt();
+		
+		deliveries = new HashMap(size);
+		
+		for (int i = 0; i < size; i++)
+		{
+			String queueName = in.readUTF();
+			
+			int size2 = in.readInt();
+			
+			Set ids = new ConcurrentHashSet(size2);
+			
+			for (int j = 0; j < size2; j++)
+			{
+				long id = in.readLong();
+				
+				ids.add(new Long(id));
+			}
+			
+			deliveries.put(queueName, ids);
+		}
+	}
+
+	public void write(DataOutputStream out) throws Exception
+	{		
+		out.writeInt(nodeID);
+		
+		out.writeInt(deliveries.size());
+		
+		Iterator iter = deliveries.entrySet().iterator();
+		
+		while (iter.hasNext())
+		{
+			Map.Entry entry = (Map.Entry)iter.next();
+			
+			String queueName = (String)entry.getKey();
+			
+			out.writeUTF(queueName);
+			
+			Set ids = (Set)entry.getValue();
+			
+			out.writeInt(ids.size());
+			
+			Iterator iter2 = ids.iterator();
+			
+			while (iter2.hasNext())
+			{
+				Long id = (Long)iter2.next();
+				
+				out.writeLong(id.longValue());
+			}
+		}
+	}
+
+}

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/ClusterRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/ClusterRequest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/ClusterRequest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -51,6 +51,18 @@
 	public static final int PUT_REPLICANT_REQUEST = 6;
 	
 	public static final int REMOVE_REPLICANT_REQUEST = 7;
+	
+	//TODO - these don't really belong here
+	
+	public static final int REPLICATE_DELIVERY_REQUEST = 8;
+	
+	public static final int REPLICATE_DELIVERY_ACK_REQUEST = 9;
+	
+	public static final int REPLICATE_ACK_REQUEST = 10;
+	
+	public static final int ACK_ALL_REPLICATED_DELIVERIES_REQUEST = 11;
+	
+	public static final int ADD_ALL_REPLICATED_DELIVERIES_REQUEST = 12;
 		
 	
    /*
@@ -94,11 +106,37 @@
             request = new PutReplicantRequest();
             break;
          }
+         //TODO move this out
          case REMOVE_REPLICANT_REQUEST:
          {
             request = new RemoveReplicantRequest();
             break;
          }
+         case REPLICATE_DELIVERY_REQUEST:
+         {
+         	request = new ReplicateDeliveryMessage();
+         	break;
+         }
+         case REPLICATE_DELIVERY_ACK_REQUEST:
+         {
+         	request = new ReplicateDeliveryAckMessage();
+         	break;
+         }
+         case REPLICATE_ACK_REQUEST:
+         {
+         	request = new ReplicateAckMessage();
+         	break;
+         }
+         case ACK_ALL_REPLICATED_DELIVERIES_REQUEST:
+         {
+         	request = new AckAllReplicatedDeliveriesMessage();
+         	break;
+         }
+         case ADD_ALL_REPLICATED_DELIVERIES_REQUEST:
+         {
+         	request = new AddAllReplicatedDeliveriesMessage();
+         	break;
+         }
          default:
          {
             throw new IllegalArgumentException("Invalid type: " + type);

Deleted: trunk/src/main/org/jboss/messaging/core/impl/postoffice/DefaultFailoverMapper.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/DefaultFailoverMapper.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/DefaultFailoverMapper.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -1,78 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.messaging.core.impl.postoffice;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.messaging.core.contract.FailoverMapper;
-
-
-/**
- * A DefaultFailoverMapper
- * 
- * Generates the mapping by looking to the element to the right and wrapping around to the first
- * element in the list
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 2681 $</tt>
- *
- * $Id: DefaultFailoverMapper.java 2681 2007-05-15 00:09:10Z timfox $
- *
- */
-public class DefaultFailoverMapper implements FailoverMapper
-{
-   /**
-    * Generate a mapping given a set of nodes - nodes will be sorted by the method.
-    *
-    * @see org.jboss.messaging.core.contract.FailoverMapper#generateMapping(java.util.Set)
-    */
-   public Map generateMapping(Set nodes)
-   {
-      Integer[] nodesArr = (Integer[])nodes.toArray(new Integer[nodes.size()]);
-      
-      // First sort them so every node has a consistent view
-      Arrays.sort(nodesArr);
-      
-      int s = nodes.size();
-      
-      // There is no need for the map to be linked
-      Map failoverNodes = new HashMap(s);
-      
-      for (int i = 0; i < s; i++)
-      {
-         int j = i + 1;
-         
-         if (j == s)
-         {
-            j = 0;
-         }
-         
-         failoverNodes.put(nodesArr[i], nodesArr[j]);
-      }
-
-      return failoverNodes;
-   }
-
-}

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -25,12 +25,10 @@
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
-import java.util.Collection;
 import java.util.Iterator;
 
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.JChannelFactory;
-import org.jboss.messaging.util.Future;
 import org.jgroups.Address;
 import org.jgroups.Channel;
 import org.jgroups.MembershipListener;
@@ -83,7 +81,7 @@
    
    private MessageDispatcher dispatcher;
    
-   private View currentView;
+   private volatile View currentView;
    
    private QueuedExecutor viewExecutor;
    
@@ -138,10 +136,6 @@
 	      
 	      dispatcher = new MessageDispatcher(controlChannel, messageListener, membershipListener, requestHandler, true);
 	      	      
-	      //Receiver controlReceiver = new ControlReceiver();
-	      
-	      //controlChannel.setReceiver(controlReceiver);
-	      	      
 	      Receiver dataReceiver = new DataReceiver();
 	      
 	      dataChannel.setReceiver(dataReceiver);
@@ -213,6 +207,11 @@
    	return castTimeout;
    }
    
+   public View getCurrentView()
+   {
+   	return currentView;
+   }
+   
    public void multicastControl(ClusterRequest request, boolean sync) throws Exception
    {
    	lock.readLock().acquire();
@@ -223,32 +222,11 @@
 	   	{   		
 		   	if (trace) { log.trace(this + " multicasting " + request + " to control channel, sync=" + sync); }
 		
-		      byte[] bytes = writeRequest(request);
-		      
-		      controlChannel.send(new Message(null, null, bytes));
-		   	
 		   	Message message = new Message(null, null, writeRequest(request));
 
 		   	RspList rspList =
 		   		dispatcher.castMessage(null, message, sync ? GroupRequest.GET_ALL: GroupRequest.GET_NONE, castTimeout);	
 		   	
-//		   	Future future = new Future();
-//		   	
-//		   	new Thread(new CastRunner(request, sync, future)).start();
-//		   	
-//		   	Object result = future.getResult();
-//		   	
-//		   	if (result instanceof Exception)
-//		   	{
-//		   		throw (Exception)result;
-//		   	}
-//		   	else if (result instanceof Error)
-//		   	{
-//		   		throw (Error)result;
-//		   	}
-//		   	
-//		   	RspList list = (RspList)result;
-		   			   	
 		   	if (sync)
 		   	{			   	
 			   	Iterator iter = rspList.values().iterator();
@@ -271,40 +249,31 @@
    	}
    }
    
-//   class CastRunner implements Runnable
-//   {
-//   	private ClusterRequest request;
-//   	
-//   	private boolean sync;
-//   	
-//   	private Future future;
-//   	
-//   	CastRunner(ClusterRequest request, boolean sync, Future future)
-//   	{
-//   		this.request = request;
-//   		
-//   		this.sync = sync;
-//   		
-//   		this.future = future;
-//   	}
-//   	
-//   	public void run()
-//   	{
-//   		try
-//   		{
-//	   		Message message = new Message(null, null, writeRequest(request));
-//	
-//		   	RspList rspList =
-//		   		dispatcher.castMessage(null, message, sync ? GroupRequest.GET_ALL: GroupRequest.GET_NONE, castTimeout);
-//		   	
-//		   	future.setResult(rspList);
-//   		}
-//   		catch (Throwable t)
-//   		{
-//   			future.setException(t);
-//   		}
-//   	}
-//   }
+   public void unicastControl(ClusterRequest request, Address address, boolean sync) throws Exception
+   {
+   	lock.readLock().acquire();
+   	
+   	try
+   	{   	
+	   	if (started)
+	   	{   		
+		   	if (trace) { log.trace(this + " multicasting " + request + " to control channel, sync=" + sync); }
+		
+		   	Message message = new Message(address, null, writeRequest(request));
+
+		   	String ret = (String)dispatcher.sendMessage(message, sync ? GroupRequest.GET_ALL: GroupRequest.GET_NONE, castTimeout);
+		   				   	
+		   	if (sync && !"ok".equals(ret))
+		   	{			   				   	
+		   		throw new IllegalStateException("Invalid response received " + ret);		   				   				   			   		
+		   	}
+	   	}
+   	}
+   	finally
+   	{
+   		lock.readLock().release();
+   	}
+   }
    
    public void multicastData(ClusterRequest request) throws Exception
    {
@@ -348,48 +317,6 @@
    	}
    }
    
-//   public void sendSyncRequest(ClusterRequest request) throws Exception
-//   {
-//   	lock.readLock().acquire();
-//   	
-//   	try
-//   	{
-//	   	if (started)
-//	   	{
-//		   	if (trace) { log.trace(this + " Sending sync request " + request); }
-//		   	
-//		   	Message message = new Message(null, null, writeRequest(request));
-//		
-//		      RspList rspList = dispatcher.castMessage(null, message, GroupRequest.GET_ALL, castTimeout);		      		      
-//	   	}
-//   	}
-//   	finally
-//   	{
-//   		lock.readLock().release();
-//   	}
-//   }
-//   
-//   //These methods need renaming
-//   public void sendAsyncRequest(ClusterRequest request) throws Exception
-//   {
-//   	lock.readLock().acquire();
-//   	
-//   	try
-//   	{
-//	   	if (started)
-//	   	{
-//		   	if (trace) { log.trace(this + " Sending async request " + request); }
-//		   	
-//		   	byte[] bytes = writeRequest(request);
-//		      
-//		      controlChannel.send(new Message(null, null, bytes));
-//	   	}
-//   	}
-//   	finally
-//   	{
-//   		lock.readLock().release();
-//   	}
-//   }
       
    public boolean getState() throws Exception
    {
@@ -628,146 +555,6 @@
       }
    }
    
-//   private class ControlReceiver implements Receiver
-//   {
-//      public void block()
-//      {
-//         //NOOP
-//      }
-//
-//      public void suspect(Address address)
-//      {
-//         //NOOP
-//      }
-//
-//      public void viewAccepted(View newView)
-//      {
-//      	try
-//         {
-//         	lock.readLock().acquire();
-//         	         	
-//         	try
-//         	{	    
-//            	if (!started)
-//            	{
-//            		//Ignore any views received after stopped
-//            		return;
-//            	}
-//         		
-//	            // We queue up changes and execute them asynchronously.
-//	            // This is because JGroups will not let us do stuff like send synch messages using the
-//	            // same thread that delivered the view change and this is what we need to do in
-//	            // failover, for example.
-//	
-//	            viewExecutor.execute(new HandleViewAcceptedRunnable(newView));
-//         	}
-//         	finally
-//         	{
-//         		lock.readLock().release();
-//         	}
-//         }
-//         catch (InterruptedException e)
-//         {
-//            log.warn("Caught InterruptedException", e);
-//         }
-//      }
-//
-//      public byte[] getState()
-//      {
-//      	log.info("*** getting state");
-//      	
-//         try
-//         {
-//	      	lock.readLock().acquire();
-//	      		      
-//	      	try
-//	      	{	      	
-//		      	if (!started)
-//		      	{
-//		      		//Ignore if received after stopped
-//		      		
-//		      		return null;
-//		      	}
-//	      		
-//		         if (trace) { log.trace(this + ".ControlMessageListener got state"); }		         
-//	
-//		         byte[] state = groupListener.getState();
-//		         
-//		         log.info("**** got state " + state);
-//		         	
-//		         return state;		        
-//	      	}
-//	      	finally
-//	      	{
-//	      		lock.readLock().release();
-//	      	}
-//      	}
-//         catch (Exception e)
-//         {
-//         	log.error("Failed to get state", e);
-//         	
-//         	return null;
-//         }
-//      }
-//
-//      public void receive(Message message)
-//      {
-//         if (trace) { log.trace(this + " received " + message + " on the ASYNC channel"); }
-//
-//         try
-//         {
-//         	lock.readLock().acquire();
-//         	
-//         	try
-//         	{
-//         		if (!started)
-//         		{
-//         			//Ignore messages received when not started
-//         			
-//         			return;
-//         		}
-//         		
-//	            byte[] bytes = message.getBuffer();
-//	
-//	            ClusterRequest request = readRequest(bytes);
-//	            
-//	            request.execute(requestTarget);
-//         	}
-//         	finally
-//         	{
-//         		lock.readLock().release();
-//         	}
-//         }
-//         catch (Throwable e)
-//         {
-//            log.error("Caught Exception in Receiver", e);
-//            IllegalStateException e2 = new IllegalStateException(e.getMessage());
-//            e2.setStackTrace(e.getStackTrace());
-//            throw e2;
-//         }
-//      }
-//
-//      public void setState(byte[] bytes)
-//      {
-//      	log.info("************* setting state");
-//         synchronized (setStateLock)
-//         {
-//         	try
-//         	{
-//         		groupListener.setState(bytes);
-//         		log.info("* set it");
-//         	}
-//         	catch (Exception e)
-//         	{
-//         		log.error("Failed to set state", e);
-//         	}
-//         	
-//         	started = true;
-//         	
-//            setStateLock.notify();
-//         }
-//      }
-//   }
 
    /*
     * This class is used to handle control channel requests

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/MappingInfo.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/MappingInfo.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/MappingInfo.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -66,6 +66,8 @@
    
    private boolean allNodes;
    
+   private long recoverDeliveriesTimeout;
+   
    MappingInfo()
    {      
    }
@@ -93,7 +95,7 @@
    MappingInfo(int nodeId, String queueName, String conditionText, String filterString,
    		      long channelId, boolean recoverable, boolean clustered, boolean allNodes,
    		      int fullSize, int pageSize, int downCacheSize,
-   		      int maxSize)
+   		      int maxSize, long recoverDeliveriesTimeout)
    {
    	this (nodeId, queueName, conditionText, filterString, channelId, recoverable, clustered, allNodes);
    	
@@ -104,6 +106,8 @@
    	this.downCacheSize = downCacheSize;
    	
    	this.maxSize = maxSize;
+   	
+   	this.recoverDeliveriesTimeout = recoverDeliveriesTimeout;
    }   
 	
 	// Streamable implementation ---------------------------------------------------------------------
@@ -133,6 +137,8 @@
       downCacheSize = in.readInt();
       
       maxSize = in.readInt();
+      
+      recoverDeliveriesTimeout = in.readLong();
    }
 
    public void write(DataOutputStream out) throws Exception
@@ -160,6 +166,8 @@
       out.writeInt(downCacheSize);
       
       out.writeInt(maxSize);
+      
+      out.writeLong(recoverDeliveriesTimeout);
    }
    
    int getNodeId()
@@ -221,5 +229,10 @@
    {
    	return maxSize;
    }
+   
+   long getRecoverDeliveriesTimeout()
+   {
+   	return recoverDeliveriesTimeout;
+   }
 
 }

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -37,6 +37,7 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.Vector;
 
 import javax.management.ListenerNotFoundException;
 import javax.management.MBeanNotificationInfo;
@@ -48,6 +49,8 @@
 import javax.transaction.TransactionManager;
 
 import org.jboss.jms.client.container.JMSClientVMIdentifier;
+import org.jboss.jms.server.ServerPeer;
+import org.jboss.jms.server.endpoint.ServerSessionEndpoint;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.Binding;
 import org.jboss.messaging.core.contract.ClusterNotification;
@@ -55,7 +58,6 @@
 import org.jboss.messaging.core.contract.Condition;
 import org.jboss.messaging.core.contract.ConditionFactory;
 import org.jboss.messaging.core.contract.Delivery;
-import org.jboss.messaging.core.contract.FailoverMapper;
 import org.jboss.messaging.core.contract.Filter;
 import org.jboss.messaging.core.contract.FilterFactory;
 import org.jboss.messaging.core.contract.JChannelFactory;
@@ -75,10 +77,14 @@
 import org.jboss.messaging.util.ConcurrentHashSet;
 import org.jboss.messaging.util.StreamUtils;
 import org.jgroups.Address;
+import org.jgroups.View;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
 import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;
+import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
 
 /**
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
@@ -188,8 +194,6 @@
 
    private Set leftSet;
 
-   private FailoverMapper failoverMapper;
-
    private NotificationBroadcasterSupport nbSupport;
    
    private IDManager channelIDManager;
@@ -204,7 +208,20 @@
    private Map loadedBindings;
 
    private boolean supportsFailover = true;
-
+   
+   //TODO - this does not belong here - it is only here so we can handle the session replication stuff
+   //we should abstract out the group member stuff and an abstract request handle message framework so any component can
+   //use it
+   private ServerPeer serverPeer;
+   
+   private PooledExecutor replyExecutor;
+   
+   private volatile int failoverNodeID = -1;
+   
+   private ReadWriteLock replicateDeliveryLock;
+   
+   private volatile boolean firstNode;
+   
    // Constructors ---------------------------------------------------------------------------------
 
    /*
@@ -249,6 +266,8 @@
 
       lock = new ReentrantWriterPreferenceReadWriteLock();
       
+      replicateDeliveryLock = new WriterPreferenceReadWriteLock();
+      
       waitForBindUnbindLock = new Object();
    }
    
@@ -271,15 +290,12 @@
                               String groupName,
                               JChannelFactory jChannelFactory,
                               long stateTimeout, long castTimeout,
-                              FailoverMapper failoverMapper,
                               boolean supportsFailover)
       throws Exception
    {
    	this(ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms, pm, tr,
    		  filterFactory, conditionFactory, channelIDManager, clusterNotifier);
      
-      this.failoverMapper = failoverMapper;
-      
       this.clustered = true;
       
       groupMember = new GroupMember(groupName, stateTimeout, castTimeout, jChannelFactory, this, this);
@@ -315,7 +331,7 @@
 	      if (knowAboutNodeId(thisNodeID))
 	      {
 	      	throw new IllegalArgumentException("Cannot start post office since there is already a post office in the " +
-	      			"cluster with the same node id (" + this.thisNodeID + "). " +
+	      			"cluster with the same node id (" + thisNodeID + "). " +
 	      			"Are you sure you have given each node a unique node id during installation?");
 	      }
 	
@@ -480,7 +496,7 @@
    			{
    				Queue queue = (Queue)iter.next();
 
-   				if (!localOnly || (queue.getNodeID() == this.thisNodeID))
+   				if (!localOnly || (queue.getNodeID() == thisNodeID))
    				{
    					list.add(queue);
    				}
@@ -569,6 +585,64 @@
    	return new HashSet(nodeIDAddressMap.keySet());
    }
    
+   //TODO - these don't belong here
+    
+   public void sendReplicateDeliveryMessage(String queueName, String sessionID, long messageID, long deliveryID,
+   		                                   boolean reply, boolean sync)
+   	throws Exception
+   {
+   	//There is no need to lock this while failover node change is occuring since the receiving node is tolerant to duplicate
+		//adds or acks
+  	
+   	Address replyAddress = null;
+   	
+   	if (reply)
+   	{
+   		//TODO optimise this
+   		
+   		PostOfficeAddressInfo info = (PostOfficeAddressInfo)nodeIDAddressMap.get(new Integer(thisNodeID));
+   		
+   		replyAddress = info.getControlChannelAddress();
+   	}
+   	
+   	ClusterRequest request = new ReplicateDeliveryMessage(queueName, sessionID, messageID, deliveryID, replyAddress, thisNodeID);
+   	
+   	if (trace) { log.trace(this + " sending replicate delivery message " + queueName + " " + sessionID + " " + messageID); }
+   	
+   	if (!firstNode)
+	   {		   
+		   Address address = getFailoverNodeControlChannelAddress();
+		   	
+		   if (address != null)
+		   {	   
+		      groupMember.unicastControl(request, address, false);
+		   }
+	   }
+   }
+
+	public void sendReplicateAckMessage(String queueName, long messageID) throws Exception
+	{
+		//There is no need to lock this while failover node change is occuring since the receiving node is tolerant to duplicate
+		//adds or acks
+	
+	   ClusterRequest request = new ReplicateAckMessage(queueName, messageID, thisNodeID);
+	   
+	   if (!firstNode)
+	   {		   
+		   Address address = getFailoverNodeControlChannelAddress();
+		   	
+		   if (address != null)
+		   {	   
+		      groupMember.unicastControl(request, address, false);
+		   }
+	   }
+	}
+	
+	public void injectServerPeer(ServerPeer serverPeer)
+	{
+		this.serverPeer = serverPeer;
+	}
+   
    // GroupListener implementation -------------------------------------------------------------
  
    public void setState(byte[] bytes) throws Exception
@@ -618,7 +692,8 @@
 	      			      		
 	      		Queue queue2 = new MessagingQueue(thisNodeID, mapping.getQueueName(), channelID, ms, pm,
 	   			                                  mapping.isRecoverable(), mapping.getMaxSize(), filter,
-	   			                                  mapping.getFullSize(), mapping.getPageSize(), mapping.getDownCacheSize(), true);     
+	   			                                  mapping.getFullSize(), mapping.getPageSize(), mapping.getDownCacheSize(),
+	   			                                  true, mapping.getRecoverDeliveriesTimeout());     
 	      		
 	      		Binding localBinding = new Binding(condition, queue2, true);
 	      			         	
@@ -681,7 +756,7 @@
 		      			mapping = new MappingInfo(queue.getNodeID(), queue.getName(), binding.condition.toText(), filterString,
 		         		                          queue.getChannelID(), queue.isRecoverable(), true, true,
 									         		     queue.getFullSize(), queue.getPageSize(), queue.getDownCacheSize(),
-									         		     queue.getMaxSize());
+									         		     queue.getMaxSize(), queue.getRecoverDeliveriesTimeout());
 		      		}
 		      		else
 		      		{
@@ -737,44 +812,47 @@
          throw new IllegalStateException(this + " cannot find node ID for address " + address);
       }
 
-      boolean crashed = !this.leaveMessageReceived(leftNodeID);
+      boolean crashed = !leaveMessageReceived(leftNodeID);
 
       log.debug(this + ": node " + leftNodeID + " has " + (crashed ? "crashed" : "cleanly left the group"));
       
+      boolean doneFailover = false;
+      
       if (crashed && isSupportsFailover())
       {	      
-	      // Need to evaluate this before we regenerate the failover map
-	      Integer failoverNode;
+	      // Need to evaluate this before we regenerate the failover map	      
+	         
+	      Integer fnodeID = (Integer)failoverMap.get(leftNodeID);
 	      
-	      synchronized (failoverMap)
+	      log.debug(this + " the failover node for the crashed node is " + fnodeID);
+   	   
+	      
+	      if (fnodeID == null)
 	      {
-	      	failoverNode = (Integer)failoverMap.get(leftNodeID);
+	      	throw new IllegalStateException("Cannot find failover node for node " + leftNodeID);
 	      }
-	
-	      if (failoverNode == null)
-	      {
-	         throw new IllegalStateException(this + " cannot find failover node for node " + leftNodeID);
-	      }
 	      
-	      log.debug(this + " the failover node for the crashed node is " + failoverNode);
-		      
-	      if (thisNodeID == failoverNode.intValue())
+	      if (fnodeID.intValue() == thisNodeID)
 	      {
 	         // The node crashed and we are the failover node so let's perform failover
 	
 	         log.debug(this + ": I am the failover node for node " + leftNodeID + " that crashed");
 	
 	         performFailover(leftNodeID);
+	         
+	         doneFailover = true;
 	      }
       }
       
-      // Remove any replicant data and non durable bindings for the node - again we need to do
-      // this irrespective of whether we crashed. This will notify any listeners which will
-      // recalculate the connection factory delegates and failover delegates.
-
-      cleanDataForNode(leftNodeID);
+      if (!doneFailover)
+      {
+	      // Remove any replicant data and non durable bindings for the node -  This will notify any listeners which will
+	      // recalculate the connection factory delegates and failover delegates.
+	
+	      cleanDataForNode(leftNodeID);
+      }
       
-      this.sendJMXNotification(VIEW_CHANGED_NOTIFICATION);
+      sendJMXNotification(VIEW_CHANGED_NOTIFICATION);
    }
    
    // RequestTarget implementation ------------------------------------------------------------
@@ -824,7 +902,8 @@
    		
    		Queue queue2 = new MessagingQueue(thisNodeID, mapping.getQueueName(), channelID, ms, pm,
 			                                  mapping.isRecoverable(), mapping.getMaxSize(), filter,
-			                                  mapping.getFullSize(), mapping.getPageSize(), mapping.getDownCacheSize(), true);
+			                                  mapping.getFullSize(), mapping.getPageSize(), mapping.getDownCacheSize(), true,
+			                                  mapping.getRecoverDeliveriesTimeout());
 
    		//We must cast back asynchronously to avoid deadlock
    		boolean added = internalAddBinding(new Binding(condition, queue2, true), false, false);
@@ -893,17 +972,39 @@
    	
    	log.debug(this + " handleNodeJoined: " + nodeId + " size: " + nodeIDAddressMap.size());
    	   
+   	final int oldFailoverNodeID = this.failoverNodeID;
+   	
+   	boolean wasFirstNode = this.firstNode;
+   	
    	calculateFailoverMap();
+   	
+   	if (!wasFirstNode && oldFailoverNodeID != this.failoverNodeID)
+   	{
+   		//Need to execute this on it's own thread since it uses the MessageDispatcher
+   		
+   		new Thread(
+	   		new Runnable() { 
+	   			public void run()
+	   			{
+	   				try
+	   				{
+	   					failoverNodeChanged(oldFailoverNodeID);
+	   				}
+	   				catch (Exception e)
+	   				{
+	   					log.error("Failed to process failover node changed", e);
+	   				}
+	   			}
+	   		}).start();   		   		
+   	}
       
-      log.debug("Updated failover map:\n" + dumpFailoverMap(failoverMap));   	
-      
       // Send a notification
       
       ClusterNotification notification = new ClusterNotification(ClusterNotification.TYPE_NODE_JOIN, nodeId, null);
       
       clusterNotifier.sendNotification(notification);
       
-      this.sendJMXNotification(VIEW_CHANGED_NOTIFICATION);
+      sendJMXNotification(VIEW_CHANGED_NOTIFICATION);
    }
 
    /**
@@ -997,6 +1098,175 @@
          }
       }
    }
+      
+   //TODO - these do not belong here
+   
+   public void handleReplicateDelivery(String queueName, String sessionID, long messageID,
+   		                              long deliveryID, final Address replyAddress, int nodeID) throws Exception
+   {
+   	if (trace) { log.trace(this + " handleReplicateDelivery for queue " + queueName + " session " + sessionID + " message " + messageID); }
+   	
+   	Binding binding = getBindingForQueueName(queueName);
+   	
+   	if (binding == null)
+   	{
+   		throw new IllegalStateException("Cannot find queue with name " + queueName +" has it been deployed?");
+   	}
+   	
+   	Queue queue = binding.queue;
+   	
+   	queue.addToRecoveryArea(nodeID, messageID);   	
+   	
+   	if (trace) { log.trace(this + " reply address is " + replyAddress); }
+   	
+   	if (replyAddress != null)
+   	{   	
+	   	//Now we send back a response saying we have added it ok
+   		
+   		if (trace) { log.trace("Sending back response"); }
+	   	
+	   	final ClusterRequest request = new ReplicateDeliveryAckMessage(sessionID, deliveryID);
+	   		   		   	
+	   	//need to execute this on another thread
+	   	
+	   	replyExecutor.execute(
+		   	new Runnable()
+		   	{
+		   		public void run()
+		   		{
+		   			try
+		   			{
+		   				groupMember.unicastControl(request, replyAddress, false);
+		   			}
+		   			catch (Exception e)
+		   			{
+		   				log.error("Failed to cast message", e);
+		   			}
+		   		}
+		   	});	   		   	   
+   	}
+   }
+   
+   private Address getFailoverNodeControlChannelAddress()
+   {
+   	PostOfficeAddressInfo info = (PostOfficeAddressInfo)nodeIDAddressMap.get(new Integer(failoverNodeID));
+   	
+   	if (info == null)
+   	{
+   		return null;
+   	}
+   	
+   	Address address = info.getControlChannelAddress();
+   	
+   	return address;
+   }
+   
+   public void handleReplicateAck(String queueName, long messageID, int nodeID) throws Exception
+   {
+      Binding binding = getBindingForQueueName(queueName);
+   	
+   	if (binding == null)
+   	{
+   		throw new IllegalStateException("Cannot find queue with name " + queueName +" has it been deployed?");
+   	}
+   	
+   	Queue queue = binding.queue;
+   	
+   	queue.removeFromRecoveryArea(nodeID, messageID);  
+   }
+   
+   public void handleReplicateDeliveryAck(String sessionID, long deliveryID) throws Exception
+   {
+   	if (trace) { log.trace(this + " handleReplicateDeliveryAck " + sessionID + " " + deliveryID); }
+   	
+   	//We need to lock this while failover node change is occurring - otherwise we could end up with the same message
+   	//being delivered more than once
+   	
+   	replicateDeliveryLock.readLock().acquire();
+   	
+   	try
+   	{	   	
+	   	//TOD - this does not belong here
+	   	ServerSessionEndpoint session = serverPeer.getSession(sessionID);
+	   	
+	   	if (session == null)
+	   	{
+	   		log.warn("Cannot find session " + sessionID);
+	   		
+	   		return;
+	   	}
+	   	
+	   	session.replicateDeliveryResponseReceived(deliveryID);
+   	}
+   	finally
+   	{
+   		replicateDeliveryLock.readLock().release();
+   	}
+   }
+   
+   public void handleAckAllReplicatedDeliveries(int nodeID) throws Exception
+   {
+   	if (trace) { log.trace(this + " handleAckAllDeliveries " + nodeID); }
+   	
+   	lock.readLock().acquire();
+   	
+   	try
+   	{
+   		if (localNameMap != null)
+   		{
+   			Iterator iter = localNameMap.values().iterator();
+   			
+   			while (iter.hasNext())
+   			{
+   				Binding binding = (Binding)iter.next();
+   				
+   				binding.queue.removeAllFromRecoveryArea(nodeID);
+   			}
+   		}
+   	}
+   	finally
+   	{
+   		lock.readLock().release();
+   	}   	
+   }
+   
+   public void handleAddAllReplicatedDeliveries(Map deliveries, int nodeID) throws Exception
+   {
+   	if (trace) { log.trace(this + " handleAddAllReplicatedDeliveries " + nodeID); }
+   	
+   	lock.readLock().acquire();
+   	
+   	try
+   	{
+   		if (localNameMap != null)
+   		{
+   			Iterator iter = deliveries.entrySet().iterator();
+   			
+   			while (iter.hasNext())
+   			{
+   				Map.Entry entry = (Map.Entry)iter.next();
+   				
+   				String queueName = (String)entry.getKey();
+   				
+   				Set ids = (Set)entry.getValue();
+   				
+   				Binding binding = (Binding)localNameMap.get(queueName);
+   				
+   				if (binding == null)
+   				{
+   					throw new IllegalStateException("Cannot find binding with name " + queueName);
+   				}
+   				
+   				binding.queue.addAllToRecoveryArea(nodeID, ids);
+   			}   			   			
+   		}
+   	}
+   	finally
+   	{
+   		lock.readLock().release();
+   	}   
+   }
+  
 
    // Replicator implementation --------------------------------------------------------------------
 
@@ -1021,9 +1291,9 @@
 
    public boolean remove(Serializable key) throws Exception
    {
-      if (removeReplicantLocally(this.thisNodeID, key))
+      if (removeReplicantLocally(thisNodeID, key))
       {
-         RemoveReplicantRequest request = new RemoveReplicantRequest(this.thisNodeID, key);
+         RemoveReplicantRequest request = new RemoveReplicantRequest(thisNodeID, key);
 
          groupMember.multicastControl(request, true);
 
@@ -1207,10 +1477,12 @@
       {
       	replicatedData = new HashMap();
 
-         failoverMap = new LinkedHashMap();
+         failoverMap = new HashMap();
 
          leftSet = new ConcurrentHashSet();
       }
+      
+      replyExecutor = new PooledExecutor(new LinkedQueue(),  10);
    }
    
    private void deInit()
@@ -1232,6 +1504,7 @@
          leftSet = null;
       }
    	
+   	replyExecutor.shutdownNow();   	
    }
 
    
@@ -1275,7 +1548,7 @@
 						}
 						else
 						{
-							Map nameMap = (Map)this.nameMaps.get(node);
+							Map nameMap = (Map)nameMaps.get(node);
 							
 							if (nameMap != null && nameMap.get(queueName) != null)
 							{
@@ -1324,7 +1597,7 @@
    
    private boolean internalAddBinding(Binding binding, boolean allNodes, boolean sync) throws Exception
    {
-   	if (trace) { log.trace(this.thisNodeID + " binding " + binding.queue + " with condition " + binding.condition + " all nodes " + allNodes); }
+   	if (trace) { log.trace(thisNodeID + " binding " + binding.queue + " with condition " + binding.condition + " all nodes " + allNodes); }
 
    	if (binding == null)
       {
@@ -1369,7 +1642,8 @@
          			                             queue.isRecoverable(), true,
          			                             binding.allNodes,
          			                             queue.getFullSize(), queue.getPageSize(), queue.getDownCacheSize(),
-         			                             queue.getMaxSize());
+         			                             queue.getMaxSize(),
+         			                             queue.getRecoverDeliveriesTimeout());
          	
             ClusterRequest request = new BindRequest(info, allNodes);
 
@@ -1382,7 +1656,7 @@
    
    private Binding internalRemoveBinding(String queueName, boolean allNodes, boolean sync) throws Throwable
    {
-      if (trace) { log.trace(this.thisNodeID + " unbind queue: " + queueName + " all nodes " + allNodes); }
+      if (trace) { log.trace(thisNodeID + " unbind queue: " + queueName + " all nodes " + allNodes); }
 
       if (queueName == null)
       {
@@ -1425,22 +1699,99 @@
    
    private void calculateFailoverMap()
    {
-   	 //calculate the failover map
-      synchronized (failoverMap)
+   	synchronized (failoverMap)
    	{
-	   	// A node-address mapping has been added/removed from global state, we need to update
-	      // the failover map.
-	      failoverMap = failoverMapper.generateMapping(nodeIDAddressMap.keySet());
-   	}
+	   	failoverMap.clear();
+	   	
+	   	View view = groupMember.getCurrentView();
+	   	
+	   	Vector members = view.getMembers();
+	   	
+	   	for (int i = 0; i < members.size(); i++)
+	   	{
+	   		Address address = (Address)members.get(i);
+	   		
+	   		Integer theNodeID = findNodeIDForAddress(address);
+	   		
+	   		if (theNodeID == null)
+	   		{
+	   			throw new IllegalStateException("Cannot find node id for address " + address);
+	   		}
+	   		
+	   		int j;
+	   		
+	   		if (i != members.size() - 1)
+	   		{
+	   			j = i + 1;
+	   		}
+	   		else
+	   		{
+	   			j = 0;
+	   		}
+	   		
+	   		Address failoverAddress = (Address)members.get(j);
+	   		
+	   		Integer failoverNodeID = this.findNodeIDForAddress(failoverAddress);
+	   		
+	   		if (failoverNodeID == null)
+	   		{
+	   			throw new IllegalStateException("Cannot find node id for address " + failoverAddress);
+	   		}
+	   		
+	   		failoverMap.put(theNodeID, failoverNodeID);	   			   		   
+	   	}   	
+	   	
+	   	int fid = ((Integer)failoverMap.get(new Integer(thisNodeID))).intValue();
+	   	
+	   	//if we are the first node in the cluster we don't want to be our own failover node!
+	   	
+	   	if (fid == thisNodeID)
+	   	{
+	   		firstNode = true;
+	   		fid = -1;
+	   	}
+	   	else
+	   	{
+	   		failoverNodeID = fid;
+	   		firstNode = false;	   		
+	   	}	   	
+   	}   
+   	
+      log.debug("Updated failover map:\n" + dumpFailoverMap(failoverMap));   	      
    }
    
+   private Integer findNodeIDForAddress(Address address)
+   {
+   	Integer theNodeID = null;
+		
+   	Iterator iter = this.nodeIDAddressMap.entrySet().iterator();
+   	
+		while (iter.hasNext())
+		{
+			Map.Entry entry = (Map.Entry)iter.next();
+			
+			Integer nodeID = (Integer)entry.getKey();
+			
+			PostOfficeAddressInfo info = (PostOfficeAddressInfo)entry.getValue();
+			
+			if (info.getControlChannelAddress().equals(address))
+			{
+				theNodeID = nodeID;
+				
+				break;
+			}
+		}
+		
+		return theNodeID;
+   }
+   
    private Collection getBindings(String queueName) throws Exception
    {
    	lock.readLock().acquire();
 
    	try
    	{
-   		Iterator iter = this.nameMaps.values().iterator();
+   		Iterator iter = nameMaps.values().iterator();
    		
    		List bindings = new ArrayList();
    		
@@ -1690,7 +2041,7 @@
    	{
    		Integer nid = new Integer(nodeID);
    		
-	   	Map nameMap = (Map)this.nameMaps.get(nid);
+	   	Map nameMap = (Map)nameMaps.get(nid);
 	   	
 	   	if (nameMap == null)
 	   	{
@@ -1765,7 +2116,7 @@
    	{	  
    		Integer nid = new Integer(queue.getNodeID());
    		
-   		Map nameMap = (Map)this.nameMaps.get(nid);
+   		Map nameMap = (Map)nameMaps.get(nid);
    		   		
    		if (nameMap != null && nameMap.containsKey(queue.getName()))
    		{
@@ -1843,7 +2194,7 @@
     */
    private void unicastRequest(ClusterRequest request, int nodeId) throws Exception
    {
-      Address address = this.getAddressForNodeId(nodeId, false);
+      Address address = getAddressForNodeId(nodeId, false);
 
       if (address == null)
       {
@@ -1955,7 +2306,8 @@
          			                             queue.isRecoverable(), true,
          			                             binding.allNodes,
          			                             queue.getFullSize(), queue.getPageSize(), queue.getDownCacheSize(),
-         			                             queue.getMaxSize());
+         			                             queue.getMaxSize(),
+         			                             queue.getRecoverDeliveriesTimeout());
          	
             ClusterRequest request = new BindRequest(info, binding.allNodes);
 
@@ -2035,7 +2387,7 @@
 
          ps = conn.prepareStatement(getSQLStatement("DELETE_BINDING"));
 
-         ps.setString(1, this.officeName);
+         ps.setString(1, officeName);
          ps.setInt(2, queue.getNodeID());
          ps.setString(3, queue.getName());
 
@@ -2145,8 +2497,18 @@
       }
       
       //Recalculate the failover map
+      
+      int oldFailoverNodeID = failoverNodeID;
+      
       calculateFailoverMap();
       
+      if (!firstNode && oldFailoverNodeID != failoverNodeID)
+      {
+      	//Failover node for this node has changed
+      	
+      	failoverNodeChanged(oldFailoverNodeID);      	
+      }
+      
       //Notify outside the lock to prevent deadlock
       
       //Send notifications for the replicant data removed
@@ -2233,6 +2595,76 @@
    	}     	
    }
    
+   private void failoverNodeChanged(int oldFailoverNodeID) throws Exception
+   {   	   	
+   	//The failover node has changed - we need to move our replicated deliveries
+   	
+   	if (trace) { log.trace("Failover node has changed from " + oldFailoverNodeID + " to " + failoverNodeID); }
+   	   	
+   	//If the old node still exists we need to send a message to remove any replicated deliveries
+   	
+   	PostOfficeAddressInfo info = (PostOfficeAddressInfo)nodeIDAddressMap.get(new Integer(oldFailoverNodeID));
+   	
+   	if (info != null)
+   	{
+   		if (trace) { log.trace("Old failover node still exists, telling it remove replicated deliveries"); }
+   		
+   		ClusterRequest request = new AckAllReplicatedDeliveriesMessage(oldFailoverNodeID);
+   		
+   		groupMember.unicastControl(request, info.getControlChannelAddress(), true);
+   		
+   		if (trace) { log.trace("Sent AckAllReplicatedDeliveriesMessage"); }
+   	}
+   	
+   	//Now send the deliveries to the new node
+   	
+   	//We must lock any responses to delivery adds coming in in this period - otherwise we could end up with the same
+   	//message being delivered more than once
+   	
+   	replicateDeliveryLock.writeLock().acquire();
+   	
+   	try
+   	{	   	
+	   	if (this.localNameMap != null)
+	   	{
+	   		info = (PostOfficeAddressInfo)nodeIDAddressMap.get(new Integer(failoverNodeID));
+	   		
+	   		if (info == null)
+	   		{
+	   			throw new IllegalStateException("Cannot find address for failover node " + failoverNodeID);
+	   		}
+	   		
+	   		Map deliveries = new HashMap();
+	   		
+				//FIXME - this is ugly
+				//Find a better way of getting the sessions
+				
+				Collection sessions = serverPeer.getSessions();
+				
+				Iterator iter2 = sessions.iterator();
+				
+				while (iter2.hasNext())
+				{
+					ServerSessionEndpoint session = (ServerSessionEndpoint)iter2.next();
+					
+					session.collectDeliveries(deliveries);				
+				}   				  
+				
+				ClusterRequest request = new AddAllReplicatedDeliveriesMessage(thisNodeID, deliveries);
+				
+				//send sync
+				
+				groupMember.unicastControl(request, info.getControlChannelAddress(), true);
+	   		
+	   		if (trace) { log.trace("Sent AddAllReplicatedDeliveriesMessage"); }
+	   	}
+   	}
+   	finally
+   	{
+   		replicateDeliveryLock.writeLock().release();
+   	}
+   }
+   
 
    /**
     * This method fails over all the queues from node <failedNodeId> onto this node. It is triggered
@@ -2257,9 +2689,9 @@
 
       try
       {
-         this.pm.mergeTransactions(failedNodeID.intValue(), thisNodeID);
+         pm.mergeTransactions(failedNodeID.intValue(), thisNodeID);
 
-      	Map nameMap = (Map)this.nameMaps.get(failedNodeID);
+      	Map nameMap = (Map)nameMaps.get(failedNodeID);
       	
       	List toRemove = new ArrayList();
       	
@@ -2332,7 +2764,7 @@
             	
             	log.debug(this + " has already a queue: " + queue.getName() + " queue so merging queues");
             	  
-               localQueue.mergeIn(queue.getChannelID());
+               localQueue.mergeIn(queue.getChannelID(), failedNodeID.intValue());
                
                log.debug("Merged queue");       
             }
@@ -2365,6 +2797,11 @@
          lock.writeLock().release();
       }
       
+      //Now clean the data for the failed node
+      
+      //TODO - does this need to be inside the lock above?
+      cleanDataForNode(failedNodeID);
+      
       log.debug(this + " announcing that failover procedure is complete");
 
       notification = new ClusterNotification(ClusterNotification.TYPE_FAILOVER_END, failedNodeID.intValue(), null);
@@ -2372,8 +2809,7 @@
       clusterNotifier.sendNotification(notification);
       
       //for testing only
-      this.sendJMXNotification(FAILOVER_COMPLETED_NOTIFICATION);
-
+      sendJMXNotification(FAILOVER_COMPLETED_NOTIFICATION);
    }
 
    private void sendJMXNotification(String notificationType)

Added: trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateAckMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateAckMessage.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateAckMessage.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.impl.postoffice;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>6 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class ReplicateAckMessage extends ClusterRequest
+{
+	private String queueName;
+	
+	private long messageID;
+	
+	private int nodeID;
+	
+	public ReplicateAckMessage()
+	{		
+	}
+	
+	public ReplicateAckMessage(String queueName, long messageID, int nodeID)
+	{
+		this.queueName = queueName;
+		
+		this.messageID = messageID;
+		
+		this.nodeID = nodeID;
+	}
+	
+	Object execute(RequestTarget office) throws Throwable
+	{
+		office.handleReplicateAck(queueName, messageID, nodeID);
+		
+		return null;
+	}
+
+	byte getType()
+	{
+		return ClusterRequest.REPLICATE_ACK_REQUEST;
+	}
+
+	public void read(DataInputStream in) throws Exception
+	{
+		queueName = in.readUTF();
+		
+		messageID = in.readLong();
+		
+		nodeID = in.readInt();
+	}
+
+	public void write(DataOutputStream out) throws Exception
+	{
+		out.writeUTF(queueName);
+		
+		out.writeLong(messageID);
+		
+		out.writeInt(nodeID);
+	}
+
+}

Added: trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryAckMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryAckMessage.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryAckMessage.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.impl.postoffice;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>6 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class ReplicateDeliveryAckMessage extends ClusterRequest
+{
+	private String sessionID;
+	
+	private long deliveryID;
+	
+	public ReplicateDeliveryAckMessage()
+	{		
+	}
+	
+	public ReplicateDeliveryAckMessage(String sessionID, long deliveryID)
+	{
+		this.sessionID = sessionID;
+		
+		this.deliveryID = deliveryID;
+	}
+	
+	Object execute(RequestTarget office) throws Throwable
+	{
+		office.handleReplicateDeliveryAck(sessionID, deliveryID);
+		
+		return null;
+	}
+
+	byte getType()
+	{
+		return ClusterRequest.REPLICATE_DELIVERY_ACK_REQUEST;
+	}
+
+	public void read(DataInputStream in) throws Exception
+	{
+		sessionID = in.readUTF();
+		
+		deliveryID = in.readLong();
+	}
+
+	public void write(DataOutputStream out) throws Exception
+	{
+		out.writeUTF(sessionID);
+		
+		out.writeLong(deliveryID);
+	}
+
+}

Added: trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryMessage.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/ReplicateDeliveryMessage.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,139 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.core.impl.postoffice;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+import org.jgroups.Address;
+import org.jgroups.stack.IpAddress;
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>6 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class ReplicateDeliveryMessage extends ClusterRequest
+{
+	private String queueName;
+	
+	private String sessionID;
+	
+	private long messageID;
+	
+	private long deliveryID;
+	
+	private Address replyAddress;
+	
+	private int nodeID;
+	
+	private static final int NULL = 0;
+	
+	private static final int NOT_NULL = 1;
+	
+	public ReplicateDeliveryMessage()
+	{		
+	}
+	
+	public ReplicateDeliveryMessage(String queueName, String sessionID, long messageID, long deliveryID,
+			                          Address replyAddress, int nodeID)
+	{
+		this.queueName = queueName;
+		
+		this.sessionID = sessionID;
+		
+		this.messageID = messageID;
+		
+		this.deliveryID = deliveryID;
+		
+		this.replyAddress = replyAddress;
+		
+		this.nodeID = nodeID;
+	}
+		
+	Object execute(RequestTarget office) throws Throwable
+	{		
+		office.handleReplicateDelivery(queueName, sessionID, messageID, deliveryID, replyAddress, nodeID);
+		
+		return "ok";
+	}
+
+	byte getType()
+	{
+		return ClusterRequest.REPLICATE_DELIVERY_REQUEST;
+	}
+
+	public void read(DataInputStream in) throws Exception
+	{
+		queueName = in.readUTF();
+		
+		sessionID = in.readUTF();
+		
+		messageID = in.readLong();
+		
+		deliveryID = in.readLong();
+		
+		byte b = in.readByte();
+		
+		if (b != NULL)
+		{
+			replyAddress = new IpAddress();
+			
+			replyAddress.readFrom(in);
+		}
+		
+		nodeID = in.readInt();
+	}
+
+	public void write(DataOutputStream out) throws Exception
+	{
+		out.writeUTF(queueName);
+		
+		out.writeUTF(sessionID);
+		
+		out.writeLong(messageID);
+		
+		out.writeLong(deliveryID);
+		
+		if (replyAddress == null)
+		{
+			out.writeByte(NULL);
+		}
+		else
+		{
+			out.writeByte(NOT_NULL);
+			
+			if (!(replyAddress instanceof IpAddress))
+	      {
+	         throw new IllegalStateException("Address must be IpAddress");
+	      }
+
+	      replyAddress.writeTo(out);
+		}
+		
+		out.writeInt(nodeID);
+	}
+
+}

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/RequestTarget.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/RequestTarget.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/RequestTarget.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -22,9 +22,11 @@
 package org.jboss.messaging.core.impl.postoffice;
 
 import java.io.Serializable;
+import java.util.Map;
 import java.util.Set;
 
 import org.jboss.messaging.core.contract.Message;
+import org.jgroups.Address;
 
 /**
  * 
@@ -51,4 +53,17 @@
    boolean removeReplicantLocally(int nodeId, Serializable key) throws Exception;
    
    void routeFromCluster(Message message, String routingKeyText, Set queueNames) throws Exception;
+   
+   //TODO - these don't belong here
+   
+   void handleReplicateDelivery(String queueName, String sessionID, long messageID,
+   		                       long deliveryID, Address replyAddress, int nodeID) throws Exception;
+   
+   void handleReplicateAck(String queueName, long messageID, int nodeID) throws Exception;
+   
+   void handleReplicateDeliveryAck(String sessionID, long deliveryID) throws Exception;
+   
+   void handleAckAllReplicatedDeliveries(int nodeID) throws Exception;
+   
+   void handleAddAllReplicatedDeliveries(Map deliveries, int nodeID) throws Exception;
 }

Modified: trunk/src/main/org/jboss/messaging/core/jmx/MessagingPostOfficeService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/jmx/MessagingPostOfficeService.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/core/jmx/MessagingPostOfficeService.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -35,7 +35,6 @@
 import org.jboss.jms.server.selector.SelectorFactory;
 import org.jboss.messaging.core.contract.ClusterNotifier;
 import org.jboss.messaging.core.contract.ConditionFactory;
-import org.jboss.messaging.core.contract.FailoverMapper;
 import org.jboss.messaging.core.contract.FilterFactory;
 import org.jboss.messaging.core.contract.JChannelFactory;
 import org.jboss.messaging.core.contract.MessageStore;
@@ -44,7 +43,6 @@
 import org.jboss.messaging.core.impl.IDManager;
 import org.jboss.messaging.core.impl.jchannelfactory.MultiplexerJChannelFactory;
 import org.jboss.messaging.core.impl.jchannelfactory.XMLJChannelFactory;
-import org.jboss.messaging.core.impl.postoffice.DefaultFailoverMapper;
 import org.jboss.messaging.core.impl.postoffice.MessagingPostOffice;
 import org.jboss.messaging.core.impl.tx.TransactionRepository;
 import org.jboss.messaging.util.ExceptionUtil;
@@ -353,8 +351,6 @@
                   
          FilterFactory ff = new SelectorFactory();
          
-         FailoverMapper mapper = new DefaultFailoverMapper();
-
          JChannelFactory jChannelFactory = null;
 
          if (channelFactoryName != null)
@@ -402,7 +398,6 @@
 	                                               groupName,
 	                                               jChannelFactory,
 	                                               stateTimeout, castTimeout,
-	                                               mapper,
                                                   serverPeer.isSupportsFailover());
          }
          else

Modified: trunk/src/main/org/jboss/messaging/util/ConcurrentHashSet.java
===================================================================
--- trunk/src/main/org/jboss/messaging/util/ConcurrentHashSet.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/util/ConcurrentHashSet.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -24,6 +24,7 @@
 import java.util.AbstractSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
 
@@ -49,6 +50,18 @@
       theMap = new ConcurrentHashMap();
    }
    
+   public ConcurrentHashSet(Set other)
+   {
+   	this();
+   	
+   	addAll(other);
+   }
+   
+   public ConcurrentHashSet(int size)
+   {
+   	theMap = new ConcurrentHashMap(size);
+   }
+   
    public int size()
    {
       return theMap.size();

Modified: trunk/src/main/org/jboss/messaging/util/ExceptionUtil.java
===================================================================
--- trunk/src/main/org/jboss/messaging/util/ExceptionUtil.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/src/main/org/jboss/messaging/util/ExceptionUtil.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -25,7 +25,6 @@
 
 import org.jboss.jms.exception.MessagingJMSException;
 import org.jboss.logging.Logger;
-import org.jboss.util.id.GUID;
 
 /**
  * A ExceptionUtil
@@ -59,7 +58,7 @@
       //We create a GUID and log it and send it in the client exception.
       //This allows what is received at the client to be correlated if necessary
       //to what is logged in the server logs
-      String id = new GUID().toString();
+      String id = GUIDGenerator.generateGUID();
       
       //First we log the Throwable
       log.error(msg + " [" + id + "]", t);

Added: trunk/src/main/org/jboss/messaging/util/GUIDGenerator.java
===================================================================
--- trunk/src/main/org/jboss/messaging/util/GUIDGenerator.java	                        (rev 0)
+++ trunk/src/main/org/jboss/messaging/util/GUIDGenerator.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,57 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.messaging.util;
+
+import org.jboss.util.id.GUID;
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>6 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class GUIDGenerator
+{
+	public static String generateGUID()
+	{
+		String guid = new GUID().toString();
+		
+		//We reverse the guid - this is because the JBoss GUID generates strings which are often the same up until
+		//the last few characters, this means comparing them can be slow (when they're not equal) since many characters need
+		//to be scanned
+		
+		int i;
+		
+		int len = guid.length();
+		
+		StringBuffer res = new StringBuffer(len);
+
+		for (i = len -1; i >= 0; i--)
+		{
+			res.append(guid.charAt(i));
+		}
+		
+		return res.toString();
+	}
+}

Modified: trunk/tests/src/org/jboss/test/messaging/core/PostOfficeTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/PostOfficeTestBase.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/PostOfficeTestBase.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -27,7 +27,6 @@
 import org.jboss.messaging.core.contract.ClusterNotifier;
 import org.jboss.messaging.core.contract.Condition;
 import org.jboss.messaging.core.contract.ConditionFactory;
-import org.jboss.messaging.core.contract.FailoverMapper;
 import org.jboss.messaging.core.contract.FilterFactory;
 import org.jboss.messaging.core.contract.JChannelFactory;
 import org.jboss.messaging.core.contract.Message;
@@ -40,7 +39,6 @@
 import org.jboss.messaging.core.impl.IDManager;
 import org.jboss.messaging.core.impl.JDBCPersistenceManager;
 import org.jboss.messaging.core.impl.message.SimpleMessageStore;
-import org.jboss.messaging.core.impl.postoffice.DefaultFailoverMapper;
 import org.jboss.messaging.core.impl.postoffice.MessagingPostOffice;
 import org.jboss.messaging.core.impl.tx.Transaction;
 import org.jboss.messaging.core.impl.tx.TransactionRepository;
@@ -78,7 +76,6 @@
       throws Exception
    {
       FilterFactory ff = new SimpleFilterFactory();
-      FailoverMapper mapper = new DefaultFailoverMapper();
       ConditionFactory cf = new SimpleConditionFactory();
       IDManager idm = new IDManager("channel_id", 10, pm);
       idm.start();
@@ -100,7 +97,7 @@
                                  sc.getPostOfficeSQLProperties(), true, nodeID,
                                  "Clustered", ms, pm, tr, ff, cf, idm, cn,
                                  groupName, jChannelFactory,
-                                 stateTimeout, castTimeout, mapper, true);
+                                 stateTimeout, castTimeout, true);
       
       postOffice.start();
 

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -62,10 +62,10 @@
    
    public void testChannelShareNP_2PC() throws Throwable
    {   	   	
-      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue1.activate();
       
-      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false, 300000);
       queue2.activate();
      
       Message[] msgs = new Message[150];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -61,10 +61,10 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue1.activate();
       
-      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false, 300000);
       queue2.activate();
       
       Message[] msgs = new Message[150];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -62,10 +62,10 @@
    
    public void testChannelShareNP_Transactional() throws Throwable
    {
-      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue1.activate();
       
-      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false, 300000);
       queue2.activate();                  
       
       Message[] msgs = new Message[150];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -57,10 +57,10 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue1.activate();
       
-      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false, 300000);
       queue2.activate();                  
       
       Message[] msgs = new Message[150];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -61,10 +61,10 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue1.activate();
       
-      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false, 300000);
       queue2.activate();          
       
       Message[] msgs = new Message[150];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -61,10 +61,10 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue1 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue1.activate();
       
-      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue2", 2, ms, pm, true, -1, null, 50, 10, 5, false, 300000);
       queue2.activate();              
       
       Message[] msgs = new Message[150];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -61,7 +61,7 @@
 
    public void testPaging() throws Exception
    {
-      MessagingQueue p = new MessagingQueue(1, "queue0", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue p = new MessagingQueue(1, "queue0", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       p.activate();
            
       CoreMessage m = null;

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -64,7 +64,7 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
       
       Message[] msgs = new Message[241];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -63,7 +63,7 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate(); 
       
       Message[] msgs = new Message[241];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -64,7 +64,7 @@
  
    public void test1() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
       
       Message[] msgs = new Message[241];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -64,7 +64,7 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
       
       Message[] msgs = new Message[241];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -63,7 +63,7 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
       
       Message[] msgs = new Message[241];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -64,7 +64,7 @@
    
    public void test1() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate();  
       
       Message[] msgs = new Message[241];

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -65,7 +65,7 @@
    
    public void testRecoverableQueueCrash() throws Throwable
    {
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
       
       Message[] msgs = new Message[200];
@@ -128,7 +128,7 @@
 
       tr.start();
          
-      MessagingQueue queue2 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 10, false, 300000);
     
       queue2.load();
       queue2.activate();
@@ -164,7 +164,7 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, false, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, false, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
          	      
       Message[] msgs = new Message[200];
@@ -225,7 +225,7 @@
       tr = new TransactionRepository(pm, ms, idm);
       tr.start();
 
-      MessagingQueue queue2 = new MessagingQueue(1, "queue1", 1, ms, pm, false, -1, null, 100, 20, 10, false);
+      MessagingQueue queue2 = new MessagingQueue(1, "queue1", 1, ms, pm, false, -1, null, 100, 20, 10, false, 300000);
       
       queue2.load();
       
@@ -257,7 +257,7 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, false, -1, null, 100, 20, 10, false);
+      MessagingQueue queue = new MessagingQueue(1, "queue1", 1, ms, pm, false, -1, null, 100, 20, 10, false, 300000);
       queue.activate();
         
       Message[] msgs = new Message[200];

Modified: trunk/tests/src/org/jboss/test/messaging/jms/WireFormatTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/WireFormatTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/WireFormatTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -448,7 +448,7 @@
       public void testConnectionFactoryCreateConnectionDelegate() throws Exception
       {
          RequestSupport req =
-            new ConnectionFactoryCreateConnectionDelegateRequest(23, (byte)77, "session123", "vm123", null, null, -1);;
+            new ConnectionFactoryCreateConnectionDelegateRequest("23", (byte)77, "session123", "vm123", null, null, -1);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTIONFACTORY_CREATECONNECTIONDELEGATE);                           
       }
@@ -456,7 +456,7 @@
       public void testConnectionFactoryGetIDBlock() throws Exception
       {
          RequestSupport req =
-            new ConnectionGetIDBlockRequest(23, (byte)77, 66);;
+            new ConnectionGetIDBlockRequest("23", (byte)77, 66);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTIONFACTORY_GETIDBLOCK);                           
       }
@@ -464,7 +464,7 @@
       public void testConnectionFactoryGetClientAOPStack() throws Exception
       {
          RequestSupport req =
-            new ConnectionFactoryGetClientAOPStackRequest(23, (byte)77);;
+            new ConnectionFactoryGetClientAOPStackRequest("23", (byte)77);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTIONFACTORY_GETCLIENTAOPSTACK);                           
       }
@@ -474,7 +474,7 @@
       public void testConnectionCreateSessionDelegateRequest() throws Exception
       {
          RequestSupport req =
-            new ConnectionCreateSessionDelegateRequest(23, (byte)77, true, 23, true);;
+            new ConnectionCreateSessionDelegateRequest("23", (byte)77, true, 23, true);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_CREATESESSIONDELEGATE);                           
       }
@@ -482,7 +482,7 @@
       public void testConnectionGetClientIDRequest() throws Exception
       {
          RequestSupport req =
-            new ConnectionGetClientIDRequest(23, (byte)77);;
+            new ConnectionGetClientIDRequest("23", (byte)77);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_GETCLIENTID);                           
       }
@@ -490,7 +490,7 @@
       public void testConnectionSetClientIDRequest() throws Exception
       {
          RequestSupport req =
-            new ConnectionSetClientIDRequest(23, (byte)77, "blah");;
+            new ConnectionSetClientIDRequest("23", (byte)77, "blah");;
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_SETCLIENTID);                           
       }
@@ -498,7 +498,7 @@
       public void testConnectionStartRequest() throws Exception
       {
          RequestSupport req =
-            new ConnectionStartRequest(23, (byte)77);;
+            new ConnectionStartRequest("23", (byte)77);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_START);                           
       }
@@ -506,7 +506,7 @@
       public void testConnectionStopRequest() throws Exception
       {
          RequestSupport req =
-            new ConnectionStopRequest(23, (byte)77);;
+            new ConnectionStopRequest("23", (byte)77);;
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_STOP);                           
       }
@@ -518,7 +518,7 @@
          TransactionRequest tr = new TransactionRequest(TransactionRequest.ONE_PHASE_COMMIT_REQUEST, null, tx);
          
          RequestSupport req =
-            new ConnectionSendTransactionRequest(23, (byte)77, tr, false);
+            new ConnectionSendTransactionRequest("23", (byte)77, tr, false);
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_SENDTRANSACTION);                           
       }      
@@ -526,7 +526,7 @@
       public void testConnectionGetPreparedTransactionsRequest() throws Exception
       {
          RequestSupport req =
-            new ConnectionGetPreparedTransactionsRequest(23, (byte)77);
+            new ConnectionGetPreparedTransactionsRequest("23", (byte)77);
                  
          testPacket(req, PacketSupport.REQ_CONNECTION_GETPREPAREDTRANSACTIONS);                           
       }  
@@ -536,7 +536,7 @@
       public void testSessionCreateConsumerDelegateRequest() throws Exception
       {
          RequestSupport req =
-            new SessionCreateConsumerDelegateRequest(23, (byte)77, new JBossQueue("wibble"), null, false, null, false, true);
+            new SessionCreateConsumerDelegateRequest("23", (byte)77, new JBossQueue("wibble"), null, false, null, false, true);
                  
          testPacket(req, PacketSupport.REQ_SESSION_CREATECONSUMERDELEGATE);                           
       } 
@@ -544,7 +544,7 @@
       public void testSessionCreateBrowserDelegateRequest() throws Exception
       {
          RequestSupport req =
-            new SessionCreateBrowserDelegateRequest(23, (byte)77, new JBossQueue("wibble"), null);
+            new SessionCreateBrowserDelegateRequest("23", (byte)77, new JBossQueue("wibble"), null);
                  
          testPacket(req, PacketSupport.REQ_SESSION_CREATEBROWSERDELEGATE);                           
       }
@@ -552,7 +552,7 @@
       public void testSessionCreateQueueRequest() throws Exception
       {
          RequestSupport req =
-            new SessionCreateQueueRequest(23, (byte)77, "wibble");
+            new SessionCreateQueueRequest("23", (byte)77, "wibble");
                  
          testPacket(req, PacketSupport.REQ_SESSION_CREATEQUEUE);                           
       }      
@@ -560,7 +560,7 @@
       public void testSessionCreateTopicRequest() throws Exception
       {
          RequestSupport req =
-            new SessionCreateTopicRequest(23, (byte)77, "wibble");
+            new SessionCreateTopicRequest("23", (byte)77, "wibble");
                  
          testPacket(req, PacketSupport.REQ_SESSION_CREATETOPIC);                           
       }
@@ -572,7 +572,7 @@
          acks.add(new DefaultAck(12323));
          
          RequestSupport req =
-            new SessionAcknowledgeDeliveriesRequest(23, (byte)77, acks);
+            new SessionAcknowledgeDeliveriesRequest("23", (byte)77, acks);
                  
          testPacket(req, PacketSupport.REQ_SESSION_ACKNOWLEDGEDELIVERIES);                           
       }   
@@ -582,7 +582,7 @@
          Ack ack = new DefaultAck(12323);
          
          RequestSupport req =
-            new SessionAcknowledgeDeliveryRequest(23, (byte)77, ack);
+            new SessionAcknowledgeDeliveryRequest("23", (byte)77, ack);
                  
          testPacket(req, PacketSupport.REQ_SESSION_ACKNOWLEDGEDELIVERY);                           
       } 
@@ -594,7 +594,7 @@
          cancels.add(new DefaultCancel(12323, 12, false, false));
          
          RequestSupport req =
-            new SessionCancelDeliveriesRequest(23, (byte)77, cancels);
+            new SessionCancelDeliveriesRequest("23", (byte)77, cancels);
                  
          testPacket(req, PacketSupport.REQ_SESSION_CANCELDELIVERIES);                           
       }   
@@ -604,7 +604,7 @@
          Cancel cancel = (new DefaultCancel(12323, 12, false, false));
          
          RequestSupport req =
-            new SessionCancelDeliveryRequest(23, (byte)77, cancel);
+            new SessionCancelDeliveryRequest("23", (byte)77, cancel);
                  
          testPacket(req, PacketSupport.REQ_SESSION_CANCELDELIVERY);                           
       } 
@@ -612,7 +612,7 @@
       public void testSessionAddTemporaryDestinationRequest() throws Exception
       {
          RequestSupport req =
-            new SessionAddTemporaryDestinationRequest(23, (byte)77, new JBossTemporaryQueue("blah"));
+            new SessionAddTemporaryDestinationRequest("23", (byte)77, new JBossTemporaryQueue("blah"));
                  
          testPacket(req, PacketSupport.REQ_SESSION_ADDTEMPORARYDESTINATION);                           
       } 
@@ -620,7 +620,7 @@
       public void testSessionDeleteTemporaryDestinationRequest() throws Exception
       {
          RequestSupport req =
-            new SessionDeleteTemporaryDestinationRequest(23, (byte)77, new JBossTemporaryQueue("blah"));
+            new SessionDeleteTemporaryDestinationRequest("23", (byte)77, new JBossTemporaryQueue("blah"));
                  
          testPacket(req, PacketSupport.REQ_SESSION_DELETETEMPORARYDESTINATION);                           
       } 
@@ -628,7 +628,7 @@
       public void testSessionUnsubscribeRequest() throws Exception
       {
          RequestSupport req =
-            new SessionUnsubscribeRequest(23, (byte)77, "blah");
+            new SessionUnsubscribeRequest("23", (byte)77, "blah");
                  
          testPacket(req, PacketSupport.REQ_SESSION_UNSUBSCRIBE);                           
       }
@@ -638,7 +638,7 @@
          JBossMessage msg = new JBossMessage(123);
          
          RequestSupport req =
-            new SessionSendRequest(23, (byte)77, msg, false);
+            new SessionSendRequest("23", (byte)77, msg, false);
                  
          testPacket(req, PacketSupport.REQ_SESSION_SEND);                           
       }
@@ -652,7 +652,7 @@
          dels.add(info);
          
          RequestSupport req =
-            new SessionRecoverDeliveriesRequest(23, (byte)77, dels);
+            new SessionRecoverDeliveriesRequest("23", (byte)77, dels);
                  
          testPacket(req, PacketSupport.REQ_SESSION_RECOVERDELIVERIES);                           
       }
@@ -662,7 +662,7 @@
       public void testConsumerChangeRateRequest() throws Exception
       { 
          RequestSupport req =
-            new ConsumerChangeRateRequest(23, (byte)77, 123.23f);
+            new ConsumerChangeRateRequest("23", (byte)77, 123.23f);
                  
          testPacket(req, PacketSupport.REQ_CONSUMER_CHANGERATE);                           
       }
@@ -672,7 +672,7 @@
       public void testBrowserNextMessageRequest() throws Exception
       { 
          RequestSupport req =
-            new BrowserNextMessageRequest(23, (byte)77);
+            new BrowserNextMessageRequest("23", (byte)77);
                  
          testPacket(req, PacketSupport.REQ_BROWSER_NEXTMESSAGE);                           
       }
@@ -680,7 +680,7 @@
       public void testBrowserHasNextMessageRequest() throws Exception
       { 
          RequestSupport req =
-            new BrowserHasNextMessageRequest(23, (byte)77);
+            new BrowserHasNextMessageRequest("23", (byte)77);
                  
          testPacket(req, PacketSupport.REQ_BROWSER_HASNEXTMESSAGE);                           
       }
@@ -688,7 +688,7 @@
       public void testBrowserNextMessageBlockRequest() throws Exception
       { 
          RequestSupport req =
-            new BrowserNextMessageBlockRequest(23, (byte)77, 123);
+            new BrowserNextMessageBlockRequest("23", (byte)77, 123);
                  
          testPacket(req, PacketSupport.REQ_BROWSER_NEXTMESSAGEBLOCK);                           
       }
@@ -696,14 +696,14 @@
       
       public void testClosingRequest() throws Exception
       { 
-         RequestSupport req =  new ClosingRequest(23, (byte)77);
+         RequestSupport req =  new ClosingRequest("23", (byte)77);
                  
          testPacket(req, PacketSupport.REQ_CLOSING);                           
       }
       
       public void testCloseRequest() throws Exception
       { 
-         RequestSupport req =  new CloseRequest(23, (byte)77);
+         RequestSupport req =  new CloseRequest("23", (byte)77);
                  
          testPacket(req, PacketSupport.REQ_CLOSE);                           
       }
@@ -749,7 +749,7 @@
       
       public void testConnectionCreateSessionDelegateResponse() throws Exception
       { 
-         ClientSessionDelegate del = new ClientSessionDelegate(786, 1000);
+         ClientSessionDelegate del = new ClientSessionDelegate("786", 1000);
          
          ResponseSupport resp =
             new ConnectionCreateSessionDelegateResponse(del);
@@ -781,7 +781,7 @@
       
       public void testSessionCreateConsumerDelegateResponse() throws Exception
       { 
-         ClientConsumerDelegate del = new ClientConsumerDelegate(786, 13123, 213, 0);
+         ClientConsumerDelegate del = new ClientConsumerDelegate("786", 13123, 213, 0);
          
          ResponseSupport resp =
             new SessionCreateConsumerDelegateResponse(del);
@@ -792,7 +792,7 @@
       
       public void testSessionCreateBrowserDelegateResponse() throws Exception
       { 
-         ClientBrowserDelegate del = new ClientBrowserDelegate(786);
+         ClientBrowserDelegate del = new ClientBrowserDelegate("786");
          
          ResponseSupport resp =
             new SessionCreateBrowserDelegateResponse(del);

Added: trunk/tests/src/org/jboss/test/messaging/jms/clustering/ChangeFailoverNodeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/ChangeFailoverNodeTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/ChangeFailoverNodeTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,495 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.messaging.jms.clustering;
+
+import javax.jms.Connection;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.jboss.jms.client.FailoverEvent;
+import org.jboss.jms.client.JBossConnection;
+import org.jboss.jms.client.JBossConnectionFactory;
+import org.jboss.test.messaging.tools.ServerManagement;
+
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>8 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class ChangeFailoverNodeTest extends ClusteringTestBase
+{
+   
+   // Constants -----------------------------------------------------
+   
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   // Constructors --------------------------------------------------
+   
+	
+	
+   public ChangeFailoverNodeTest(String name)
+   {
+      super(name);
+   }
+   
+   // Public --------------------------------------------------------
+   
+//   public void testKillFailoverNodeTransactional() throws Exception
+//   {
+//   	this.killFailoverNode(true);
+//   }
+//   
+//   public void testKillFailoverNodeNonTransactional() throws Exception
+//   {
+//   	this.killFailoverNode(false);
+//   }
+   
+   
+   
+   public void testStopFailoverNodeTransactional() throws Exception
+   {
+   	this.stopFailoverNode(true);
+   }
+   
+   public void testStopFailoverNodeNonTransactional() throws Exception
+   {
+   	this.stopFailoverNode(false);
+   }
+      
+  
+   
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   protected void setUp() throws Exception
+   {
+      nodeCount = 4;
+
+      super.setUp();
+
+      log.debug("setup done");
+   }
+   
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+   }
+   
+   // Private -------------------------------------------------------
+
+   private void killFailoverNode(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn1 = createConnectionOnServer(factory,1);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+      	
+         Session sessSend = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      		
+      	MessageProducer prod1 = sessSend.createProducer(queue[1]);
+      	
+      	final int numMessages = 10;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message" + i);
+      		
+      		prod1.send(tm);      		
+      	}
+      	
+      	Session sess1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      
+      	
+      	conn1.start();
+      	
+      	TextMessage tm = null;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		tm = (TextMessage)cons1.receive(2000);
+      		
+      		assertNotNull(tm);
+      		
+      		assertEquals("message" + i, tm.getText());
+      	}
+      	
+      	//Don't ack
+      	
+      	//We kill the failover node for node 1
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Killing failover node:" + failoverNodeId);
+      	
+      	ServerManagement.kill(failoverNodeId);
+      	
+      	log.info("Killed failover node");
+      	
+      	Thread.sleep(5000);
+      	
+      	//Now kill node 1
+      	
+      	failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Failover node id is now " + failoverNodeId);
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+                  
+         //Now ack
+         if (transactional)
+         {
+         	sess1.commit();
+         }
+         else
+         {
+         	tm.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess1.close();
+         
+         log.info("closed");
+         
+	      sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      
+	      log.info("created new session");
+      	
+      	cons1 = sess1.createConsumer(queue[1]);
+      	
+      	log.info("Created consumer");
+      	
+         //Messages should be gone
+      	
+         tm = (TextMessage)cons1.receive(5000);
+      		
+      	assertNull(tm);      		
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+      }
+   }
+   
+   
+   private void stopFailoverNode(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn1 = createConnectionOnServer(factory,1);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+      	
+         Session sessSend = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      		
+      	MessageProducer prod1 = sessSend.createProducer(queue[1]);
+      	
+      	final int numMessages = 10;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message" + i);
+      		
+      		prod1.send(tm);      		
+      	}
+      	
+      	Session sess1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      
+      	
+      	conn1.start();
+      	
+      	TextMessage tm = null;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		tm = (TextMessage)cons1.receive(2000);
+      		
+      		assertNotNull(tm);
+      		
+      		assertEquals("message" + i, tm.getText());
+      	}
+      	
+      	//Don't ack
+      	
+      	//We kill the failover node for node 1
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Killing failover node:" + failoverNodeId);
+      	
+      	ServerManagement.stop(failoverNodeId);
+      	
+      	log.info("Killed failover node");
+      	
+      	Thread.sleep(5000);
+      	
+      	//Now kill node 1
+      	
+      	failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Failover node id is now " + failoverNodeId);
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+                  
+         //Now ack
+         if (transactional)
+         {
+         	sess1.commit();
+         }
+         else
+         {
+         	tm.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess1.close();
+         
+         log.info("closed");
+         
+	      sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      
+	      log.info("created new session");
+      	
+      	cons1 = sess1.createConsumer(queue[1]);
+      	
+      	log.info("Created consumer");
+      	
+         //Messages should be gone
+      	
+         tm = (TextMessage)cons1.receive(5000);
+      		
+      	assertNull(tm);      		
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+      }
+   }
+   
+   
+   private void changeFailoverNodeByAdd(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn1 = createConnectionOnServer(factory,1);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+      	
+         Session sessSend = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      		
+      	MessageProducer prod1 = sessSend.createProducer(queue[1]);
+      	
+      	final int numMessages = 10;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message" + i);
+      		
+      		prod1.send(tm);      		
+      	}
+      	
+      	Session sess1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      
+      	
+      	conn1.start();
+      	
+      	TextMessage tm = null;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		tm = (TextMessage)cons1.receive(2000);
+      		
+      		assertNotNull(tm);
+      		
+      		assertEquals("message" + i, tm.getText());
+      	}
+      	
+      	//Don't ack
+      	
+      	//We kill the failover node for node 1
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Killing failover node:" + failoverNodeId);
+      	
+      	ServerManagement.stop(failoverNodeId);
+      	
+      	log.info("Killed failover node");
+      	
+      	Thread.sleep(5000);
+      	
+      	//Now kill node 1
+      	
+      	failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Failover node id is now " + failoverNodeId);
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+                  
+         //Now ack
+         if (transactional)
+         {
+         	sess1.commit();
+         }
+         else
+         {
+         	tm.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess1.close();
+         
+         log.info("closed");
+         
+	      sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      
+	      log.info("created new session");
+      	
+      	cons1 = sess1.createConsumer(queue[1]);
+      	
+      	log.info("Created consumer");
+      	
+         //Messages should be gone
+      	
+         tm = (TextMessage)cons1.receive(5000);
+      		
+      	assertNull(tm);      		
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+      }
+   }
+   
+   
+   // Inner classes -------------------------------------------------
+   
+}

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteredConnectionFactoryTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteredConnectionFactoryTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteredConnectionFactoryTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -23,10 +23,7 @@
 package org.jboss.test.messaging.jms.clustering;
 
 import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.JMSException;
 
-import org.jboss.jms.client.JBossConnection;
 import org.jboss.jms.client.JBossConnectionFactory;
 import org.jboss.jms.exception.MessagingNetworkFailureException;
 import org.jboss.test.messaging.tools.ServerManagement;

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteringTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteringTestBase.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusteringTestBase.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -35,6 +35,8 @@
 import org.jboss.jms.client.FailoverEvent;
 import org.jboss.jms.client.FailoverListener;
 import org.jboss.jms.client.JBossConnection;
+import org.jboss.jms.client.JBossConnectionFactory;
+import org.jboss.jms.client.delegate.ClientClusteredConnectionFactoryDelegate;
 import org.jboss.jms.client.delegate.DelegateSupport;
 import org.jboss.jms.client.state.ConnectionState;
 import org.jboss.test.messaging.MessagingTestCase;
@@ -78,13 +80,20 @@
    {
       super(name);
    }
-
+   
    // Public ---------------------------------------------------------------------------------------
 
    // Package protected ----------------------------------------------------------------------------
 
    // Protected ------------------------------------------------------------------------------------
 
+   protected int getFailoverNodeForNode(JBossConnectionFactory factory, int nodeID)
+   {
+   	Integer l = (Integer)((ClientClusteredConnectionFactoryDelegate)(factory.getDelegate())).getFailoverMap().get(new Integer(nodeID));
+   	
+      return l.intValue();
+   }
+   
    protected void setUp() throws Exception
    {
       super.setUp();
@@ -158,7 +167,7 @@
          getRemotingClient().getInvoker().getLocator().getLocatorURI();
    }
 
-   protected int getObjectId(Connection conn)
+   protected String getObjectId(Connection conn)
    {
       return ((DelegateSupport) ((JBossConnection) conn).
          getDelegate()).getID();

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -33,6 +33,7 @@
 import javax.jms.Session;
 import javax.jms.TextMessage;
 
+import org.jboss.jms.client.JBossConnectionFactory;
 import org.jboss.test.messaging.tools.ServerManagement;
 
 
@@ -83,7 +84,175 @@
    {
       localQueue(true);
    }
+   
+   
+   public void testWithConnectionsOnAllNodesClientAck() throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
 
+      Connection conn0 = createConnectionOnServer(factory, 0);
+      
+      Connection conn1 = createConnectionOnServer(factory, 1);
+      
+      Connection conn2 = createConnectionOnServer(factory, 2);
+      
+      try
+      {
+      	conn0.start();
+      	
+      	conn1.start();
+      	
+      	conn2.start();
+      	
+      	//Send a load of messages on node 0
+      	      	         
+      	Session sess0_1 = conn0.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons0_1 = sess0_1.createConsumer(queue[0]);
+      	
+      	MessageProducer prod0 = sess0_1.createProducer(queue[0]);
+      	
+      	Set msgIds = new HashSet();
+      	
+      	final int numMessages = 60;
+      	      	      	 
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sess0_1.createTextMessage("message-" + i);
+      		
+      		prod0.send(tm);      		
+      	}
+      		
+      	TextMessage tm0_1 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm0_1 = (TextMessage)cons0_1.receive(5000000);
+      		
+      		assertNotNull(tm0_1);
+      		
+      		msgIds.add(tm0_1.getText());
+      	}
+      	
+      	cons0_1.close();
+      	
+      	Session sess0_2 = conn0.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons0_2 = sess0_2.createConsumer(queue[0]);
+      	
+      	TextMessage tm0_2 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm0_2 = (TextMessage)cons0_2.receive(5000000);
+      		
+      		assertNotNull(tm0_2);
+      		
+      		msgIds.add(tm0_2.getText());
+      	}
+      	
+      	cons0_2.close();
+      	
+      	
+      	//Two on node 1
+      	
+      	Session sess1_1 = conn1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1_1 = sess1_1.createConsumer(queue[1]);      	
+      	
+      	TextMessage tm1_1 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm1_1 = (TextMessage)cons1_1.receive(5000000);
+      		
+      		assertNotNull(tm1_1);
+      		
+      		msgIds.add(tm1_1.getText());
+      	}
+      	
+      	cons1_1.close();
+     
+      	Session sess1_2 = conn1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1_2 = sess1_2.createConsumer(queue[1]);
+      	
+      	TextMessage tm1_2 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm1_2 = (TextMessage)cons1_2.receive(5000000);
+      		      		      		
+      		assertNotNull(tm1_2);
+      		
+      		msgIds.add(tm1_2.getText());
+      	}
+      	
+      	cons1_2.close();
+      	
+      	
+      	//Two on node 2
+      	
+      	Session sess2_1 = conn2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons2_1 = sess2_1.createConsumer(queue[2]);
+      	
+      	TextMessage tm2_1 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm2_1 = (TextMessage)cons2_1.receive(5000000);
+      		
+      		assertNotNull(tm2_1);
+      		
+      		msgIds.add(tm2_1.getText());
+      	}
+      	
+      	cons2_1.close();
+      	
+      	Session sess2_2 = conn2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons2_2 = sess2_2.createConsumer(queue[2]);
+      	
+      	TextMessage tm2_2 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm2_2 = (TextMessage)cons2_2.receive(5000000);
+      		
+      		assertNotNull(tm2_2);
+      		
+      		msgIds.add(tm2_2.getText());
+      	}
+      	
+      	cons2_2.close();
+      	
+      	assertEquals(numMessages, msgIds.size());
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		assertTrue(msgIds.contains("message-" + i));
+      	}      	      
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+         
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+         
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+      }
+   }
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/FailoverTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/FailoverTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/FailoverTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -22,10 +22,7 @@
 import org.jboss.jms.client.FailoverEvent;
 import org.jboss.jms.client.JBossConnection;
 import org.jboss.jms.client.delegate.ClientConnectionDelegate;
-import org.jboss.jms.client.delegate.DelegateSupport;
 import org.jboss.jms.client.remoting.JMSRemotingConnection;
-import org.jboss.jms.client.state.ConnectionState;
-import org.jboss.jms.exception.MessagingTransactionRolledBackException;
 import org.jboss.test.messaging.tools.ServerManagement;
 import org.jboss.test.messaging.tools.aop.PoisonInterceptor;
 
@@ -145,13 +142,23 @@
          log.info("failover completed");
 
          assertEquals(0, getServerId(conn));
+         
+         log.info("here1");
 
          // use the old session to send/receive a message
          session.createProducer(queue[0]).send(session.createTextMessage("blik"));
+         
+         log.info("here 2");
 
-         TextMessage m = (TextMessage)session.createConsumer(queue[0]).receive(2000);
+         TextMessage m = (TextMessage)session.createConsumer(queue[0]).receive(5000);
+         
+         log.info("Here3: " + m);
 
+         assertNotNull(m);
+         
          assertEquals("blik", m.getText());
+         
+         log.info("here4");
       }
       finally
       {
@@ -1036,96 +1043,95 @@
       }
    }
 
-   // Commented out until http://jira.jboss.org/jira/browse/JBMESSAGING-883
-//   public void testTransactedSessionWithAcknowledgmentsCommitOnFailover() throws Exception
-//   {
-//      Connection conn = null;
-//
-//      try
-//      {
-//         // skip connection to node 0
-//         conn = cf.createConnection();
-//         conn.close();
-//
-//         // create a connection to node 1
-//         conn = cf.createConnection();
-//
-//         conn.start();
-//
-//         assertEquals(1, getServerId(conn));
-//
-//         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);
-//
-//         // send 2 messages (one persistent and one non-persistent)
-//
-//         MessageProducer prod = session.createProducer(queue[1]);
-//
-//         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-//         prod.send(session.createTextMessage("clik-persistent"));
-//         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
-//         prod.send(session.createTextMessage("clak-non-persistent"));
-//
-//         session.commit();
-//
-//         // close the producer
+   public void testTransactedSessionWithAcknowledgmentsCommitOnFailover() throws Exception
+   {
+      Connection conn = null;
+
+      try
+      {
+         // skip connection to node 0
+         conn = cf.createConnection();
+         conn.close();
+
+         // create a connection to node 1
+         conn = cf.createConnection();
+
+         conn.start();
+
+         assertEquals(1, getServerId(conn));
+
+         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);
+
+         // send 2 messages (one persistent and one non-persistent)
+
+         MessageProducer prod = session.createProducer(queue[1]);
+
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+         prod.send(session.createTextMessage("clik-persistent"));
+         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
+         prod.send(session.createTextMessage("clak-non-persistent"));
+
+         session.commit();
+
+         // close the producer
    
-//         prod.close();
-//
-//         // create a consumer and receive messages, but don't acknowledge
-//
-//         MessageConsumer cons = session.createConsumer(queue[1]);
-//         TextMessage clik = (TextMessage)cons.receive(2000);
-//         assertEquals("clik-persistent", clik.getText());
-//         TextMessage clak = (TextMessage)cons.receive(2000);
-//         assertEquals("clak-non-persistent", clak.getText());
-//
-//         // register a failover listener
-//         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
-//         ((JBossConnection)conn).registerFailoverListener(failoverListener);
-//
-//         log.debug("killing node 1 ....");
-//
-//         ServerManagement.kill(1);
-//
-//         log.info("########");
-//         log.info("######## KILLED NODE 1");
-//         log.info("########");
-//
-//         // wait for the client-side failover to complete
-//
-//         while(true)
-//         {
-//            FailoverEvent event = failoverListener.getEvent(120000);
-//            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
-//            {
-//               break;
-//            }
-//            if (event == null)
-//            {
-//               fail("Did not get expected FAILOVER_COMPLETED event");
-//            }
-//         }
-//
-//         // failover complete
-//         log.info("failover completed");
-//
-//         assertEquals(0, getServerId(conn));
-//
-//         // acknowledge the messages
-//         session.commit();
-//
-//         // make sure no messages are left in the queue
-//         Message m = cons.receive(1000);
-//         assertNull(m);
-//      }
-//      finally
-//      {
-//         if (conn != null)
-//         {
-//            conn.close();
-//         }
-//      }
-//   }
+         prod.close();
+
+         // create a consumer and receive messages, but don't acknowledge
+
+         MessageConsumer cons = session.createConsumer(queue[1]);
+         TextMessage clik = (TextMessage)cons.receive(2000);
+         assertEquals("clik-persistent", clik.getText());
+         TextMessage clak = (TextMessage)cons.receive(2000);
+         assertEquals("clak-non-persistent", clak.getText());
+
+         // register a failover listener
+         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn).registerFailoverListener(failoverListener);
+
+         log.debug("killing node 1 ....");
+
+         ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+
+         // failover complete
+         log.info("failover completed");
+
+         assertEquals(0, getServerId(conn));
+
+         // acknowledge the messages
+         session.commit();
+
+         // make sure no messages are left in the queue
+         Message m = cons.receive(1000);
+         assertNull(m);
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      }
+   }
    
   
    public void testTransactedSessionWithAcknowledgmentsRollbackOnFailover() throws Exception
@@ -1534,12 +1540,11 @@
       }
    }
 
-   // TODO:Reactivate as soon http://jira.jboss.org/jira/browse/JBMESSAGING-883 is done
    // http://jira.jboss.org/jira/browse/JBMESSAGING-808
-//   public void testFailureRightAfterACK() throws Exception
-//   {
-//      failureOnInvocation(PoisonInterceptor.FAIL_AFTER_ACKNOWLEDGE_DELIVERY);
-//   }
+   public void testFailureRightAfterACK() throws Exception
+   {
+      failureOnInvocation(PoisonInterceptor.FAIL_AFTER_ACKNOWLEDGE_DELIVERY);
+   }
 
    // http://jira.jboss.org/jira/browse/JBMESSAGING-808
    public void testFailureRightBeforeACK() throws Exception
@@ -1559,74 +1564,74 @@
 
    // Commented out until this is complete:
    // http://jira.jboss.org/jira/browse/JBMESSAGING-604
-//   public void testFailureRightAfterSendTransaction() throws Exception
-//   {
-//      Connection conn = null;
-//      Connection conn0 = null;
-//
-//      try
-//      {
-//         conn0 = cf.createConnection();
-//
-//         assertEquals(0, ((JBossConnection)conn0).getServerID());
-//
-//         conn0.close();
-//
-//         conn = cf.createConnection();
-//
-//         assertEquals(1, getServerId(conn));
-//
-//         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
-//         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
-//         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
-//            getDelegate()).getRemotingConnection();
-//         rc.removeConnectionListener();
-//
-//         // poison the server
-//         ServerManagement.poisonTheServer(1, PoisonInterceptor.FAIL_AFTER_SENDTRANSACTION);
-//
-//         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);
-//
-//         conn.start();
-//
-//         MessageProducer producer = session.createProducer(queue[0]);
-//
-//         producer.setDeliveryMode(DeliveryMode.PERSISTENT);
-//
-//         MessageConsumer consumer = session.createConsumer(queue[0]);
-//
-//         producer.send(session.createTextMessage("before-poison1"));
-//         producer.send(session.createTextMessage("before-poison2"));
-//         producer.send(session.createTextMessage("before-poison3"));
-//         session.commit();
-//
-//         Thread.sleep(2000);
-//
-//         for (int i = 1; i <= 10; i++)
-//         {
-//            TextMessage tm = (TextMessage) consumer.receive(5000);
-//
-//            assertNotNull(tm);
-//
-//            assertEquals("before-poison" + i, tm.getText());
-//         }
-//
-//         assertNull(consumer.receive(1000));
-//
-//      }
-//      finally
-//      {
-//         if (conn != null)
-//         {
-//            conn.close();
-//         }
-//         if (conn0 != null)
-//         {
-//            conn0.close();
-//         }
-//      }
-//   }
+   public void testFailureRightAfterSendTransaction() throws Exception
+   {
+      Connection conn = null;
+      Connection conn0 = null;
 
+      try
+      {
+         conn0 = cf.createConnection();
+
+         assertEquals(0, ((JBossConnection)conn0).getServerID());
+
+         conn0.close();
+
+         conn = cf.createConnection();
+
+         assertEquals(1, getServerId(conn));
+
+         // we "cripple" the remoting connection by removing ConnectionListener. This way, failures
+         // cannot be "cleanly" detected by the client-side pinger, and we'll fail on an invocation
+         JMSRemotingConnection rc = ((ClientConnectionDelegate)((JBossConnection)conn).
+            getDelegate()).getRemotingConnection();
+         rc.removeConnectionListener();
+
+         // poison the server
+         ServerManagement.poisonTheServer(1, PoisonInterceptor.FAIL_AFTER_SENDTRANSACTION);
+
+         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);
+
+         conn.start();
+
+         MessageProducer producer = session.createProducer(queue[0]);
+
+         producer.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+         MessageConsumer consumer = session.createConsumer(queue[0]);
+
+         producer.send(session.createTextMessage("before-poison1"));
+         producer.send(session.createTextMessage("before-poison2"));
+         producer.send(session.createTextMessage("before-poison3"));
+         session.commit();
+
+         Thread.sleep(2000);
+
+         for (int i = 1; i <= 10; i++)
+         {
+            TextMessage tm = (TextMessage) consumer.receive(5000);
+
+            assertNotNull(tm);
+
+            assertEquals("before-poison" + i, tm.getText());
+         }
+
+         assertNull(consumer.receive(1000));
+
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+      }
+   }
+
    public void testCloseConsumer() throws Exception
    {
       Connection conn0 = null;
@@ -1775,272 +1780,129 @@
       }
    }
 
-   //See http://jira.jboss.org/jira/browse/JBMESSAGING-883
-   //This is commented out until we have a better fix in 1.2.1
-//   public void testFailoverDeliveryRecoveryTransacted() throws Exception
-//   {
-//      Connection conn0 = null;
-//      Connection conn1 = null;
-//
-//      try
-//      {
-//         conn0 = cf.createConnection();
-//
-//         // Objects Server1
-//         conn1 = cf.createConnection();
-//
-//         assertEquals(1, ((JBossConnection)conn1).getServerID());
-//
-//         Session session1 = conn1.createSession(true, Session.SESSION_TRANSACTED);
-//         
-//         Session session2 = conn1.createSession(true, Session.SESSION_TRANSACTED);
-//
-//         MessageConsumer cons1 = session1.createConsumer(queue[1]);
-//         
-//         MessageConsumer cons2 = session2.createConsumer(queue[1]);
-//         
-//         MessageProducer prod = session1.createProducer(queue[1]);
-//         
-//         conn1.start();
-//                  
-//         TextMessage tm1 = session1.createTextMessage("message1");
-//         
-//         TextMessage tm2 = session1.createTextMessage("message2");
-//         
-//         TextMessage tm3 = session1.createTextMessage("message3");
-//         
-//         prod.send(tm1);
-//         
-//         prod.send(tm2);
-//         
-//         prod.send(tm3);
-//         
-//         session1.commit();
-//                           
-//         TextMessage rm1 = (TextMessage)cons1.receive(1000);
-//         
-//         assertNotNull(rm1);
-//         
-//         assertEquals(tm1.getText(), rm1.getText());
-//                                    
-//         TextMessage rm2 = (TextMessage)cons2.receive(1000);
-//         
-//         assertNotNull(rm2);
-//         
-//         assertEquals(tm2.getText(), rm2.getText());
-//         
-//         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
-//         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
-//
-//         log.debug("killing node 1 ....");
-//
-//         ServerManagement.kill(1);
-//
-//         log.info("########");
-//         log.info("######## KILLED NODE 1");
-//         log.info("########");
-//
-//         // wait for the client-side failover to complete
-//
-//         while(true)
-//         {
-//            FailoverEvent event = failoverListener.getEvent(120000);
-//            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
-//            {
-//               break;
-//            }
-//            if (event == null)
-//            {
-//               fail("Did not get expected FAILOVER_COMPLETED event");
-//            }
-//         }
-//
-//         // failover complete
-//         log.info("failover completed");
-//         
-//
-//         //now commit
-//         
-//         session1.commit();
-//         
-//         session2.commit();
-//         
-//         session1.close();
-//         
-//         session2.close();;
-//         
-//         Session session3 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
-//         
-//         MessageConsumer cons3 = session3.createConsumer(queue[0]);
-//         
-//         TextMessage rm3 = (TextMessage)cons3.receive(2000);
-//         
-//         assertNotNull(rm3);
-//         
-//         assertEquals(tm3.getText(), rm3.getText());
-//         
-//         rm3 = (TextMessage)cons3.receive(2000);
-//         
-//         assertNull(rm3);
-//
-//         
-//      }
-//      finally
-//      {
-//         if (conn1 != null)
-//         {
-//            conn1.close();
-//         }
-//
-//         if (conn0 != null)
-//         {
-//            conn0.close();
-//         }
-//      }
-//   }
-   
-   // See http://jira.jboss.org/jira/browse/JBMESSAGING-883
-   // This tests our current behaviour - which is throwing an exception
-   // This will change in 1.2.1
-//   public void testFailoverDeliveryRecoveryTransacted() throws Exception
-//   {
-//      Connection conn0 = null;
-//      Connection conn1 = null;
-//
-//      try
-//      {
-//         conn0 = cf.createConnection();
-//
-//         conn1 = cf.createConnection();
-//
-//         assertEquals(1, ((JBossConnection)conn1).getServerID());
-//
-//         Session session1 = conn1.createSession(true, Session.SESSION_TRANSACTED);
-//
-//         Session session2 = conn1.createSession(true, Session.SESSION_TRANSACTED);
-//
-//         MessageConsumer cons1 = session1.createConsumer(queue[1]);
-//
-//         MessageConsumer cons2 = session2.createConsumer(queue[1]);
-//
-//         MessageProducer prod = session1.createProducer(queue[1]);
-//
-//         conn1.start();
-//
-//         TextMessage tm1 = session1.createTextMessage("message1");
-//
-//         TextMessage tm2 = session1.createTextMessage("message2");
-//
-//         TextMessage tm3 = session1.createTextMessage("message3");
-//
-//         prod.send(tm1);
-//
-//         prod.send(tm2);
-//
-//         prod.send(tm3);
-//
-//         session1.commit();
-//
-//         TextMessage rm1 = (TextMessage)cons1.receive(1000);
-//
-//         assertNotNull(rm1);
-//
-//         assertEquals(tm1.getText(), rm1.getText());
-//
-//         TextMessage rm2 = (TextMessage)cons2.receive(1000);
-//
-//         assertNotNull(rm2);
-//
-//         assertEquals(tm2.getText(), rm2.getText());
-//
-//         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
-//         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
-//
-//         log.debug("killing node 1 ....");
-//
-//         ServerManagement.kill(1);
-//
-//         log.info("########");
-//         log.info("######## KILLED NODE 1");
-//         log.info("########");
-//
-//         // wait for the client-side failover to complete
-//
-//         while(true)
-//         {
-//            FailoverEvent event = failoverListener.getEvent(120000);
-//            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
-//            {
-//               break;
-//            }
-//            if (event == null)
-//            {
-//               fail("Did not get expected FAILOVER_COMPLETED event");
-//            }
-//         }
-//
-//         // failover complete
-//         log.info("failover completed");
-//
-//
-//         //now commit
-//
-//         try
-//         {
-//            session1.commit();
-//
-//            fail();
-//         }
-//         catch (MessagingTransactionRolledBackException e)
-//         {
-//            //Ok
-//         }
-//
-//         try
-//         {
-//            session2.commit();
-//
-//            fail();
-//         }
-//         catch (MessagingTransactionRolledBackException e)
-//         {
-//            //Ok
-//         }
-//
-////         session1.close();
-////
-////         session2.close();;
-////
-////         Session session3 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
-////
-////         MessageConsumer cons3 = session3.createConsumer(queue[0]);
-////
-////         TextMessage rm3 = (TextMessage)cons3.receive(2000);
-////
-////         assertNotNull(rm3);
-////
-////         assertEquals(tm3.getText(), rm3.getText());
-////
-////         rm3 = (TextMessage)cons3.receive(2000);
-////
-////         assertNull(rm3);
-//
-//
-//      }
-//      finally
-//      {
-//         if (conn1 != null)
-//         {
-//            conn1.close();
-//         }
-//
-//         if (conn0 != null)
-//         {
-//            conn0.close();
-//         }
-//      }
-//   }
+   public void testFailoverDeliveryRecoveryTransacted() throws Exception
+   {
+      Connection conn0 = null;
+      Connection conn1 = null;
 
+      try
+      {
+         conn0 = cf.createConnection();
+
+         // Objects Server1
+         conn1 = cf.createConnection();
+
+         assertEquals(1, ((JBossConnection)conn1).getServerID());
+
+         Session session1 = conn1.createSession(true, Session.SESSION_TRANSACTED);
+         
+         Session session2 = conn1.createSession(true, Session.SESSION_TRANSACTED);
+
+         MessageConsumer cons1 = session1.createConsumer(queue[1]);
+         
+         MessageConsumer cons2 = session2.createConsumer(queue[1]);
+         
+         MessageProducer prod = session1.createProducer(queue[1]);
+         
+         conn1.start();
+                  
+         TextMessage tm1 = session1.createTextMessage("message1");
+         
+         TextMessage tm2 = session1.createTextMessage("message2");
+         
+         TextMessage tm3 = session1.createTextMessage("message3");
+         
+         prod.send(tm1);
+         
+         prod.send(tm2);
+         
+         prod.send(tm3);
+         
+         session1.commit();
+                           
+         TextMessage rm1 = (TextMessage)cons1.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals(tm1.getText(), rm1.getText());
+                                    
+         TextMessage rm2 = (TextMessage)cons2.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals(tm2.getText(), rm2.getText());
+         
+         SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+
+         log.debug("killing node 1 ....");
+
+         ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+
+         // failover complete
+         log.info("failover completed");
+         
+
+         //now commit
+         
+         session1.commit();
+         
+         session2.commit();
+         
+         session1.close();
+         
+         session2.close();;
+         
+         Session session3 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons3 = session3.createConsumer(queue[0]);
+         
+         TextMessage rm3 = (TextMessage)cons3.receive(2000);
+         
+         assertNotNull(rm3);
+         
+         assertEquals(tm3.getText(), rm3.getText());
+         
+         rm3 = (TextMessage)cons3.receive(2000);
+         
+         assertNull(rm3);
+
+         
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+      }
+   }
+    
+
    // Package protected ----------------------------------------------------------------------------
 
    // Protected ------------------------------------------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/LargeClusterTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/LargeClusterTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/LargeClusterTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -68,7 +68,7 @@
 
       ServerManagement.addNotificationListener(4, postOfficeObjectName, clusterEvent);
 
-      // We start programatically the eight node.
+      // We start programatically the eighth node.
 
       ServerManagement.start(7, "all");
 

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/MultipleFailoverTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/MultipleFailoverTest.java	2007-07-08 04:43:50 UTC (rev 2856)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/MultipleFailoverTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -133,7 +133,9 @@
          log.info("########");
 
          ServerManagement.start(3, "all", false);
+         log.info("deploying queue on3");
          ServerManagement.deployQueue("testDistributedQueue", 3);
+         log.info("deployed it");
 
          // send/receive message
          prod.send(s.createTextMessage("step5"));
@@ -181,6 +183,8 @@
          m = (TextMessage)cons.receive();
          assertNotNull(m);
          assertEquals("step8", m.getText());
+         
+         log.info("Got to the end");
 
       }
       finally

Added: trunk/tests/src/org/jboss/test/messaging/jms/clustering/RecoverDeliveriesTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/RecoverDeliveriesTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/RecoverDeliveriesTest.java	2007-07-08 13:21:39 UTC (rev 2857)
@@ -0,0 +1,790 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.messaging.jms.clustering;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.jboss.jms.client.FailoverEvent;
+import org.jboss.jms.client.JBossConnection;
+import org.jboss.jms.client.JBossConnectionFactory;
+import org.jboss.test.messaging.tools.ServerManagement;
+
+
+/**
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: $</tt>7 Jul 2007
+ *
+ * $Id: $
+ *
+ */
+public class RecoverDeliveriesTest extends ClusteringTestBase
+{
+   
+   // Constants -----------------------------------------------------
+   
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   // Constructors --------------------------------------------------
+   
+	
+	/*
+	 * Need to test acknowledging with and without transaction
+	 * 
+	 * Test timeout
+	 * 
+	 * Test multiple failover
+	 * 
+	 * Test nothing left in map or area
+	 * 
+	 * Multiple queues in same session
+	 * 
+	 * Queues
+	 * 
+	 * multiple durable subs on same topic
+	 * 
+	 * Temporary queues
+	 */
+	
+   public RecoverDeliveriesTest(String name)
+   {
+      super(name);
+   }
+   
+   // Public --------------------------------------------------------
+   
+   public void testSimpleTransactional() throws Exception
+   {
+   	this.simple(true);
+   }
+   
+   public void testSimpleNonTransactional() throws Exception
+   {
+   	this.simple(false);
+   }
+      
+   public void testWithConnectionOnNewNodeTransactional() throws Exception
+   {
+   	connectionOnNewNode(true);
+   }
+   
+   public void testWithConnectionOnNewNodeNonTransactional() throws Exception
+   {
+   	connectionOnNewNode(false);
+   }
+         
+   public void testWithConnectionsOnAllNodesTransactional() throws Exception
+   {
+   	connectionsOnAllNodes(true);
+   }
+   
+   public void testWithConnectionsOnAllNodesNonTransactional() throws Exception
+   {
+   	connectionsOnAllNodes(false);
+   }     
+   
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   protected void setUp() throws Exception
+   {
+      nodeCount = 3;
+
+      super.setUp();
+
+      log.debug("setup done");
+   }
+   
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+   }
+   
+   // Private -------------------------------------------------------
+
+   private void simple(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn1 = createConnectionOnServer(factory,1);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+      	
+         Session sessSend = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      		
+      	MessageProducer prod1 = sessSend.createProducer(queue[1]);
+      	
+      	final int numMessages = 10;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message" + i);
+      		
+      		prod1.send(tm);      		
+      	}
+      	
+      	Session sess1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      
+      	
+      	conn1.start();
+      	
+      	TextMessage tm = null;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		tm = (TextMessage)cons1.receive(2000);
+      		
+      		assertNotNull(tm);
+      		
+      		assertEquals("message" + i, tm.getText());
+      	}
+      	
+      	//Don't ack
+      	
+      	//Now kill server
+      	
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+                  
+         //Now ack
+         if (transactional)
+         {
+         	sess1.commit();
+         }
+         else
+         {
+         	tm.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess1.close();
+         
+         log.info("closed");
+         
+	      sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      
+	      log.info("created new session");
+      	
+      	cons1 = sess1.createConsumer(queue[1]);
+      	
+      	log.info("Created consumer");
+      	
+         //Messages should be gone
+      	
+         tm = (TextMessage)cons1.receive(5000);
+      		
+      	assertNull(tm);      		
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+      }
+   }
+   
+   
+   private void killFailoverNode(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn1 = createConnectionOnServer(factory,1);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+      	
+         Session sessSend = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      		
+      	MessageProducer prod1 = sessSend.createProducer(queue[1]);
+      	
+      	final int numMessages = 10;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message" + i);
+      		
+      		prod1.send(tm);      		
+      	}
+      	
+      	Session sess1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      
+      	
+      	conn1.start();
+      	
+      	TextMessage tm = null;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		tm = (TextMessage)cons1.receive(2000);
+      		
+      		assertNotNull(tm);
+      		
+      		assertEquals("message" + i, tm.getText());
+      	}
+      	
+      	//Don't ack
+      	
+      	//We kill the failover node for node 1
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Killing failover node:" + failoverNodeId);
+      	
+      	ServerManagement.kill(failoverNodeId);
+      	
+      	log.info("Killed failover node");
+      	
+      	Thread.sleep(5000);
+      	
+      	//Now kill 
+      	
+      	failoverNodeId = this.getFailoverNodeForNode(factory, 1);
+      	
+      	log.info("Failover node id is now " + failoverNodeId);
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+                  
+         //Now ack
+         if (transactional)
+         {
+         	sess1.commit();
+         }
+         else
+         {
+         	tm.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess1.close();
+         
+         log.info("closed");
+         
+	      sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      
+	      log.info("created new session");
+      	
+      	cons1 = sess1.createConsumer(queue[1]);
+      	
+      	log.info("Created consumer");
+      	
+         //Messages should be gone
+      	
+         tm = (TextMessage)cons1.receive(5000);
+      		
+      	assertNull(tm);      		
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+      }
+   }
+   
+   
+   
+   private void connectionOnNewNode(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn1 = createConnectionOnServer(factory,1);
+      
+      Connection conn2 = createConnectionOnServer(factory,2);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+      	
+         Session sessSend = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+      	MessageProducer prod1 = sessSend.createProducer(queue[1]);
+      	
+      	final int numMessages = 10;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message" + i);
+      		
+      		prod1.send(tm);      		
+      	}
+      	
+      	Session sess1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      	      	
+      	conn1.start();
+      	
+      	TextMessage tm = null;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		tm = (TextMessage)cons1.receive(2000);
+      		
+      		assertNotNull(tm);
+      		
+      		assertEquals("message" + i, tm.getText());
+      	}
+      	
+      	//Create another connection on server 2 with a consumer
+      	
+      	Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons2 = sess2.createConsumer(queue[2]);
+      	
+      	conn2.start();
+      	
+      	//Don't ack
+      	
+      	//Now kill server
+      	
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);      	
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+                  
+         if (transactional)
+         {
+         	sess1.commit();
+         }
+         else
+         {
+	         //Now ack
+	         tm.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess1.close();
+         
+         log.info("closed");
+         
+	      sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      
+	      log.info("created new session");
+      	
+      	cons1 = sess1.createConsumer(queue[1]);
+      	
+      	log.info("Created consumer");
+      	
+         //Messages should be gone
+      	
+         tm = (TextMessage)cons1.receive(5000);
+      		
+      	assertNull(tm);      		
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+         
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+      }
+   }
+   
+   private void connectionsOnAllNodes(boolean transactional) throws Exception
+   {
+   	JBossConnectionFactory factory = (JBossConnectionFactory) ic[0].lookup("/ClusteredConnectionFactory");
+
+      Connection conn0 = createConnectionOnServer(factory, 0);
+      
+      Connection conn1 = createConnectionOnServer(factory, 1);
+      
+      Connection conn2 = createConnectionOnServer(factory, 2);
+ 
+      try
+      {
+      	SimpleFailoverListener failoverListener = new SimpleFailoverListener();
+         ((JBossConnection)conn1).registerFailoverListener(failoverListener);
+         
+      	conn0.start();
+      	
+      	conn1.start();
+      	
+      	conn2.start();
+      	
+      	//Send a load of messages on node 0
+      	
+      	Session sessSend = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      	
+      	MessageProducer prod0 = sessSend.createProducer(queue[0]);
+      	
+      	      	
+      	final int numMessages = 60;
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		TextMessage tm = sessSend.createTextMessage("message-" + i);
+      		
+      		prod0.send(tm);      		
+      	}
+      	      	
+      	      	         
+      	Session sess0_1 = conn0.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons0_1 = sess0_1.createConsumer(queue[0]);      	
+      	
+      	Set msgIds = new HashSet();
+      	      	      	
+      	TextMessage tm0_1 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm0_1 = (TextMessage)cons0_1.receive(5000000);
+      		
+      		assertNotNull(tm0_1);
+      		
+      		log.info("got:" + tm0_1.getText());      		
+      		
+      		msgIds.add(tm0_1.getText());
+      	}
+      	
+      	cons0_1.close();
+      	
+      	Session sess0_2 = conn0.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons0_2 = sess0_2.createConsumer(queue[0]);
+      	
+      	TextMessage tm0_2 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm0_2 = (TextMessage)cons0_2.receive(5000000);
+      		
+      		assertNotNull(tm0_2);
+      		
+      		log.info("got:" + tm0_2.getText());      		
+      		
+      		msgIds.add(tm0_2.getText());
+      	}
+      	
+      	cons0_2.close();
+      	
+      	
+      	//Two on node 1
+      	
+      	Session sess1_1 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1_1 = sess1_1.createConsumer(queue[1]);      	
+      	
+      	TextMessage tm1_1 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm1_1 = (TextMessage)cons1_1.receive(5000000);
+      		
+      		assertNotNull(tm1_1);
+      		
+      		log.info("got:" + tm1_1.getText());      		
+      		
+      		msgIds.add(tm1_1.getText());
+      	}
+      	
+      	cons1_1.close();
+      	
+      	Session sess1_2 = conn1.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1_2 = sess1_2.createConsumer(queue[1]);
+      	
+      	TextMessage tm1_2 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm1_2 = (TextMessage)cons1_2.receive(5000000);
+      		      		      		
+      		assertNotNull(tm1_2);
+      		
+      		log.info("got:" + tm1_2.getText());
+      		
+      		msgIds.add(tm1_2.getText());
+      	}
+      	
+      	cons1_2.close();
+      	
+      	
+      	//Two on node 2
+      	
+      	Session sess2_1 = conn2.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons2_1 = sess2_1.createConsumer(queue[2]);
+      	
+      	TextMessage tm2_1 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm2_1 = (TextMessage)cons2_1.receive(5000000);
+      		
+      		assertNotNull(tm2_1);
+      		
+      		log.info("got:" + tm2_1.getText());      		
+      		
+      		msgIds.add(tm2_1.getText());
+      	}
+      	
+      	cons2_1.close();
+      	
+      	Session sess2_2 = conn2.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.CLIENT_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons2_2 = sess2_2.createConsumer(queue[2]);
+      	
+      	TextMessage tm2_2 = null;
+      	
+      	for (int i = 0; i < numMessages / 6; i++)
+      	{
+      		tm2_2 = (TextMessage)cons2_2.receive(5000000);
+      		
+      		assertNotNull(tm2_2);
+      		
+      		log.info("got:" + tm2_2.getText());
+      		
+      		msgIds.add(tm2_2.getText());
+      	}
+      	
+      	cons2_2.close();
+      	
+      	assertEquals(numMessages, msgIds.size());
+      	
+      	for (int i = 0; i < numMessages; i++)
+      	{
+      		assertTrue(msgIds.contains("message-" + i));
+      	}
+      	
+      	//Don't ack
+      	
+      	//Now kill server
+      	
+      	int failoverNodeId = this.getFailoverNodeForNode(factory, 1);    
+      	
+      	log.info("Failover node is " + failoverNodeId);
+      	
+      	ServerManagement.kill(1);
+
+         log.info("########");
+         log.info("######## KILLED NODE 1");
+         log.info("########");
+
+         // wait for the client-side failover to complete
+
+         log.info("Waiting for failover to complete");
+         
+         while(true)
+         {
+            FailoverEvent event = failoverListener.getEvent(120000);
+            if (event != null && FailoverEvent.FAILOVER_COMPLETED == event.getType())
+            {
+               break;
+            }
+            if (event == null)
+            {
+               fail("Did not get expected FAILOVER_COMPLETED event");
+            }
+         }
+         
+         log.info("Failover completed");
+                           
+         log.info("server id is now " + getServerId(conn1));
+         
+         assertEquals(failoverNodeId, getServerId(conn1));
+         
+         log.info("ok, committing");
+                  
+         //Now ack
+         if (transactional)
+         {
+         	sess0_1.commit();
+         	sess0_2.commit();
+         	sess1_1.commit();
+         	sess1_2.commit();
+         	sess2_1.commit();
+         	sess2_2.commit();
+         }
+         else
+         {
+	         tm0_1.acknowledge();
+	         tm0_2.acknowledge();
+	         tm1_1.acknowledge();
+	         tm1_2.acknowledge();
+	         tm2_1.acknowledge();
+	         tm2_2.acknowledge();
+         }
+         
+         log.info("acked");
+         
+         sess0_1.close();
+         sess0_2.close();
+         sess1_1.close();
+         sess1_2.close();
+         sess2_1.close();
+         sess2_2.close();
+         
+         log.info("closed");
+         
+	      Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+	      	
+      	MessageConsumer cons0 = sess0.createConsumer(queue[0]);
+      	
+         Message msg = cons0.receive(5000);         
+      		
+      	assertNull(msg);      		
+      	
+      	Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+      	
+         msg = cons1.receive(5000);
+      		
+      	assertNull(msg);      		
+      	
+      	Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      	
+      	MessageConsumer cons2 = sess2.createConsumer(queue[2]);
+      	
+         msg = cons2.receive(5000);
+      		
+      	assertNull(msg);      		
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+         
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+         
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+      }
+   }
+   
+   // Inner classes -------------------------------------------------
+   
+}




More information about the jboss-cvs-commits mailing list