[jboss-cvs] JBoss Messaging SVN: r3341 - in trunk: docs/userguide/en/modules and 17 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Nov 19 09:34:57 EST 2007


Author: timfox
Date: 2007-11-19 09:34:57 -0500 (Mon, 19 Nov 2007)
New Revision: 3341

Added:
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java
Removed:
   trunk/src/etc/server/default/deploy/db2-persistence-service.xml
   trunk/src/etc/server/default/deploy/mysqlcluster-persistence-service.xml
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueDontUseXATest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTestBase.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueUseXATest.java
Modified:
   trunk/.classpath
   trunk/docs/userguide/en/modules/c_configuration.xml
   trunk/docs/userguide/en/modules/configuration.xml
   trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml
   trunk/src/etc/server/default/deploy/messaging-service.xml
   trunk/src/etc/server/default/deploy/mssql-persistence-service.xml
   trunk/src/etc/server/default/deploy/mysql-persistence-service.xml
   trunk/src/etc/server/default/deploy/oracle-persistence-service.xml
   trunk/src/etc/server/default/deploy/postgresql-persistence-service.xml
   trunk/src/etc/server/default/deploy/sybase-persistence-service.xml
   trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
   trunk/src/main/org/jboss/jms/client/container/ProducerAspect.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/destination/TopicService.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.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/server/messagecounter/MessageCounterManager.java
   trunk/src/main/org/jboss/messaging/core/contract/DeliveryObserver.java
   trunk/src/main/org/jboss/messaging/core/contract/Message.java
   trunk/src/main/org/jboss/messaging/core/contract/PersistenceManager.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/JDBCPersistenceManager.java
   trunk/src/main/org/jboss/messaging/core/impl/JDBCSupport.java
   trunk/src/main/org/jboss/messaging/core/impl/PagingChannelSupport.java
   trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/ClusterConnectionManager.java
   trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java
   trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java
   trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
   trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryObserver.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/BrowserTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/SecurityTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusterConnectionManagerTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/clustering/GroupManagementTest.java
   trunk/tests/src/org/jboss/test/messaging/tools/ServerManagement.java
   trunk/tests/src/org/jboss/test/messaging/tools/container/InVMInitialContextFactory.java
   trunk/tests/src/org/jboss/test/messaging/tools/container/MockJBossSecurityManager.java
   trunk/tests/src/org/jboss/test/messaging/tools/container/RMINamingDelegate.java
Log:
svn merge -r 3286:3340 https://svn.jboss.org/repos/messaging/branches/Branch_Stable


Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/.classpath	2007-11-19 14:34:57 UTC (rev 3341)
@@ -45,7 +45,6 @@
 	<classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/>
 	<classpathentry kind="var" path="ANT_HOME/lib/ant-junit.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/common/lib/jboss-common.jar"/>
-	<classpathentry kind="src" path=".apt_generated"/>
 	<classpathentry kind="lib" path="thirdparty/jbossas/core-libs/lib/jboss-j2ee.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/aop/lib/jboss-aop.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jbossas/core-libs/lib/jboss-system.jar"/>

Modified: trunk/docs/userguide/en/modules/c_configuration.xml
===================================================================
--- trunk/docs/userguide/en/modules/c_configuration.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/docs/userguide/en/modules/c_configuration.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1,53 +1,93 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF8"?>
 <chapter id="c_configuration">
    <title>JBoss Messaging Clustering Notes</title>
-   <para>JBoss Messaging clustering should work out of the box in most cases
-   with no configuration changes. It is however crucial that every node is
-   assigned a unique server id, as specified in the installation guide.</para>
-   <para>Every node deployed must have a unique id, including those in a
-   particular LAN cluster, and also those only linked by mesage
-   bridges.</para>
-   <para>JBoss Messaging clusters JMS queues and topics transparently across
-   the cluster. Messages sent to a distributed queue or topic on one node are
-   consumable on other nodes. To designate that a particular destination is
-   clustered simply set the clustered attribute in the destination deployment
-   descriptor to true.</para>
-   <para>JBoss Messaging balances messages between nodes, catering for faster
-   or slower consumers to efficiently balance processing load across the
-   cluster.</para>
-   <para>JBoss Messaging durable subscrtiptions can also be clustered. This
-   means multiple subscribers can consume from the same durable subscription
-   from different nodes of the cluster. A durable subscription will be
-   clustered if it's topic is clustered</para>
-   <para>JBoss Messaging also supports clustered temporary topics and queues.
-   All temporary topics and queues will be clustered if the post office is
-   clustered</para>
-   <para>If you don't want your nodes to participate in a cluster, or only
-   have one non clustered server you can set the clustered attribute on the
-   postoffice to false</para>
-   <para>If you wish to apply strict JMS ordering to messages, such that a
-   particular JMS consumer consumes messages in the same order as they were
-   produced by a particular producer, you can set the DefaultPreserveOrdering
-   attribute in the server peer to true. By default this is false. The
-   side-effect of setting this to true is that messages cannot be distributed
-   as freely around the cluster</para>
-   <para>When pulling reliable messages from one node to another, JBoss
-   Messaging can use client acnowledgement or an XA transaction. The default
-   is client acknowledgement. Using XA transactions is a fairly heavyweight
-   operation but ensures absolute once and only once delivery.</para>
-   <para>If the call to send a persistent message to a persistent destination
-   returns successfully with no exception, then you can be sure that the
-   message was persisted. However if the call doesn't return successfully e.g.
-   if an exception is thrown, then you *can't be sure the message wasn't
-   persisted*. Since the failure might have occurred after persisting the
-   message but before writing the response to the caller. This is a common
-   attribute of any RPC type call: You can't tell by the call not returning
-   that the call didn't actually succeed. Whether it's a web services call, an
-   HTTP get request, an ejb invocation the same applies. The trick is to code
-   your application so your operations are *idempotent* - i.e. they can be
-   repeated without getting the system into an inconsistent state. With a
-   message system you can do this on the application level, by checking for
-   duplicate messages, and discarding them if they arrive. Duplicate checking
-   is a very powerful technique that can remove the need for XA transactions
-   in many cases.</para>
+  
+   <section id="c_conf.serverpeerid">
+	   <title>Unique server peer id</title>
+	   <para>JBoss Messaging clustering should work out of the box in most cases
+		 with no configuration changes. It is however crucial that every node is
+		 assigned a unique server id, as specified in the installation guide.</para>
+	   <para>Every node deployed must have a unique id, including those in a
+		 particular LAN cluster, and also those only linked by mesage
+		 bridges.</para>
+   </section>
+     
+   <section id="c_conf.clustereddests">   
+	<title>Clustered destinations</title>
+	<para>JBoss Messaging clusters JMS queues and topics transparently across
+		the cluster. Messages sent to a distributed queue or topic on one node are
+		consumable on other nodes. To designate that a particular destination is
+		clustered simply set the clustered attribute in the destination deployment
+		descriptor to true.</para>
+	<para>JBoss Messaging balances messages between nodes, catering for faster
+		or slower consumers to efficiently balance processing load across the
+		cluster.</para>
+   </section>
+   
+      <section id="c_conf.clustereddursubs">
+	   	<title>Clustered durable subs</title>
+	   	<para>JBoss Messaging durable subscriptions can also be clustered. This
+		   	means multiple subscribers can consume from the same durable subscription
+		   	from different nodes of the cluster. A durable subscription will be
+		   	clustered if it's topic is clustered</para>
+	      </section>
+      
+      <section id="c_conf.clusteredtempdest">
+	   	<title>Clustered temporary destinations</title>
+	   	<para>JBoss Messaging also supports clustered temporary topics and queues.
+		   	All temporary topics and queues will be clustered if the post office is
+		   	clustered</para>
+	      </section>
+   
+      <section id="c_conf.nonclusteredserver">  
+	   	<title>Non clustered servers</title>
+	   	<para>If you don't want your nodes to participate in a cluster, or only
+		   	have one non clustered server you can set the clustered attribute on the
+		   	postoffice to false</para>
+	      </section>
+      
+      
+      <section id="c_conf.orderingincluster">
+	   	<title>Message ordering in the cluster</title>
+	   	<para>If you wish to apply strict JMS ordering to messages, such that a
+		   	particular JMS consumer consumes messages in the same order as they were
+		   	produced by a particular producer, you can set the DefaultPreserveOrdering
+		   	attribute in the server peer to true. By default this is false. The
+		   	sideeffect of setting this to true is that messages cannot be distributed
+		   	as freely around the cluster</para>
+	      </section>
+   
+   	   
+      <section id="c_conf.idempotentops">	
+	   	<title>Idempotent operations</title>
+	   	<para>If the call to send a persistent message to a persistent destination
+		   	returns successfully with no exception, then you can be sure that the
+		   	message was persisted. However if the call doesn't return successfully e.g.
+		   	if an exception is thrown, then you *can't be sure the message wasn't
+		   	persisted*. Since the failure might have occurred after persisting the
+		   	message but before writing the response to the caller. This is a common
+		   	attribute of any RPC type call: You can't tell by the call not returning
+		   	that the call didn't actually succeed. Whether it's a web services call, an
+		   	HTTP get request, an ejb invocation the same applies. The trick is to code
+		   	your application so your operations are *idempotent*  i.e. they can be
+		   	repeated without getting the system into an inconsistent state. With a
+		   	message system you can do this on the application level, by checking for
+		   	duplicate messages, and discarding them if they arrive. Duplicate checking
+		   	is a very powerful technique that can remove the need for XA transactions
+		   	in many cases.</para>
+	      </section>
+      
+      
+      <section id="c_conf.clusteredcfs">
+	   	<title>Clustered connection factories</title>
+	   	<para>If the supportsLoadBalancing attribute of the connection factory is set to true then consecutive create connection attempts will round robin between available servers. The first node to try is chosen randomly</para>
+	   	<para>If the supportsFailover attribute of the connection factory is set to true then automatic failover is enabled.
+		   	This will automatically failover from one server to another, transparently to the user, in case of failure.</para>
+	           <para>If automatic failover is not required or you wish to do manual failover (JBoss MQ style) this can be set to false, and you can supply a standard JMS ExceptionListener on the connection which will be called in case of
+		   	connection failure. You would then need to manually close the connection, lookup a new connection factory from
+		   	HA JNDI and recreate the connection.</para>
+	   	
+   </section>
+   
+   
 </chapter>
\ No newline at end of file

Modified: trunk/docs/userguide/en/modules/configuration.xml
===================================================================
--- trunk/docs/userguide/en/modules/configuration.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/docs/userguide/en/modules/configuration.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -105,10 +105,6 @@
       
       &lt;attribute name="ClusterPullConnectionFactoryName"&gt;jboss.messaging.connectionfactory:service=ClusterPullConnectionFactory&lt;/attribute&gt;
       
-      &lt;!-- Use XA when pulling persistent messages from a remote node to this one. --&gt;
-      
-      &lt;attribute name="UseXAForMessagePull"&gt;false&lt;/attribute&gt;
-      
       &lt;!-- When redistributing messages in the cluster. Do we need to preserve the order of messages received
             by a particular consumer from a particular producer? --&gt;
             
@@ -271,13 +267,6 @@
             messages between nodes. You will not normally need to change
             this.</para>
          </section>
-         <section id="conf.serverpeer.attributes.usexaformessagepull">
-            <title>UseXAForMessagePull</title>
-            <para>If true, then move a reliable message from one node to
-            another in an XA transaction. Relaxing this gives better
-            performance at the expense of some reliability. See the cluster
-            configurations section for more details. Default is false.</para>
-         </section>
          <section id="conf.serverpeer.attributes.defaultpreserveordering">
             <title>DefaultPreserveOrdering</title>
             <para>If true, then strict JMS ordering is preserved in the
@@ -832,7 +821,7 @@
    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, TYPE TINYINT, INS_TIME BIGINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, PRIMARY KEY (MESSAGE_ID)) ENGINE = INNODB
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, TYPE TINYINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, PRIMARY KEY (MESSAGE_ID)) ENGINE = INNODB
    CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
    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
@@ -855,12 +844,11 @@
    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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INST_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
    UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
-   MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME &lt; ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
+   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
+   MESSAGE_ID_COLUMN=MESSAGE_ID   
    DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)      
    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 = ?

Deleted: trunk/src/etc/server/default/deploy/db2-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/db2-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/db2-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1,258 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-     DB2 persistence deployment descriptor.
-
-     UNTESTED
-
-     $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_DUAL=CREATE TABLE JBM_DUAL (DUAL_DUMMY INTEGER NOT NULL, PRIMARY KEY (DUAL_DUMMY))
-   CREATE_MESSAGE_REFERENCE=CREATE TABLE JBM_MSG_REF (CHANNEL_ID BIGINT NOT NULL, MESSAGE_ID BIGINT NOT NULL, 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 PG_OD_IDX ON JBM_MSG_REF (PAGE_ORD)
-   CREATE_IDX_MESSAGE_REF_MESSAGE_ID=CREATE INDEX JBREIDIDX ON JBM_MSG_REF (MESSAGE_ID)
-   CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY=CREATE INDEX SC_DL_IDX ON JBM_MSG_REF (SCHED_DELIVERY)
-   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT NOT NULL, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY SMALLINT, TYPE SMALLINT, INS_TIME BIGINT, HEADERS BLOB, PAYLOAD BLOB, PRIMARY KEY (MESSAGE_ID))
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_TMST_ID ON JBM_MSG (TIMESTAMP)
-   CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER NOT NULL, TRANSACTION_ID BIGINT NOT NULL, BRANCH_QUAL BLOB(254), FORMAT_ID INTEGER, GLOBAL_TXID BLOB(254), PRIMARY KEY (TRANSACTION_ID))
-   CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255) NOT NULL, NEXT_ID BIGINT, PRIMARY KEY(NAME))
-   INSERT_DUAL=INSERT INTO JBM_DUAL VALUES (1)
-   CHECK_DUAL=SELECT 1 FROM JBM_DUAL
-   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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
-   UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
-   MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)   
-   DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)      
-   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">${jboss.messaging.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">5000</attribute>
-      
-      <!-- JGroups stack configuration for the data channel - used for sending data across the cluster -->               
-      
-      <!-- By default we use the TCP stack for data -->                  
-      <attribute name="DataChannelConfig">      
-         <config>
-            <TCP start_port="7900"
-                 loopback="true"
-                 recv_buf_size="20000000"
-                 send_buf_size="640000"
-                 discard_incompatible_packets="true"
-                 max_bundle_size="64000"
-                 max_bundle_timeout="30"
-                 use_incoming_packet_handler="true"
-                 use_outgoing_packet_handler="false"
-                 down_thread="false" up_thread="false"
-                 enable_bundling="false"
-                 use_send_queues="false"
-                 sock_conn_timeout="300"
-                 skip_suspected_members="true"/>
-            <MPING timeout="4000"
-		         bind_to_all_interfaces="true"
-		         mcast_addr="${jboss.messaging.datachanneludpaddress:228.6.6.6}"
-		         mcast_port="${jboss.messaging.datachanneludpport:45567}"
-		         ip_ttl="${jboss.messaging.ipttl:8}"
-		         num_initial_members="2"
-		         num_ping_requests="1"/>                     
-            <MERGE2 max_interval="100000"
-                    down_thread="false" up_thread="false" min_interval="20000"/>
-            <FD_SOCK down_thread="false" up_thread="false"/>            
-            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
-            <pbcast.NAKACK max_xmit_size="60000"
-                           use_mcast_xmit="false" gc_lag="0"
-                           retransmit_timeout="300,600,1200,2400,4800"
-                           down_thread="false" up_thread="false"
-                           discard_delivered_msgs="true"/>
-            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
-                           down_thread="false" up_thread="false"
-                           max_bytes="400000"/>
-            <pbcast.GMS print_local_addr="true" join_timeout="3000"
-                        down_thread="false" up_thread="false"
-                        join_retry_timeout="2000" shun="false"
-                        view_bundling="true"/>
-        </config>        
-      </attribute>
-      
-      <!-- JGroups stack configuration to use for the control channel - used for control messages -->         
-              
-      <!-- We use udp stack for the control channel -->
-      <attribute name="ControlChannelConfig">
-         <config>
-            <UDP
-                 mcast_addr="${jboss.messaging.controlchanneludpaddress:228.7.7.7}"
-                 mcast_port="${jboss.messaging.controlchanneludpport:45568}"
-                 tos="8"
-                 ucast_recv_buf_size="20000000"
-                 ucast_send_buf_size="640000"
-                 mcast_recv_buf_size="25000000"
-                 mcast_send_buf_size="640000"
-                 loopback="false"
-                 discard_incompatible_packets="true"
-                 max_bundle_size="64000"
-                 max_bundle_timeout="30"
-                 use_incoming_packet_handler="true"
-                 use_outgoing_packet_handler="false"
-                 ip_ttl="${jboss.messaging.ipttl:2}"
-                 down_thread="false" up_thread="false"
-                 enable_bundling="false"/>
-            <PING timeout="2000"
-                  down_thread="false" up_thread="false" num_initial_members="3"/>
-            <MERGE2 max_interval="100000"
-                    down_thread="false" up_thread="false" min_interval="20000"/>
-            <FD_SOCK down_thread="false" up_thread="false"/>
-            <FD timeout="10000" max_tries="5" down_thread="false" up_thread="false" shun="true"/>
-            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
-            <pbcast.NAKACK max_xmit_size="60000"
-                           use_mcast_xmit="false" gc_lag="0"
-                           retransmit_timeout="300,600,1200,2400,4800"
-                           down_thread="false" up_thread="false"
-                           discard_delivered_msgs="true"/>
-            <UNICAST timeout="300,600,1200,2400,3600"
-                     down_thread="false" up_thread="false"/>
-            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
-                           down_thread="false" up_thread="false"
-                           max_bytes="400000"/>
-            <pbcast.GMS print_local_addr="true" join_timeout="3000" use_flush="true" flush_timeout="3000"
-                        down_thread="false" up_thread="false"
-                        join_retry_timeout="2000" shun="false"
-                        view_bundling="true"/>
-            <FRAG2 frag_size="60000" down_thread="false" up_thread="false"/>
-            <pbcast.STATE_TRANSFER down_thread="false" up_thread="false" use_flush="true" flush_timeout="3000"/>
-            <pbcast.FLUSH down_thread="false" up_thread="false" timeout="20000" auto_flush_conf="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>
-
-</server>

Modified: trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -84,7 +84,20 @@
       <attribute name="CreateTablesOnStartup">true</attribute>
       
       <attribute name="SqlProperties"><![CDATA[
-POPULATE.TABLES.1=INSERT INTO JBM_USER (USER_ID,PASSWD,CLIENTID) VALUES ('dilbert','dogbert','dilbert-id')
+POPULATE.TABLES.1  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('guest', 'guest')
+POPULATE.TABLES.2  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('j2ee', 'j2ee')
+POPULATE.TABLES.3  = INSERT INTO JBM_USER (USER_ID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
+POPULATE.TABLES.4  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('nobody', 'nobody')
+POPULATE.TABLES.5  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('dynsub', 'dynsub')
+POPULATE.TABLES.6  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('guest','guest')
+POPULATE.TABLES.7  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('j2ee','guest')
+POPULATE.TABLES.8  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('john','guest')
+POPULATE.TABLES.9  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('subscriber','john')
+POPULATE.TABLES.10 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','john')
+POPULATE.TABLES.11 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','dynsub')
+POPULATE.TABLES.12 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','john')
+POPULATE.TABLES.13 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','dynsub')
+POPULATE.TABLES.14 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('noacc','nobody')
       ]]></attribute>
    </mbean>
 

Modified: trunk/src/etc/server/default/deploy/messaging-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/messaging-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/messaging-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -81,10 +81,6 @@
       
       <attribute name="ClusterPullConnectionFactoryName">jboss.messaging.connectionfactory:service=ClusterPullConnectionFactory</attribute>
       
-      <!-- Use XA when pulling persistent messages from a remote node to this one. -->
-      
-      <attribute name="UseXAForMessagePull">false</attribute>
-      
       <!-- When redistributing messages in the cluster. Do we need to preserve the order of messages received
             by a particular consumer from a particular producer? -->
             

Modified: trunk/src/etc/server/default/deploy/mssql-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/mssql-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/mssql-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -41,8 +41,7 @@
    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, TYPE TINYINT, INS_TIME BIGINT, HEADERS IMAGE, PAYLOAD IMAGE, PRIMARY KEY (MESSAGE_ID))
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, TYPE TINYINT, HEADERS IMAGE, PAYLOAD IMAGE, PRIMARY KEY (MESSAGE_ID))
    CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER, TRANSACTION_ID BIGINT, BRANCH_QUAL VARBINARY(254), FORMAT_ID INT, GLOBAL_TXID VARBINARY(254), PRIMARY KEY (TRANSACTION_ID))
    CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME))
    INSERT_DUAL=INSERT INTO JBM_DUAL VALUES (1)
@@ -62,14 +61,14 @@
    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 = ?
+   UPDATE_CHANNEL_ID=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ?   
+   MOVE_REFERENCE=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ? AND MESSAGE_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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE) SELECT ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
    UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
+   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
    MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
    DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)   
    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 = ?
@@ -134,11 +133,11 @@
      
       <!-- Max time to wait for state to arrive when the post office joins the cluster -->            
       
-      <attribute name="StateTimeout">5000</attribute>
+      <attribute name="StateTimeout">30000</attribute>
       
       <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->            
       
-      <attribute name="CastTimeout">5000</attribute>
+      <attribute name="CastTimeout">30000</attribute>
        
       <!-- JGroups stack configuration for the data channel - used for sending data across the cluster -->               
       
@@ -254,7 +253,20 @@
 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')
+POPULATE.TABLES.1  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('guest', 'guest')
+POPULATE.TABLES.2  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('j2ee', 'j2ee')
+POPULATE.TABLES.3  = INSERT INTO JBM_USER (USER_ID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
+POPULATE.TABLES.4  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('nobody', 'nobody')
+POPULATE.TABLES.5  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('dynsub', 'dynsub')
+POPULATE.TABLES.6  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('guest','guest')
+POPULATE.TABLES.7  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('j2ee','guest')
+POPULATE.TABLES.8  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('john','guest')
+POPULATE.TABLES.9  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('subscriber','john')
+POPULATE.TABLES.10 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','john')
+POPULATE.TABLES.11 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','dynsub')
+POPULATE.TABLES.12 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','john')
+POPULATE.TABLES.13 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','dynsub')
+POPULATE.TABLES.14 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('noacc','nobody')
       ]]></attribute>
    </mbean>
 

Modified: trunk/src/etc/server/default/deploy/mysql-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/mysql-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/mysql-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -3,7 +3,7 @@
 <!--
      MySql persistence deployment descriptor.
 
-     Tested with MySQL 4.1.22
+     Tested with MySQL 5.0.27
 
      $Id$
  -->
@@ -41,8 +41,7 @@
    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, TYPE TINYINT, INS_TIME BIGINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, PRIMARY KEY (MESSAGE_ID)) ENGINE = INNODB
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, TYPE TINYINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, 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_DUAL=INSERT INTO JBM_DUAL VALUES (1)
@@ -63,13 +62,13 @@
    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 = ?
+   MOVE_REFERENCE=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ? AND MESSAGE_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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE) SELECT ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
    UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
-   MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
+   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
+   MESSAGE_ID_COLUMN=MESSAGE_ID   
    DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)      
    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 = ?
@@ -134,11 +133,11 @@
       
       <!-- Max time to wait for state to arrive when the post office joins the cluster -->            
                   
-      <attribute name="StateTimeout">5000</attribute>
+      <attribute name="StateTimeout">300000</attribute>
       
       <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->            
                   
-      <attribute name="CastTimeout">50000</attribute>
+      <attribute name="CastTimeout">300000</attribute>
       
       <!-- JGroups stack configuration for the data channel - used for sending data across the cluster --> 
                    
@@ -250,7 +249,20 @@
 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')
+POPULATE.TABLES.1  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('guest', 'guest')
+POPULATE.TABLES.2  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('j2ee', 'j2ee')
+POPULATE.TABLES.3  = INSERT INTO JBM_USER (USER_ID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
+POPULATE.TABLES.4  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('nobody', 'nobody')
+POPULATE.TABLES.5  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('dynsub', 'dynsub')
+POPULATE.TABLES.6  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('guest','guest')
+POPULATE.TABLES.7  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('j2ee','guest')
+POPULATE.TABLES.8  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('john','guest')
+POPULATE.TABLES.9  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('subscriber','john')
+POPULATE.TABLES.10 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','john')
+POPULATE.TABLES.11 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','dynsub')
+POPULATE.TABLES.12 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','john')
+POPULATE.TABLES.13 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','dynsub')
+POPULATE.TABLES.14 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('noacc','nobody')
       ]]></attribute>
    </mbean>
 

Deleted: trunk/src/etc/server/default/deploy/mysqlcluster-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/mysqlcluster-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/mysqlcluster-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1,257 +0,0 @@
-<?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_DUAL=CREATE TABLE JBM_DUAL (DUMMY INTEGER, PRIMARY KEY (DUMMY)) ENGINE = NDBCLUSTER
-   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 = NDBCLUSTER
-   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, TYPE TINYINT, INS_TIME BIGINT, HEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, PRIMARY KEY (MESSAGE_ID)) ENGINE = NDBCLUSTER
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
-   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 = NDBCLUSTER
-   CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME)) ENGINE = NDBCLUSTER
-   INSERT_DUAL=INSERT INTO JBM_DUAL VALUES (1)
-   CHECK_DUAL=SELECT 1 FROM JBM_DUAL
-   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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INST_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
-   UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
-   MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
-   DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)   
-   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 = NDBCLUSTER
-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">${jboss.messaging.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>
-      
-      <!-- JGroups stack configuration for the data channel - used for sending data across the cluster -->
-
-      <!-- By default we use the TCP stack for data -->                  
-      <attribute name="DataChannelConfig">      
-         <config>
-            <TCP start_port="7900"
-                 loopback="true"
-                 recv_buf_size="20000000"
-                 send_buf_size="640000"
-                 discard_incompatible_packets="true"
-                 max_bundle_size="64000"
-                 max_bundle_timeout="30"
-                 use_incoming_packet_handler="true"
-                 use_outgoing_packet_handler="false"
-                 down_thread="false" up_thread="false"
-                 enable_bundling="false"
-                 use_send_queues="false"
-                 sock_conn_timeout="300"
-                 skip_suspected_members="true"/>
-            <MPING timeout="4000"
-		         bind_to_all_interfaces="true"
-		         mcast_addr="${jboss.messaging.datachanneludpaddress:228.6.6.6}"
-		         mcast_port="${jboss.messaging.datachanneludpport:45567}"
-		         ip_ttl="${jboss.messaging.ipttl:8}"
-		         num_initial_members="2"
-		         num_ping_requests="1"/>                     
-            <MERGE2 max_interval="100000"
-                    down_thread="false" up_thread="false" min_interval="20000"/>
-            <FD_SOCK down_thread="false" up_thread="false"/>            
-            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
-            <pbcast.NAKACK max_xmit_size="60000"
-                           use_mcast_xmit="false" gc_lag="0"
-                           retransmit_timeout="300,600,1200,2400,4800"
-                           down_thread="false" up_thread="false"
-                           discard_delivered_msgs="true"/>
-            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
-                           down_thread="false" up_thread="false"
-                           max_bytes="400000"/>
-            <pbcast.GMS print_local_addr="true" join_timeout="3000"
-                        down_thread="false" up_thread="false"
-                        join_retry_timeout="2000" shun="false"
-                        view_bundling="true"/>
-        </config>        
-      </attribute>
-      
-      <!-- JGroups stack configuration to use for the control channel - used for control messages -->         
-              
-      <!-- We use udp stack for the control channel -->
-      <attribute name="ControlChannelConfig">
-         <config>
-            <UDP
-                 mcast_addr="${jboss.messaging.controlchanneludpaddress:228.7.7.7}"
-                 mcast_port="${jboss.messaging.controlchanneludpport:45568}"
-                 tos="8"
-                 ucast_recv_buf_size="20000000"
-                 ucast_send_buf_size="640000"
-                 mcast_recv_buf_size="25000000"
-                 mcast_send_buf_size="640000"
-                 loopback="false"
-                 discard_incompatible_packets="true"
-                 max_bundle_size="64000"
-                 max_bundle_timeout="30"
-                 use_incoming_packet_handler="true"
-                 use_outgoing_packet_handler="false"
-                 ip_ttl="${jboss.messaging.ipttl:2}"
-                 down_thread="false" up_thread="false"
-                 enable_bundling="false"/>
-            <PING timeout="2000"
-                  down_thread="false" up_thread="false" num_initial_members="3"/>
-            <MERGE2 max_interval="100000"
-                    down_thread="false" up_thread="false" min_interval="20000"/>
-            <FD_SOCK down_thread="false" up_thread="false"/>
-            <FD timeout="10000" max_tries="5" down_thread="false" up_thread="false" shun="true"/>
-            <VERIFY_SUSPECT timeout="1500" down_thread="false" up_thread="false"/>
-            <pbcast.NAKACK max_xmit_size="60000"
-                           use_mcast_xmit="false" gc_lag="0"
-                           retransmit_timeout="300,600,1200,2400,4800"
-                           down_thread="false" up_thread="false"
-                           discard_delivered_msgs="true"/>
-            <UNICAST timeout="300,600,1200,2400,3600"
-                     down_thread="false" up_thread="false"/>
-            <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
-                           down_thread="false" up_thread="false"
-                           max_bytes="400000"/>
-            <pbcast.GMS print_local_addr="true" join_timeout="3000" use_flush="true" flush_timeout="3000"
-                        down_thread="false" up_thread="false"
-                        join_retry_timeout="2000" shun="false"
-                        view_bundling="true"/>
-            <FRAG2 frag_size="60000" down_thread="false" up_thread="false"/>
-            <pbcast.STATE_TRANSFER down_thread="false" up_thread="false" use_flush="true" flush_timeout="3000"/>
-            <pbcast.FLUSH down_thread="false" up_thread="false" timeout="20000" auto_flush_conf="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 = NDBCLUSTER
-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 = NDBCLUSTER
-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/server/default/deploy/oracle-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/oracle-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/oracle-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -3,7 +3,7 @@
 <!--
      Oracle persistence deployment descriptor.
 
-     Tested with Oracle 10.1.0.3
+     Tested with Oracle 10.2.0.1
 
      $Id$
  -->
@@ -45,8 +45,7 @@
    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 INTEGER, RELIABLE CHAR(1), EXPIRATION INTEGER, TIMESTAMP INTEGER, PRIORITY INTEGER, TYPE INTEGER, INS_TIME INTEGER, HEADERS BLOB, PAYLOAD BLOB, PRIMARY KEY (MESSAGE_ID))
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID INTEGER, RELIABLE CHAR(1), EXPIRATION INTEGER, TIMESTAMP INTEGER, PRIORITY INTEGER, TYPE INTEGER, HEADERS BLOB, PAYLOAD BLOB, PRIMARY KEY (MESSAGE_ID))
    CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER, TRANSACTION_ID INTEGER, BRANCH_QUAL RAW(254), FORMAT_ID INTEGER, GLOBAL_TXID RAW(254), PRIMARY KEY (TRANSACTION_ID))
    CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR2(255), NEXT_ID INTEGER, PRIMARY KEY(NAME))
    INSERT_DUAL=INSERT INTO JBM_DUAL VALUES (1)
@@ -67,13 +66,13 @@
    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 = ?
+   MOVE_REFERENCE=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ? AND MESSAGE_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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE) SELECT ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
    UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
+   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
    MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
    DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)   
    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 = ?
@@ -138,11 +137,11 @@
      
       <!-- Max time to wait for state to arrive when the post office joins the cluster -->            
                   
-      <attribute name="StateTimeout">5000</attribute>
+      <attribute name="StateTimeout">30000</attribute>
       
       <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->            
                   
-      <attribute name="CastTimeout">5000</attribute>
+      <attribute name="CastTimeout">30000</attribute>
       
       <!-- JGroups stack configuration for the data channel - used for sending data across the cluster -->               
       
@@ -258,7 +257,20 @@
 CREATE_USER_TABLE=CREATE TABLE JBM_USER (USER_ID VARCHAR2(32) NOT NULL, PASSWD VARCHAR2(32) NOT NULL, CLIENTID VARCHAR2(128), PRIMARY KEY(USER_ID))
 CREATE_ROLE_TABLE=CREATE TABLE JBM_ROLE (ROLE_ID VARCHAR2(32) NOT NULL, USER_ID VARCHAR2(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')
+POPULATE.TABLES.1  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('guest', 'guest')
+POPULATE.TABLES.2  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('j2ee', 'j2ee')
+POPULATE.TABLES.3  = INSERT INTO JBM_USER (USER_ID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
+POPULATE.TABLES.4  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('nobody', 'nobody')
+POPULATE.TABLES.5  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('dynsub', 'dynsub')
+POPULATE.TABLES.6  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('guest','guest')
+POPULATE.TABLES.7  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('j2ee','guest')
+POPULATE.TABLES.8  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('john','guest')
+POPULATE.TABLES.9  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('subscriber','john')
+POPULATE.TABLES.10 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','john')
+POPULATE.TABLES.11 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','dynsub')
+POPULATE.TABLES.12 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','john')
+POPULATE.TABLES.13 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','dynsub')
+POPULATE.TABLES.14 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('noacc','nobody')
       ]]></attribute>
    </mbean>
 

Modified: trunk/src/etc/server/default/deploy/postgresql-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/postgresql-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/postgresql-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -3,7 +3,7 @@
 <!--
      Postgresql persistence deployment descriptor.
 
-     Tested with PostgresSQL 8.1.5
+     Tested with PostgresSQL 8.2.3
 
      $Id$
  -->
@@ -41,8 +41,7 @@
    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 SMALLINT, TYPE SMALLINT, INS_TIME BIGINT, HEADERS BYTEA, PAYLOAD BYTEA, PRIMARY KEY (MESSAGE_ID))
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY SMALLINT, TYPE SMALLINT, HEADERS BYTEA, PAYLOAD BYTEA, PRIMARY KEY (MESSAGE_ID))   
    CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER, TRANSACTION_ID BIGINT, BRANCH_QUAL BYTEA, FORMAT_ID INTEGER, GLOBAL_TXID BYTEA, PRIMARY KEY (TRANSACTION_ID))
    CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME))
    INSERT_DUAL=INSERT INTO JBM_DUAL VALUES (1)
@@ -63,13 +62,13 @@
    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 = ?
+   MOVE_REFERENCE=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ? AND MESSAGE_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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE) SELECT ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
    UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
+   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
    MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
    DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)   
    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 = ?
@@ -134,11 +133,11 @@
       
       <!-- Max time to wait for state to arrive when the post office joins the cluster -->                        
       
-      <attribute name="StateTimeout">5000</attribute>
+      <attribute name="StateTimeout">30000</attribute>
       
       <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->                        
       
-      <attribute name="CastTimeout">5000</attribute>
+      <attribute name="CastTimeout">30000</attribute>
       
       <!-- Max number of concurrent replications -->
       
@@ -260,7 +259,20 @@
 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')
+POPULATE.TABLES.1  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('guest', 'guest')
+POPULATE.TABLES.2  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('j2ee', 'j2ee')
+POPULATE.TABLES.3  = INSERT INTO JBM_USER (USER_ID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
+POPULATE.TABLES.4  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('nobody', 'nobody')
+POPULATE.TABLES.5  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('dynsub', 'dynsub')
+POPULATE.TABLES.6  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('guest','guest')
+POPULATE.TABLES.7  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('j2ee','guest')
+POPULATE.TABLES.8  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('john','guest')
+POPULATE.TABLES.9  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('subscriber','john')
+POPULATE.TABLES.10 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','john')
+POPULATE.TABLES.11 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','dynsub')
+POPULATE.TABLES.12 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','john')
+POPULATE.TABLES.13 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','dynsub')
+POPULATE.TABLES.14 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('noacc','nobody')
       ]]></attribute>
    </mbean>
 

Modified: trunk/src/etc/server/default/deploy/sybase-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/sybase-persistence-service.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/server/default/deploy/sybase-persistence-service.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -3,7 +3,7 @@
 <!--
      Sybase persistence deployment descriptor.
 
-     Tested with Sybase Adaptive Server Enterprise 12.5.2
+     Tested with Sybase Adaptive Server Enterprise 12.5.3
 
      $Id$
  -->
@@ -46,8 +46,7 @@
    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 DECIMAL(19, 0), RELIABLE CHAR(1), EXPIRATION DECIMAL(19, 0), TIMESTAMP DECIMAL(19, 0), PRIORITY TINYINT, TYPE TINYINT, INS_TIME DECIMAL(19, 0), HEADERS IMAGE NULL, PAYLOAD IMAGE NULL, PRIMARY KEY (MESSAGE_ID))
-   CREATE_IDX_MESSAGE_TIMESTAMP=CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)
+   CREATE_MESSAGE=CREATE TABLE JBM_MSG (MESSAGE_ID DECIMAL(19, 0), RELIABLE CHAR(1), EXPIRATION DECIMAL(19, 0), TIMESTAMP DECIMAL(19, 0), PRIORITY TINYINT, TYPE TINYINT, HEADERS IMAGE NULL, PAYLOAD IMAGE NULL, PRIMARY KEY (MESSAGE_ID))
    CREATE_TRANSACTION=CREATE TABLE JBM_TX (NODE_ID INTEGER, TRANSACTION_ID DECIMAL(19, 0), BRANCH_QUAL VARBINARY(254) NULL, FORMAT_ID INTEGER NULL, GLOBAL_TXID VARBINARY(254) NULL, PRIMARY KEY (TRANSACTION_ID))
    CREATE_COUNTER=CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID DECIMAL(19, 0), PRIMARY KEY(NAME))
    INSERT_DUAL=INSERT INTO JBM_DUAL VALUES (1)
@@ -68,13 +67,13 @@
    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 = ?
+   MOVE_REFERENCE=UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ? AND MESSAGE_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, TYPE, INS_TIME, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
-   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME) SELECT ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
+   INSERT_MESSAGE=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE_CONDITIONAL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE) SELECT ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)
    UPDATE_MESSAGE_4CONDITIONAL=UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?
-   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
-   MESSAGE_ID_COLUMN=MESSAGE_ID
-   REAP_MESSAGES=DELETE FROM JBM_MSG WHERE INS_TIME < ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)
+   INSERT_MESSAGE_CONDITIONAL_FULL=INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)   
+   MESSAGE_ID_COLUMN=MESSAGE_ID   
    DELETE_MESSAGE=DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)   
    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 = ?
@@ -139,11 +138,11 @@
      
       <!-- Max time to wait for state to arrive when the post office joins the cluster -->            
                   
-      <attribute name="StateTimeout">5000</attribute>
+      <attribute name="StateTimeout">30000</attribute>
       
       <!-- Max time to wait for a synchronous call to node members using the MessageDispatcher -->            
                   
-      <attribute name="CastTimeout">5000</attribute>
+      <attribute name="CastTimeout">30000</attribute>
       
       <!-- JGroups stack configuration for the data channel - used for sending data across the cluster -->               
       
@@ -254,7 +253,20 @@
 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')
+POPULATE.TABLES.1  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('guest', 'guest')
+POPULATE.TABLES.2  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('j2ee', 'j2ee')
+POPULATE.TABLES.3  = INSERT INTO JBM_USER (USER_ID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
+POPULATE.TABLES.4  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('nobody', 'nobody')
+POPULATE.TABLES.5  = INSERT INTO JBM_USER (USER_ID, PASSWD) VALUES ('dynsub', 'dynsub')
+POPULATE.TABLES.6  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('guest','guest')
+POPULATE.TABLES.7  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('j2ee','guest')
+POPULATE.TABLES.8  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('john','guest')
+POPULATE.TABLES.9  = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('subscriber','john')
+POPULATE.TABLES.10 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','john')
+POPULATE.TABLES.11 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('publisher','dynsub')
+POPULATE.TABLES.12 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','john')
+POPULATE.TABLES.13 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('durpublisher','dynsub')
+POPULATE.TABLES.14 = INSERT INTO JBM_ROLE (ROLE_ID, USER_ID) VALUES ('noacc','nobody')
       ]]></attribute>
    </mbean>
 

Modified: trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2007-11-19 14:34:57 UTC (rev 3341)
@@ -181,13 +181,7 @@
       <name>ClusterPullConnectionFactoryName</name>
       <type>java.lang.String</type>
    </attribute> 
-   
-   <attribute access="read-write" getMethod="isUseXAForMessagePull" setMethod="setUseXAForMessagePull">
-      <description>When pulling persistent messages from a remote durable queue to a local one, should XA be used?</description>
-      <name>UseXAForMessagePull</name>
-      <type>boolean</type>
-   </attribute>  
-   
+
    <attribute access="read-write" getMethod="isDefaultPreserveOrdering" setMethod="setDefaultPreserveOrdering">
       <description>When pulling messages do we need to preserve the ordering of messages consumed from a particular producer, for a particular consumer?</description>
       <name>DefaultPreserveOrdering</name>

Modified: trunk/src/main/org/jboss/jms/client/container/ProducerAspect.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/container/ProducerAspect.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/client/container/ProducerAspect.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -25,6 +25,7 @@
 import javax.jms.Destination;
 import javax.jms.MapMessage;
 import javax.jms.Message;
+import javax.jms.MessageFormatException;
 import javax.jms.ObjectMessage;
 import javax.jms.StreamMessage;
 import javax.jms.TextMessage;
@@ -88,9 +89,7 @@
       long timeToLive = ((Long)args[4]).longValue();
 
       boolean keepID = args.length>5? ((Boolean)args[5]).booleanValue() : false;
-
-      String keptId = null;
-
+      
       // configure the message for sending, using attributes stored as metadata
 
       ProducerState producerState = getProducerState(mi);
@@ -109,6 +108,11 @@
          priority = producerState.getPriority();
          if (trace) { log.trace("Using producer's default priority: " + priority); }
       }
+      if (priority < 0 || priority > 9)
+      {
+         throw new MessageFormatException("Invalid message priority (" + priority + "). " +
+                                          "Valid priorities are 0-9");
+      }
       m.setJMSPriority(priority);
 
       if (producerState.isDisableMessageTimestamp())
@@ -169,7 +173,7 @@
       // Generate the message id
       ConnectionState connectionState = (ConnectionState)sessionState.getParent();
 
-      long id = 0;
+      long id = -1;
 
       JBossMessage messageToSend;
       boolean foreign = false;
@@ -223,14 +227,13 @@
          // get the actual message
          MessageProxy proxy = (MessageProxy)m;
 
+         m.setJMSDestination(destination);
+         
          if (keepID)
          {
-            keptId = m.getJMSMessageID();
+            id = proxy.getMessage().getMessageID();
          }
 
-
-         m.setJMSDestination(destination);
-
          //The following line executed on the proxy should cause a copy to occur
          //if it is necessary
          proxy.setJMSMessageID(null);
@@ -243,15 +246,13 @@
 
       // Set the new id
 
-      id = connectionState.getIdGenerator().getId((ConnectionDelegate)connectionState.getDelegate());
-      messageToSend.setMessageId(id);
-
-      if (keptId != null)
+      if (!keepID)
       {
-         messageToSend.setJMSMessageID(keptId);
+         id = connectionState.getIdGenerator().getId((ConnectionDelegate)connectionState.getDelegate());
       }
-
-
+      
+      messageToSend.setMessageId(id);
+            
       // This only really used for BytesMessages and StreamMessages to reset their state
       messageToSend.doBeforeSend(); 
       

Modified: trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -55,6 +55,10 @@
 import org.jboss.messaging.util.Version;
 import org.jboss.remoting.InvokerLocator;
 
+import EDU.oswego.cs.dl.util.concurrent.Executor;
+import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
 /**
  * @author <a href="mailto:ovidiu at feodorov.com">Ovidiu Feodorov</a>
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
@@ -86,6 +90,8 @@
    private Map delegates;
 
    private Replicator replicator;
+   
+   private QueuedExecutor notifyExecutor;
 
    // Constructors ---------------------------------------------------------------------------------
 
@@ -93,7 +99,8 @@
    {
       this.serverPeer = serverPeer;
       endpoints = new HashMap();
-      delegates = new HashMap();
+      delegates = new HashMap();          
+      notifyExecutor = new QueuedExecutor(new LinkedQueue());
    }
 
    // ConnectionFactoryManager implementation ------------------------------------------------------
@@ -291,115 +298,140 @@
    public void stop() throws Exception
    {
       initialContext.close();
+      
+      notifyExecutor.shutdownNow();
 
       log.debug("stopped");
    }
 
    // ReplicationListener interface ----------------------------------------------------------------
 
-   public synchronized void notify(ClusterNotification notification)
+   public void notify(final ClusterNotification notification)
    {
       log.debug(this + " received notification from node " + notification.nodeID );
 
-      try
+      class NotifyRunner implements Runnable
       {
-      	if (notification.type == ClusterNotification.TYPE_NODE_JOIN || notification.type == ClusterNotification.TYPE_NODE_LEAVE)
-      	{
-            // We respond to changes in the node-address mapping. This will be replicated whan a
-            // node joins / leaves the group. When this happens we need to rebind all connection factories with the new mapping.
+         public void run()
+         {
+            try
+            {
+               if (notification.type == ClusterNotification.TYPE_NODE_JOIN || notification.type == ClusterNotification.TYPE_NODE_LEAVE)
+               {
+                  // We respond to changes in the node-address mapping. This will be replicated whan a
+                  // node joins / leaves the group. When this happens we need to rebind all connection factories with the new mapping.
 
-            Map failoverMap = serverPeer.getPostOfficeInstance().getFailoverMap();
+                  Map failoverMap = serverPeer.getPostOfficeInstance().getFailoverMap();
 
-            // Rebind
+                  // Rebind
 
-            for(Iterator i = endpoints.entrySet().iterator(); i.hasNext(); )
-            {
-               Map.Entry entry = (Map.Entry)i.next();
-               String uniqueName = (String)entry.getKey();
+                  for(Iterator i = endpoints.entrySet().iterator(); i.hasNext(); )
+                  {
+                     Map.Entry entry = (Map.Entry)i.next();
+                     String uniqueName = (String)entry.getKey();
 
-               Object del = delegates.get(uniqueName);
+                     Object del = delegates.get(uniqueName);
 
-               if (del == null)
-               {
-                  throw new IllegalStateException(
-                     "Cannot find connection factory with name " + uniqueName);
+                     if (del == null)
+                     {
+                        throw new IllegalStateException(
+                           "Cannot find connection factory with name " + uniqueName);
+                     }
+
+                     if (del instanceof ClientClusteredConnectionFactoryDelegate)
+                     {
+                        ((ClientClusteredConnectionFactoryDelegate)del).setFailoverMap(failoverMap);
+                     }
+                  }                  
+                                 
+                  //Note we don't rebind at this point - we just update the maps.
+                  //When a node joins or leaves, we first get the join/leave notification
+                  //Then we'll get a subsequent connection factory deploy/undeploy
+                  //Even when a node crashes we'll get this since the postoffice ensures replication removes 
+                  //are called in this event                  
                }
-
-               if (del instanceof ClientClusteredConnectionFactoryDelegate)
+               else if ((notification.type == ClusterNotification.TYPE_REPLICATOR_PUT || notification.type == ClusterNotification.TYPE_REPLICATOR_REMOVE) &&
+                        (notification.data instanceof String) && ((String)notification.data).startsWith(Replicator.CF_PREFIX))
                {
-                  ((ClientClusteredConnectionFactoryDelegate)del).setFailoverMap(failoverMap);
-               }
-            }
-         }
-         else if ((notification.type == ClusterNotification.TYPE_REPLICATOR_PUT || notification.type == ClusterNotification.TYPE_REPLICATOR_REMOVE) &&
-         		   (notification.data instanceof String) && ((String)notification.data).startsWith(Replicator.CF_PREFIX))
-         {
 
-            log.debug("Updating CF information for " + notification.data);
-            // A connection factory has been deployed / undeployed
+                  log.debug("Updating CF information for " + notification.data);
+                  // A connection factory has been deployed / undeployed
 
-         	// NOTE! All connection factories MUST be deployed on all nodes!
-         	// Otherwise the server might failover onto a node which doesn't have that connection factory deployed
-            // so the connection won't be able to recconnect.
+                  // NOTE! All connection factories MUST be deployed on all nodes!
+                  // Otherwise the server might failover onto a node which doesn't have that connection factory deployed
+                  // so the connection won't be able to recconnect.
 
-         	String key = (String)notification.data;
+                  String key = (String)notification.data;
 
-            String uniqueName = key.substring(Replicator.CF_PREFIX.length());
+                  String uniqueName = key.substring(Replicator.CF_PREFIX.length());
 
-            log.debug(this + " received '" + uniqueName +  "' connection factory deploy / undeploy");
+                  log.debug(this + " received '" + uniqueName +  "' connection factory deploy / undeploy");
 
-            ConnectionFactoryDelegate cfd = (ConnectionFactoryDelegate)delegates.get(uniqueName);
+                  ConnectionFactoryDelegate cfd = (ConnectionFactoryDelegate)delegates.get(uniqueName);
 
-            if (cfd == null)
-            {
-               //This is ok - connection factory a might be deployed on node A before being deployed on node B so
-            	//node B might get the notification before it has deployed a itself
-            }
-            else
-            {
-               if (cfd instanceof ClientConnectionFactoryDelegate)
-               {
-                  //Non clustered - ignore
+                  if (cfd == null)
+                  {
+                     //This is ok - connection factory a might be deployed on node A before being deployed on node B so
+                     //node B might get the notification before it has deployed a itself
+                  }
+                  else
+                  {
+                     if (cfd instanceof ClientConnectionFactoryDelegate)
+                     {
+                        //Non clustered - ignore
 
-               	//We still replicate non clustered connection factories since the ClusterPullConnectionFactory
-               	//is non clustered but needs to be available across the cluster
-               }
-               else
-               {
-               	ClientClusteredConnectionFactoryDelegate del = (ClientClusteredConnectionFactoryDelegate)cfd;
+                        //We still replicate non clustered connection factories since the ClusterPullConnectionFactory
+                        //is non clustered but needs to be available across the cluster
+                     }
+                     else
+                     {
+                        ClientClusteredConnectionFactoryDelegate del = (ClientClusteredConnectionFactoryDelegate)cfd;
 
-	            	Map updatedReplicantMap = replicator.get(key);
+                        Map updatedReplicantMap = replicator.get(key);
 
-		            List newDels = sortDelegatesOnServerID(updatedReplicantMap.values());
+                        List newDels = sortDelegatesOnServerID(updatedReplicantMap.values());
 
-		            ClientConnectionFactoryDelegate[] delArr =
-		               (ClientConnectionFactoryDelegate[])newDels.
-		                  toArray(new ClientConnectionFactoryDelegate[newDels.size()]);
+                        ClientConnectionFactoryDelegate[] delArr =
+                           (ClientConnectionFactoryDelegate[])newDels.
+                              toArray(new ClientConnectionFactoryDelegate[newDels.size()]);
 
-                  Map failoverMap = serverPeer.getPostOfficeInstance().getFailoverMap();
+                        Map failoverMap = serverPeer.getPostOfficeInstance().getFailoverMap();
 
-		            del.setDelegates(delArr);
-                  del.setFailoverMap(failoverMap);
+                        del.setDelegates(delArr);
+                        del.setFailoverMap(failoverMap);
 
-		            ServerConnectionFactoryEndpoint endpoint =
-		               (ServerConnectionFactoryEndpoint)endpoints.get(uniqueName);
+                        ServerConnectionFactoryEndpoint endpoint =
+                           (ServerConnectionFactoryEndpoint)endpoints.get(uniqueName);
 
-		            if (endpoint == null)
-		            {
-		               throw new IllegalStateException("Cannot find endpoint with name " + uniqueName);
-		            }
+                        if (endpoint == null)
+                        {
+                           throw new IllegalStateException("Cannot find endpoint with name " + uniqueName);
+                        }
 
-		            rebindConnectionFactory(initialContext, endpoint.getJNDIBindings(), del);
+                        rebindConnectionFactory(initialContext, endpoint.getJNDIBindings(), del);
 
-		            endpoint.updateClusteredClients(delArr, failoverMap);
+                        endpoint.updateClusteredClients(delArr, failoverMap);
+                     }
+                  }
                }
             }
+            catch (Exception e)
+            {
+               log.error("Failed to rebind connection factory", e);
+            }
          }
       }
-      catch (Exception e)
+      
+      //Run on a different thread to prevent distributed deadlock when multiple nodes are starting together
+      //and deploying connection factories concurrently
+      try
       {
-         log.error("Failed to rebind connection factory", e);
+         notifyExecutor.execute(new NotifyRunner());
       }
+      catch (InterruptedException e)
+      {
+         //Ignore
+      }
    }
 
    // Public ---------------------------------------------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/server/destination/QueueService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -138,6 +138,22 @@
          
          started = true;         
          
+         //Now we need to trigger a delivery - this is because message suckers might have
+         //been create *before* the queue was deployed - this is because message suckers can be
+         //created when the clusterpullconnectionfactory deploy is detected which then causes
+         //the clusterconnectionmanager to inspect the bindings for queues to create suckers
+         //to - but these bindings will exist before the queue or topic is deployed and before
+         //it has had its messages loaded
+         //Therefore we need to trigger a delivery now so remote suckers get messages
+         //See http://jira.jboss.org/jira/browse/JBMESSAGING-1136
+         //For JBM we should remove the distinction between activation and deployment to
+         //remove these annoyances and edge cases.
+         //The post office should load(=deploy) all bindings on startup including loading their
+         //state before adding the binding - there should be no separate deployment stage
+         //If the queue can be undeployed there should be a separate flag for this on the
+         //binding
+         queue.deliver();
+         
          log.info(this + " started, fullSize=" + destination.getFullSize() +
                   ", pageSize=" + destination.getPageSize() + ", downCacheSize=" + destination.getDownCacheSize());
       }

Modified: trunk/src/main/org/jboss/jms/server/destination/TopicService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -102,7 +102,23 @@
                new MessageCounter(counterName, subName, queue, true, true,
                                   dayLimitToUse);
             
-            serverPeer.getMessageCounterManager().registerMessageCounter(counterName, counter);            
+            serverPeer.getMessageCounterManager().registerMessageCounter(counterName, counter);    
+            
+            //Now we need to trigger a delivery - this is because message suckers might have
+            //been create *before* the queue was deployed - this is because message suckers can be
+            //created when the clusterpullconnectionfactory deploy is detected which then causes
+            //the clusterconnectionmanager to inspect the bindings for queues to create suckers
+            //to - but these bindings will exist before the queue or topic is deployed and before
+            //it has had its messages loaded
+            //Therefore we need to trigger a delivery now so remote suckers get messages
+            //See http://jira.jboss.org/jira/browse/JBMESSAGING-1136
+            //For JBM we should remove the distinction between activation and deployment to
+            //remove these annoyances and edge cases.
+            //The post office should load(=deploy) all bindings on startup including loading their
+            //state before adding the binding - there should be no separate deployment stage
+            //If the queue can be undeployed there should be a separate flag for this on the
+            //binding
+            queue.deliver();
          }
 
          serverPeer.getDestinationManager().registerDestination(destination);

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -57,6 +57,7 @@
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.Binding;
 import org.jboss.messaging.core.contract.Delivery;
+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.PostOffice;
@@ -698,7 +699,7 @@
       if (dest.isDirect())
       {
       	//Route directly to queue - temp kludge for clustering
-      	
+         
       	Binding binding = postOffice.getBindingForQueueName(dest.getName());
       	
       	if (binding == null)
@@ -708,7 +709,9 @@
       	
       	Queue queue = binding.queue;
       	
-      	Delivery del = queue.handle(null, ref, tx);
+         Long scid = (Long)ref.getMessage().removeHeader(Message.SOURCE_CHANNEL_ID);
+         
+         Delivery del = queue.handleMove(ref, scid.longValue());
       	
       	if (del == null)
       	{

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -438,6 +438,11 @@
 
    // Package protected ----------------------------------------------------------------------------
    
+   boolean isRemote()
+   {
+      return this.remote;
+   }       
+   
    boolean isReplicating()
    {
    	return replicating;

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1768,8 +1768,18 @@
          return false;
       }
       
-      rec.del.acknowledge(null);  
+      ServerConsumerEndpoint consumer = rec.getConsumer();
       
+      if (consumer != null && consumer.isRemote())
+      {
+         //Optimisation for shared DB - we don't ack in DB - we move
+         rec.del.getObserver().acknowledgeNoPersist(rec.del);
+      }
+      else
+      {      
+         rec.del.acknowledge(null);
+      }
+           
       //Now replicate the ack
       
       if (rec.replicating && replicating)

Modified: trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -66,9 +66,7 @@
    public synchronized void start()
    {
       if (started)
-      {
-         log.warn(this + " already started");
-         
+      {  
          return;
       }
       
@@ -83,11 +81,9 @@
    }
 
    public synchronized void stop()
-   {
+   { 
       if (!started)
       {
-         log.warn(this + " isn't started");
-         
          return;
       }
       

Modified: trunk/src/main/org/jboss/messaging/core/contract/DeliveryObserver.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/DeliveryObserver.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/contract/DeliveryObserver.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -32,6 +32,8 @@
 public interface DeliveryObserver
 {
    void acknowledge(Delivery d, Transaction tx) throws Throwable;
+   
+   void acknowledgeNoPersist(Delivery d) throws Throwable;
 
    void cancel(Delivery d) throws Throwable;
 }

Modified: trunk/src/main/org/jboss/messaging/core/contract/Message.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/Message.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/contract/Message.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -43,8 +43,15 @@
 	 * The header is checked when sucking messages and if order preservation is true then the message is not accepted.
 	 * This is a basic way of ensuring message order is preserved.
 	 */
-	public static final String CLUSTER_SUCKED = "CLUSTER_SUCKED";
+	public static final String CLUSTER_SUCKED = "SUCKED";
 	
+	/**
+	 * This header is set on a message when it is sucked from one node to another.
+	 * If the header exists on the destination node, and the message is persistent, the message
+	 * will be moved from one channel to the other by doing a simple database update
+	 */
+	public static final String SOURCE_CHANNEL_ID = "SCID";
+		
    /**    
     * @return The unique id of the message
     */

Modified: trunk/src/main/org/jboss/messaging/core/contract/PersistenceManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/PersistenceManager.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/contract/PersistenceManager.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -40,6 +40,8 @@
 public interface PersistenceManager extends MessagingComponent
 {
    void addReference(long channelID, MessageReference ref, Transaction tx) throws Exception;
+   
+   void moveReference(long sourceChannelID, long destChannelID, MessageReference ref) throws Exception;
 
    void removeReference(long channelID, MessageReference ref, Transaction tx) throws Exception;
    

Modified: trunk/src/main/org/jboss/messaging/core/contract/Queue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/contract/Queue.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/contract/Queue.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -91,4 +91,7 @@
    Map getRecoveryArea();
    
    int getRecoveryMapSize();
+   
+   //Optimisation for shared database
+   Delivery handleMove(MessageReference ref, long sourceChannelID);   
 }

Modified: trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/ChannelSupport.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -35,8 +35,8 @@
 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;
 import org.jboss.messaging.core.impl.tx.Transaction;
 import org.jboss.messaging.core.impl.tx.TransactionException;
@@ -129,7 +129,62 @@
    }
    
    // Receiver implementation ----------------------------------------------------------------------
+   
+   //Optimisation
+   public Delivery handleMove(MessageReference ref, long sourceChannelID)
+   {
+      if (!isActive())
+      {  
+         if (trace) { log.trace(this + " is not active, returning null delivery for " + ref); }
+         
+         return null;
+      }
 
+      checkClosed();
+           
+      if (trace) { log.trace(this + " moving ref " + ref + " from channel " + sourceChannelID); }
+      
+      if (maxSize != -1 && getMessageCount() >= maxSize)
+      {
+         //Have reached maximum size - will drop message
+         
+         log.warn(this + " has reached maximum size, " + ref + " will be dropped");
+         
+         return null;
+      }
+   
+      // Each channel has its own copy of the reference
+      ref = ref.copy();
+
+      try
+      {           
+         if (ref.getMessage().isReliable() && recoverable)
+         {
+            // Reliable message in a recoverable state - also add to db
+            if (trace) { log.trace(this + " adding " + ref + " to database non-transactionally"); }
+            
+            pm.moveReference(sourceChannelID, channelID, ref);        
+         }
+         
+         synchronized (lock)
+         {
+            addReferenceInMemory(ref);
+            
+            deliverInternal();
+         }
+            
+         messagesAdded.increment();
+      }
+      catch (Throwable t)
+      {
+         log.error("Failed to handle message", t);
+
+         return null;
+      }
+
+      return new SimpleDelivery(this, ref, true, false);  
+   }
+   
    public Delivery handle(DeliveryObserver sender, MessageReference ref, Transaction tx)
    {
       if (!isActive())
@@ -141,7 +196,78 @@
 
       checkClosed();
       
-      return handleInternal(sender, ref, tx, true);      
+      if (ref == null)
+      {
+         return null;
+      }
+
+      if (trace) { log.trace(this + " handles " + ref + (tx == null ? " non-transactionally" : " in transaction: " + tx)); }
+      
+      if (maxSize != -1 && getMessageCount() >= maxSize)
+      {
+         //Have reached maximum size - will drop message
+         
+         log.warn(this + " has reached maximum size, " + ref + " will be dropped");
+         
+         return null;
+      }
+   
+      // Each channel has its own copy of the reference
+      ref = ref.copy();
+
+      try
+      {           
+         if (tx == null)
+         {
+            if (ref.getMessage().isReliable() && recoverable)
+            {
+               // Reliable message in a recoverable state - also add to db
+               if (trace) { log.trace(this + " adding " + ref + " to database non-transactionally"); }
+               
+               pm.addReference(channelID, ref, null);        
+            }
+            
+            // If the ref has a scheduled delivery time then we don't add to the in memory queue
+            // instead we create a timeout, so when that time comes delivery will attempted directly
+            
+            if (!checkAndSchedule(ref))
+            {               
+               synchronized (lock)
+               {
+                  addReferenceInMemory(ref);
+                  
+                  deliverInternal();
+               }            
+            }
+         }
+         else
+         {
+            if (trace) { log.trace(this + " adding " + ref + " to state " + (tx == null ? "non-transactionally" : "in transaction: " + tx)); }
+
+            // add to post commit callback
+            getCallback(tx).addRef(ref);
+            
+            if (trace) { log.trace(this + " added transactionally " + ref + " in memory"); }
+            
+            if (ref.getMessage().isReliable() && recoverable)
+            {
+               // Reliable message in a recoverable state - also add to db
+               if (trace) { log.trace(this + " adding " + ref + (tx == null ? " to database non-transactionally" : " in transaction: " + tx)); }
+
+               pm.addReference(channelID, ref, tx);
+            }
+         }
+         
+         messagesAdded.increment();
+      }
+      catch (Throwable t)
+      {
+         log.error("Failed to handle message", t);
+
+         return null;
+      }
+
+      return new SimpleDelivery(this, ref, true, false);     
    }
 
    // DeliveryObserver implementation --------------------------------------------------------------
@@ -152,6 +278,11 @@
 
       acknowledgeInternal(d, tx, true);
    }
+   
+   public void acknowledgeNoPersist(Delivery d) throws Throwable
+   {
+      acknowledgeInternal(d, null, false);
+   }
 
    public void cancel(Delivery del) throws Throwable
    {
@@ -580,86 +711,7 @@
       
       return false;
    }
-      
-   protected Delivery handleInternal(DeliveryObserver sender, MessageReference ref,
-                                     Transaction tx, boolean persist)
-   {
-      if (ref == null)
-      {
-         return null;
-      }
-
-      if (trace) { log.trace(this + " handles " + ref + (tx == null ? " non-transactionally" : " in transaction: " + tx)); }
-      
-      if (maxSize != -1 && getMessageCount() >= maxSize)
-      {
-         //Have reached maximum size - will drop message
          
-         log.warn(this + " has reached maximum size, " + ref + " will be dropped");
-         
-         return null;
-      }
-   
-      // Each channel has its own copy of the reference
-      ref = ref.copy();
-
-      try
-      {        	
-         if (tx == null)
-         {
-            if (persist && ref.getMessage().isReliable() && recoverable)
-            {
-               // Reliable message in a recoverable state - also add to db
-               if (trace) { log.trace(this + " adding " + ref + " to database non-transactionally"); }
-               
-               // TODO - this db access could safely be done outside the event loop
-               pm.addReference(channelID, ref, null);        
-            }
-            
-            // If the ref has a scheduled delivery time then we don't add to the in memory queue
-            // instead we create a timeout, so when that time comes delivery will attempted directly
-            
-            if (!checkAndSchedule(ref))
-            {               
-               synchronized (lock)
-               {
-                  addReferenceInMemory(ref);
-                  
-                  deliverInternal();
-               }            
-            }
-         }
-         else
-         {
-            if (trace) { log.trace(this + " adding " + ref + " to state " + (tx == null ? "non-transactionally" : "in transaction: " + tx)); }
-
-            // add to post commit callback
-            getCallback(tx).addRef(ref);
-            
-            if (trace) { log.trace(this + " added transactionally " + ref + " in memory"); }
-            
-            if (persist && ref.getMessage().isReliable() && recoverable)
-            {
-               // Reliable message in a recoverable state - also add to db
-               if (trace) { log.trace(this + " adding " + ref + (tx == null ? " to database non-transactionally" : " in transaction: " + tx)); }
-
-               pm.addReference(channelID, ref, tx);
-            }
-         }
-         
-         messagesAdded.increment();
-      }
-      catch (Throwable t)
-      {
-         log.error("Failed to handle message", t);
-
-         return null;
-      }
-
-      return new SimpleDelivery(this, ref, true, false);
-   }
-
-   
    protected boolean checkAndSchedule(MessageReference ref)
    {
       if (ref.getScheduledDeliveryTime() > System.currentTimeMillis())

Modified: trunk/src/main/org/jboss/messaging/core/impl/JDBCPersistenceManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/JDBCPersistenceManager.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/JDBCPersistenceManager.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -70,97 +70,107 @@
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
  * @author <a href="mailto:juha at jboss.org">Juha Lindfors</a>
- *
+ * 
  * @version <tt>1.1</tt>
- *
+ * 
  * JDBCPersistenceManager.java,v 1.1 2006/02/22 17:33:41 timfox Exp
  */
-public class JDBCPersistenceManager extends JDBCSupport implements PersistenceManager
+public class JDBCPersistenceManager extends JDBCSupport implements
+      PersistenceManager
 {
    // Constants -----------------------------------------------------
-   
-   private static final Logger log = Logger.getLogger(JDBCPersistenceManager.class); 
 
+   private static final Logger log = Logger
+         .getLogger(JDBCPersistenceManager.class);
+
    // Static --------------------------------------------------------
-      
+
    private boolean trace = log.isTraceEnabled();
-      
+
    private boolean usingBinaryStream = true;
-   
+
    private boolean usingTrailingByte = false;
-   
+
    private int maxParams;
-   
+
    private short orderCount;
-   
+
    private int nodeID;
-   
+
    private boolean nodeIDSet;
-   
-   // Some versions of the oracle driver don't support binding blobs on select clauses,
-   // what would force us to use a two stage insert (insert and if successful, update)
+
+   // Some versions of the oracle driver don't support binding blobs on select
+   // clauses,
+   // what would force us to use a two stage insert (insert and if successful,
+   // update)
    private boolean supportsBlobSelect;
 
    // Constructors --------------------------------------------------
-    
-   public JDBCPersistenceManager(DataSource ds, TransactionManager tm, Properties sqlProperties,
-                                 boolean createTablesOnStartup, boolean usingBatchUpdates,
-                                 boolean usingBinaryStream, boolean usingTrailingByte, int maxParams,
-                                 boolean supportsBlobSelect)
+
+   public JDBCPersistenceManager(DataSource ds, TransactionManager tm,
+         Properties sqlProperties, boolean createTablesOnStartup,
+         boolean usingBatchUpdates, boolean usingBinaryStream,
+         boolean usingTrailingByte, int maxParams, boolean supportsBlobSelect)
    {
       super(ds, tm, sqlProperties, createTablesOnStartup);
-      
-      //usingBatchUpdates is currently ignored due to sketchy support from databases
-      
+
+      // usingBatchUpdates is currently ignored due to sketchy support from
+      // databases
+
       this.usingBinaryStream = usingBinaryStream;
-      
+
       this.usingTrailingByte = usingTrailingByte;
-      
-      this.maxParams = maxParams;    
-         
+
+      this.maxParams = maxParams;
+
       this.supportsBlobSelect = supportsBlobSelect;
    }
-   
-   
+
    // MessagingComponent overrides ---------------------------------
-   
+
    public void start() throws Exception
    {
       super.start();
 
       Connection conn = null;
-      
+
       PreparedStatement ps = null;
 
       TransactionWrapper wrap = new TransactionWrapper();
 
       try
       {
-         conn = ds.getConnection();      
-         //JBossMessaging requires transaction isolation of READ_COMMITTED
-         //Any looser isolation level and we cannot maintain consistency for paging (HSQL)
+         conn = ds.getConnection();
+         // JBossMessaging requires transaction isolation of READ_COMMITTED
+         // Any looser isolation level and we cannot maintain consistency for
+         // paging (HSQL)
          if (conn.getTransactionIsolation() != Connection.TRANSACTION_READ_COMMITTED)
          {
             int level = conn.getTransactionIsolation();
 
-            String warn =
-               "\n\n" +
-               "JBoss Messaging Warning: DataSource connection transaction isolation should be READ_COMMITTED, but it is currently " + Util.transactionIsolationToString(level) + ".\n" +
-               "                         Using an isolation level less strict than READ_COMMITTED may lead to data consistency problems.\n" +
-               "                         Using an isolation level more strict than READ_COMMITTED may lead to deadlock.\n";
+            String warn = "\n\n"
+                  + "JBoss Messaging Warning: DataSource connection transaction isolation should be READ_COMMITTED, but it is currently "
+                  + Util.transactionIsolationToString(level)
+                  + ".\n"
+                  + "                         Using an isolation level less strict than READ_COMMITTED may lead to data consistency problems.\n"
+                  + "                         Using an isolation level more strict than READ_COMMITTED may lead to deadlock.\n";
             log.warn(warn);
          }
-         
+
          log.debug("Adding record on JBM_DUAL");
-         
-         //Now we need to insert a row in the DUAL table if it doesn't contain one already
+
+         // Now we need to insert a row in the DUAL table if it doesn't contain
+         // one already
          ps = conn.prepareStatement(this.getSQLStatement("INSERT_DUAL"));
-         
+
          try
          {
-         	int rows = ps.executeUpdate();
-         
-         	if (trace) { log.trace("Inserted " + rows + " rows into dual"); }
+            int rows = ps.executeUpdate();
+
+            if (trace)
+            {
+               log.trace("Inserted " + rows + " rows into dual");
+            }
          }
          catch (SQLException e)
          {
@@ -171,23 +181,31 @@
             log.debug("Checking for existance on JBM_DUAL");
 
             Statement selectCount = conn.createStatement();
-            ResultSet rset = selectCount.executeQuery(this.getSQLStatement("CHECK_DUAL"));
+            ResultSet rset = selectCount.executeQuery(this
+                  .getSQLStatement("CHECK_DUAL"));
             try
             {
-               // if JBM_DUAL is empty, and if an exception happened, we should warn!
-               // if JBM_DUAL has a line already, we don't care about the exception...
+               // if JBM_DUAL is empty, and if an exception happened, we should
+               // warn!
+               // if JBM_DUAL has a line already, we don't care about the
+               // exception...
                if (!rset.next())
                {
-                  log.debug("JBM_DUAL didn't have a record.. throwing exception", e);
+                  log
+                        .debug(
+                              "JBM_DUAL didn't have a record.. throwing exception",
+                              e);
                   throw e;
                }
 
-
-               // if there are two lines or more on JBM_DUAL, that is also a problem
+               // if there are two lines or more on JBM_DUAL, that is also a
+               // problem
                if (rset.next())
                {
-                  log.debug("duplicated record found on JBM_DUAL... throwing exception");
-                  throw new IllegalStateException("JBM_DUAL is missing a primary key as it allowed a duplicate value");
+                  log
+                        .debug("duplicated record found on JBM_DUAL... throwing exception");
+                  throw new IllegalStateException(
+                        "JBM_DUAL is missing a primary key as it allowed a duplicate value");
                }
             }
             finally
@@ -201,7 +219,7 @@
                {
                }
             }
-         }         
+         }
       }
       catch (Exception e)
       {
@@ -214,88 +232,93 @@
          closeConnection(conn);
          wrap.end();
       }
-         
+
       log.debug(this + " started");
    }
-   
+
    // Injection -------------------------------------------------
-   
+
    // This is only known by server peer so we inject it after startup
-   
+
    public void injectNodeID(int nodeID)
    {
-   	this.nodeID = nodeID;
-   	
-   	this.nodeIDSet = true;
-   }      
-   
+      this.nodeID = nodeID;
+
+      this.nodeIDSet = true;
+   }
+
    // PersistenceManager implementation -------------------------
-         
+
    // Related to XA Recovery
    // ======================
-   
-   public List getMessageChannelPairRefsForTx(long transactionId) throws Exception
+
+   public List getMessageChannelPairRefsForTx(long transactionId)
+         throws Exception
    {
       String sql = this.getSQLStatement("SELECT_MESSAGE_ID_FOR_REF");
       return getMessageChannelPair(sql, transactionId);
    }
-   
-   public List getMessageChannelPairAcksForTx(long transactionId) throws Exception
+
+   public List getMessageChannelPairAcksForTx(long transactionId)
+         throws Exception
    {
       String sql = this.getSQLStatement("SELECT_MESSAGE_ID_FOR_ACK");
       return getMessageChannelPair(sql, transactionId);
    }
-   
+
    public List retrievePreparedTransactions() throws Exception
    {
       if (!this.nodeIDSet)
       {
-      	//Sanity
-      	throw new IllegalStateException("Node id has not been set");
+         // Sanity
+         throw new IllegalStateException("Node id has not been set");
       }
-   	
-      /* Note the API change for 1.0.2 XA Recovery -- List now contains instances of PreparedTxInfo<TxId, Xid>
-       * instead of direct Xids [JPL] */
-      
+
+      /*
+       * Note the API change for 1.0.2 XA Recovery -- List now contains
+       * instances of PreparedTxInfo<TxId, Xid> instead of direct Xids [JPL]
+       */
+
       Connection conn = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       PreparedTxInfo txInfo = null;
       TransactionWrapper wrap = new TransactionWrapper();
-      
+
       try
       {
-         List<PreparedTxInfo> transactions = new ArrayList<PreparedTxInfo> ();
-         
+         List<PreparedTxInfo> transactions = new ArrayList<PreparedTxInfo>();
+
          conn = ds.getConnection();
-         
-         st = conn.prepareStatement(getSQLStatement("SELECT_PREPARED_TRANSACTIONS"));
-         
+
+         st = conn
+               .prepareStatement(getSQLStatement("SELECT_PREPARED_TRANSACTIONS"));
+
          st.setInt(1, nodeID);
-         
+
          rs = st.executeQuery();
-         
+
          while (rs.next())
          {
-            //get the existing tx id --MK START
+            // get the existing tx id --MK START
             long txId = rs.getLong(1);
-            
+
             byte[] branchQual = getVarBinaryColumn(rs, 2);
-            
+
             int formatId = rs.getInt(3);
-            
+
             byte[] globalTxId = getVarBinaryColumn(rs, 4);
-            
+
             Xid xid = new MessagingXid(branchQual, formatId, globalTxId);
-            
+
             // create a tx info object with the result set detailsdetails
             txInfo = new PreparedTxInfo(txId, xid);
-            
+
             transactions.add(txInfo);
          }
-         
+
          return transactions;
-         
+
       }
       catch (Exception e)
       {
@@ -304,110 +327,135 @@
       }
       finally
       {
-      	closeResultSet(rs);
-      	closeStatement(st);
-      	closeConnection(conn);
+         closeResultSet(rs);
+         closeStatement(st);
+         closeConnection(conn);
          wrap.end();
       }
    }
-         
+
    // Related to counters
    // ===================
-   
-   public long reserveIDBlock(final String counterName, final int size) throws Exception
+
+   public long reserveIDBlock(final String counterName, final int size)
+         throws Exception
    {
-      if (trace) { log.trace("Getting ID block for counter " + counterName + ", size " + size); }
-      
-      if (size <= 0)
+      if (trace)
       {
-         throw new IllegalArgumentException("block size must be > 0");
+         log.trace("Getting ID block for counter " + counterName + ", size "
+               + size);
       }
-      
+
+      if (size <= 0) { throw new IllegalArgumentException(
+            "block size must be > 0"); }
+
       class ReserveIDBlockRunner extends JDBCTxRunner2<Long>
       {
-      	public Long doTransaction() throws Exception
-   		{
-            //	For the clustered case - this MUST use SELECT .. FOR UPDATE or a similar
-            //construct the locks the row
+         public Long doTransaction() throws Exception
+         {
+            // For the clustered case - this MUST use SELECT .. FOR UPDATE or a
+            // similar
+            // construct the locks the row
             String selectCounterSQL = getSQLStatement("SELECT_COUNTER");
-            
+
             PreparedStatement ps = null;
             ResultSet rs = null;
-            
+
             try
-            {            
-	            ps = conn.prepareStatement(selectCounterSQL);
-	
-	            ps.setString(1, counterName);
-	            
-	            rs = ps.executeQuery();
-	            
-	            if (trace) { log.trace(JDBCUtil.statementToString(selectCounterSQL, counterName)); }         
-	            
-	            if (!rs.next())
-	            {
-	               rs.close();
-	               rs = null;
-	               
-	               ps.close();
-	               
-	               //There is a very small possibility that two threads will attempt to insert the same counter
-	               //at the same time, if so, then the second one will fail eventually after a few retries by throwing
-	               //a primary key violation.
-	               
-	               String insertCounterSQL = getSQLStatement("INSERT_COUNTER");
-	               
-	               ps = conn.prepareStatement(insertCounterSQL);
-	               
-	               ps.setString(1, counterName);
-	               ps.setLong(2, size);
-	               
-	               int rows = ps.executeUpdate();
-	               if (trace) { log.trace(JDBCUtil.statementToString(insertCounterSQL, counterName, new Integer(size)) + " inserted " + rows + " rows"); }
-	               
-	               return 0L;
-	            }
-	            
-	            long nextId = rs.getLong(1);
-	            
-	            ps.close();
-	
-	            String updateCounterSQL = getSQLStatement("UPDATE_COUNTER");
-	
-	            ps = conn.prepareStatement(updateCounterSQL);
-	            
-	            ps.setLong(1, nextId + size);
-	            ps.setString(2, counterName);
+            {
+               ps = conn.prepareStatement(selectCounterSQL);
 
-	            int rows = ps.executeUpdate();
+               ps.setString(1, counterName);
 
-	            if (trace) { log.trace(JDBCUtil.statementToString(updateCounterSQL, new Long(nextId + size), counterName) + " updated " + rows + " rows"); }
+               rs = ps.executeQuery();
 
-	            return nextId;
+               if (trace)
+               {
+                  log.trace(JDBCUtil.statementToString(selectCounterSQL,
+                        counterName));
+               }
+
+               if (!rs.next())
+               {
+                  rs.close();
+                  ps.close();
+
+                  // There is a very small possibility that two threads will
+                  // attempt to insert the same counter
+                  // at the same time, if so, then the second one will fail
+                  // eventually after a few retries by throwing
+                  // a primary key violation.
+
+                  String insertCounterSQL = getSQLStatement("INSERT_COUNTER");
+
+                  ps = conn.prepareStatement(insertCounterSQL);
+
+                  ps.setString(1, counterName);
+                  ps.setLong(2, size);
+
+                  int rows = ps.executeUpdate();
+                  if (trace)
+                  {
+                     log.trace(JDBCUtil.statementToString(insertCounterSQL,
+                           counterName, new Integer(size))
+                           + " inserted " + rows + " rows");
+                  }
+
+                  return 0L;
+               }
+               else
+               {
+                  long nextId = rs.getLong(1);
+   
+                  rs.close();
+                  ps.close();
+   
+                  String updateCounterSQL = getSQLStatement("UPDATE_COUNTER");
+   
+                  ps = conn.prepareStatement(updateCounterSQL);
+   
+                  ps.setLong(1, nextId + size);
+                  ps.setString(2, counterName);
+   
+                  int rows = ps.executeUpdate();
+   
+                  if (trace)
+                  {
+                     log.trace(JDBCUtil.statementToString(updateCounterSQL,
+                           new Long(nextId + size), counterName)
+                           + " updated " + rows + " rows");
+                  }
+   
+                  return nextId;
+               }
             }
             finally
             {
-            	closeResultSet(rs);
-            	closeStatement(ps);
+               closeResultSet(rs);
+               closeStatement(ps);
             }
-   		}
+         }
       }
-      
+
       return new ReserveIDBlockRunner().executeWithRetry();
    }
-         
+
    /*
-    * Retrieve a List of messages corresponding to the specified List of message ids.
-    * The implementation here for HSQLDB does this by using a PreparedStatment with an IN clause
-    * with a maximum of 100 elements.
-    * If there are more than maxParams message to retrieve this is repeated a number of times.
-    * For "Enterprise" databases (Oracle, DB2, Sybase etc) a more sophisticated technique should be used
-    * e.g. Oracle ARRAY types in Oracle which can be submitted as a param to an Oracle prepared statement
+    * Retrieve a List of messages corresponding to the specified List of message
+    * ids. The implementation here for HSQLDB does this by using a
+    * PreparedStatment with an IN clause with a maximum of 100 elements. If
+    * there are more than maxParams message to retrieve this is repeated a
+    * number of times. For "Enterprise" databases (Oracle, DB2, Sybase etc) a
+    * more sophisticated technique should be used e.g. Oracle ARRAY types in
+    * Oracle which can be submitted as a param to an Oracle prepared statement
     * Although this would all be DB specific.
     */
    public List getMessages(final List messageIds) throws Exception
    {
-      if (trace) { log.trace("Getting batch of messages for " + messageIds); }
+      if (trace)
+      {
+         log.trace("Getting batch of messages for " + messageIds);
+      }
 
       class GetMessageListTX extends JDBCTxRunner2<List>
       {
@@ -431,8 +479,9 @@
                {
                   if (ps == null)
                   {
-                     //PreparedStatements are cached in the JCA layer so we will never actually have more than
-                     //100 distinct ones
+                     // PreparedStatements are cached in the JCA layer so we
+                     // will never actually have more than
+                     // 100 distinct ones
                      int numParams;
                      if (count < (size / maxParams) * maxParams)
                      {
@@ -442,8 +491,11 @@
                      {
                         numParams = size % maxParams;
                      }
-                     StringBuffer buff = new StringBuffer(getSQLStatement("LOAD_MESSAGES"));
-                     buff.append(" WHERE ").append(getSQLStatement("MESSAGE_ID_COLUMN")).append(" IN (");
+                     StringBuffer buff = new StringBuffer(
+                           getSQLStatement("LOAD_MESSAGES"));
+                     buff.append(" WHERE ").append(
+                           getSQLStatement("MESSAGE_ID_COLUMN"))
+                           .append(" IN (");
                      for (int i = 0; i < numParams; i++)
                      {
                         buff.append("?");
@@ -461,7 +513,7 @@
                      }
                   }
 
-                  long msgId = ((Long)iter.next()).longValue();
+                  long msgId = ((Long) iter.next()).longValue();
 
                   ps.setLong((count % maxParams) + 1, msgId);
 
@@ -491,20 +543,22 @@
 
                         byte type = rs.getByte(8);
 
-                        Message m = MessageFactory.createMessage(messageId, reliable, expiration, timestamp, priority,
-                                                                 headers, payload, type);
+                        Message m = MessageFactory.createMessage(messageId,
+                              reliable, expiration, timestamp, priority,
+                              headers, payload, type);
                         msgs.add(m);
                      }
 
                      rs.close();
-                     rs = null;
-
                      ps.close();
                      ps = null;
                   }
                }
 
-               if (trace) { log.trace("Loaded " + msgs.size() + " messages in total"); }
+               if (trace)
+               {
+                  log.trace("Loaded " + msgs.size() + " messages in total");
+               }
 
                return msgs;
             }
@@ -520,270 +574,312 @@
          }
       }
 
-
       return new GetMessageListTX().executeWithRetry();
 
-      
    }
-   
-       
+
    // Related to paging functionality
-   // ===============================                 
-   
-   //Used to page NP messages or P messages in a non recoverable queue
-   
-   public void pageReferences(final long channelID, final List references, final boolean page) throws Exception
-   {  
-   	if (trace) { log.trace("Paging references in channel " + channelID + " refs " + references.size()); }
-   	
-   	class PageReferencesRunner extends JDBCTxRunner2
-      {	
-      	public Object doTransaction() throws Exception
-   		{
-      		PreparedStatement psInsertReference = null;
-      		PreparedStatement psInsertMessage = null;
+   // ===============================
+
+   // Used to page NP messages or P messages in a non recoverable queue
+
+   public void pageReferences(final long channelID, final List references,
+         final boolean page) throws Exception
+   {
+      if (trace)
+      {
+         log.trace("Paging references in channel " + channelID + " refs "
+               + references.size());
+      }
+
+      class PageReferencesRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psInsertReference = null;
+            PreparedStatement psInsertMessage = null;
             PreparedStatement psUpdateMessage = null;
 
             try
-      		{      		
-	      		Iterator iter = references.iterator();
-	
-	         	psInsertReference = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
+            {
+               Iterator iter = references.iterator();
 
+               psInsertReference = conn
+                     .prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
+
                if (supportsBlobSelect)
                {
-                  psInsertMessage = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE_CONDITIONAL_FULL"));
+                  psInsertMessage = conn
+                        .prepareStatement(getSQLStatement("INSERT_MESSAGE_CONDITIONAL_FULL"));
                }
                else
                {
-                  psInsertMessage = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE_CONDITIONAL"));
-                  psUpdateMessage = conn.prepareStatement(getSQLStatement("UPDATE_MESSAGE_4CONDITIONAL"));
+                  psInsertMessage = conn
+                        .prepareStatement(getSQLStatement("INSERT_MESSAGE_CONDITIONAL"));
+                  psUpdateMessage = conn
+                        .prepareStatement(getSQLStatement("UPDATE_MESSAGE_4CONDITIONAL"));
                }
-	
+
                while (iter.hasNext())
-	         	{
-	         		//We may need to persist the message itself 
-	         		MessageReference ref = (MessageReference) iter.next();
-	
-	         		//For non reliable refs we insert the ref (and maybe the message) itself
-	
-	         		//Now store the reference
-	
-	         		log.trace("Paged ref with page order " + ref.getPagingOrder());
-	
-	         		addReference(channelID, ref, psInsertReference, page);
-	
-	         		int rows = psInsertReference.executeUpdate();
-	
-	         		if (trace)
-	         		{
-	         			log.trace("Inserted " + rows + " rows");
-	         		}
-	
-	         		//Maybe we need to persist the message itself
-	         		Message m = ref.getMessage();
+               {
+                  // We may need to persist the message itself
+                  MessageReference ref = (MessageReference) iter.next();
 
+                  // For non reliable refs we insert the ref (and maybe the
+                  // message) itself
+
+                  // Now store the reference
+
+                  log
+                        .trace("Paged ref with page order "
+                              + ref.getPagingOrder());
+
+                  addReference(channelID, ref, psInsertReference, page);
+
+                  int rows = psInsertReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Inserted " + rows + " rows");
+                  }
+
+                  // Maybe we need to persist the message itself
+                  Message m = ref.getMessage();
+
                   rows = storeMessage(m, psInsertMessage, psUpdateMessage);
 
-                  if (trace) { log.trace("Inserted " + rows + " rows"); }
-	         	} 
-	         	
-	         	return null;
-      		}
-      		finally
-      		{
-      			closeStatement(psInsertReference);
+                  if (trace)
+                  {
+                     log.trace("Inserted " + rows + " rows");
+                  }
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psInsertReference);
                closeStatement(psInsertMessage);
                closeStatement(psUpdateMessage);
-      		}
-   		}
+            }
+         }
       }
-   	
-   	new PageReferencesRunner().executeWithRetry();   	
+
+      new PageReferencesRunner().executeWithRetry();
    }
-         
-   //After loading paged refs this is used to remove any NP or P messages in a unrecoverable channel
-   public void removeDepagedReferences(final long channelID, final List references) throws Exception
-   {   	
-      if (trace) { log.trace(this + " Removing depaged " + references.size() + " refs from channel " + channelID); }
-      
+
+   // After loading paged refs this is used to remove any NP or P messages in a
+   // unrecoverable channel
+   public void removeDepagedReferences(final long channelID,
+         final List references) throws Exception
+   {
+      if (trace)
+      {
+         log.trace(this + " Removing depaged " + references.size()
+               + " refs from channel " + channelID);
+      }
+
       class RemoveDepagedReferencesRunner extends JDBCTxRunner2
       {
-      	public Object doTransaction() throws Exception
-   		{
-		      PreparedStatement psDeleteReference = null; 
-		      
-		      try
-		      {	
-		         psDeleteReference = conn.prepareStatement(getSQLStatement("DELETE_MESSAGE_REF"));
-		         
-		         Iterator iter = references.iterator();		         
-		
-		         while (iter.hasNext())
-		         {
-		            MessageReference ref = (MessageReference) iter.next();
-		                                                             
-		            removeReference(channelID, ref, psDeleteReference);
-		            
-		            int rows = psDeleteReference.executeUpdate();
-		            
-		            if (trace) { log.trace("Deleted " + rows + " references"); }
-		            
-		         }         
-		         
-		         return null;
-		      }		      
-		      finally
-		      {
-		      	closeStatement(psDeleteReference);       
-		      }      
-   		}
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psDeleteReference = null;
+
+            try
+            {
+               psDeleteReference = conn
+                     .prepareStatement(getSQLStatement("DELETE_MESSAGE_REF"));
+
+               Iterator iter = references.iterator();
+
+               while (iter.hasNext())
+               {
+                  MessageReference ref = (MessageReference) iter.next();
+
+                  removeReference(channelID, ref, psDeleteReference);
+
+                  int rows = psDeleteReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Deleted " + rows + " references");
+                  }
+
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psDeleteReference);
+            }
+         }
       }
-            
+
       new RemoveDepagedReferencesRunner().executeWithRetry();
-      
+
       deleteMessages(references);
-   }   
-     
+   }
+
    // After loading paged refs this is used to update P messages to non paged
-   public void updateReferencesNotPagedInRange(final long channelID, final long orderStart, final long orderEnd, final long num) throws Exception
+   public void updateReferencesNotPagedInRange(final long channelID,
+         final long orderStart, final long orderEnd, final long num)
+         throws Exception
    {
-      if (trace) { log.trace("Updating paged references for channel " + channelID + " between " + orderStart + " and " + orderEnd); }
-      
+      if (trace)
+      {
+         log.trace("Updating paged references for channel " + channelID
+               + " between " + orderStart + " and " + orderEnd);
+      }
+
       class UpdateReferencesNotPagedInRangeRunner extends JDBCTxRunner2
       {
-      	public Object doTransaction() throws Exception
-   		{
-             PreparedStatement ps = null;
-             
-             try
-             {              
-		         ps = conn.prepareStatement(getSQLStatement("UPDATE_REFS_NOT_PAGED"));
-		                 
-		         ps.setLong(1, orderStart);
-		         
-		         ps.setLong(2, orderEnd);
-		         
-		         ps.setLong(3, channelID);
-		         
-		         int rows = ps.executeUpdate();
-		           
-		         if (trace) { log.trace(JDBCUtil.statementToString(getSQLStatement("UPDATE_REFS_NOT_PAGED"), new Long(channelID),
-		                                new Long(orderStart), new Long(orderEnd)) + " updated " + rows + " rows"); }
-		
-		         //Sanity check
-		         if (rows != num)
-		         {
-		            throw new IllegalStateException("Did not update correct number of rows");
-		         }     
-		         
-		         return null;
-		      }
-		      finally
-		      {
-		      	closeStatement(ps);
-		      }
-   		}
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement ps = null;
+
+            try
+            {
+               ps = conn
+                     .prepareStatement(getSQLStatement("UPDATE_REFS_NOT_PAGED"));
+
+               ps.setLong(1, orderStart);
+
+               ps.setLong(2, orderEnd);
+
+               ps.setLong(3, channelID);
+
+               int rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace(JDBCUtil.statementToString(
+                        getSQLStatement("UPDATE_REFS_NOT_PAGED"), new Long(
+                              channelID), new Long(orderStart), new Long(
+                              orderEnd))
+                        + " updated " + rows + " rows");
+               }
+
+               // Sanity check
+               if (rows != num) { throw new IllegalStateException(
+                     "Did not update correct number of rows"); }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(ps);
+            }
+         }
       }
-      
+
       new UpdateReferencesNotPagedInRangeRunner().executeWithRetry();
    }
-   
-   public void updatePageOrder(final long channelID, final List references) throws Exception
+
+   public void updatePageOrder(final long channelID, final List references)
+         throws Exception
    {
-      if (trace) { log.trace("Updating page order for channel:" + channelID); }
-      
+      if (trace)
+      {
+         log.trace("Updating page order for channel:" + channelID);
+      }
+
       class UpdatePageOrderRunner extends JDBCTxRunner2
       {
-      	public Object doTransaction() throws Exception
-   		{      
-      		PreparedStatement psUpdateReference = null;
-      		try
-      		{
-		         Iterator iter = references.iterator();
-		         
-		         psUpdateReference = conn.prepareStatement(getSQLStatement("UPDATE_PAGE_ORDER"));
-		
-		         while (iter.hasNext())
-		         {
-		            MessageReference ref = (MessageReference) iter.next();
-		                 
-		            psUpdateReference.setLong(1, ref.getPagingOrder());
-		
-		            psUpdateReference.setLong(2, ref.getMessage().getMessageID());
-		            
-		            psUpdateReference.setLong(3, channelID);
-		            
-		            int rows = psUpdateReference.executeUpdate();
-		               
-		            if (trace) { log.trace("Updated " + rows + " rows"); }		            
-		         }
-		                     
-		         return null;
-		      }
-		      finally
-		      {
-		      	closeStatement(psUpdateReference);
-		      }    
-   		}
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psUpdateReference = null;
+            try
+            {
+               Iterator iter = references.iterator();
+
+               psUpdateReference = conn
+                     .prepareStatement(getSQLStatement("UPDATE_PAGE_ORDER"));
+
+               while (iter.hasNext())
+               {
+                  MessageReference ref = (MessageReference) iter.next();
+
+                  psUpdateReference.setLong(1, ref.getPagingOrder());
+
+                  psUpdateReference.setLong(2, ref.getMessage().getMessageID());
+
+                  psUpdateReference.setLong(3, channelID);
+
+                  int rows = psUpdateReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Updated " + rows + " rows");
+                  }
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psUpdateReference);
+            }
+         }
       }
-      
-      new UpdatePageOrderRunner().executeWithRetry();      
+
+      new UpdatePageOrderRunner().executeWithRetry();
    }
-      
-   public List getPagedReferenceInfos(final long channelID, final long orderStart, final int number) throws Exception
+
+   public List getPagedReferenceInfos(final long channelID,
+         final long orderStart, final int number) throws Exception
    {
-      if (trace) { log.trace("loading message reference info for channel " + channelID + " from " + orderStart + " number " + number);      }
-                 
+      if (trace)
+      {
+         log.trace("loading message reference info for channel " + channelID
+               + " from " + orderStart + " number " + number);
+      }
+
       List<ReferenceInfo> refs = new ArrayList<ReferenceInfo>();
-      
+
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;
       TransactionWrapper wrap = new TransactionWrapper();
-      
+
       try
       {
          conn = ds.getConnection();
-         
+
          ps = conn.prepareStatement(getSQLStatement("LOAD_PAGED_REFS"));
-         
+
          ps.setLong(1, channelID);
-         
+
          ps.setLong(2, orderStart);
-         
+
          ps.setLong(3, orderStart + number - 1);
-         
+
          rs = ps.executeQuery();
-         
+
          long ord = orderStart;
-         
+
          while (rs.next())
          {
-            long msgId = rs.getLong(1);     
+            long msgId = rs.getLong(1);
             int deliveryCount = rs.getInt(2);
             int pageOrd = rs.getInt(3);
             long sched = rs.getLong(4);
-            
-            //Sanity check
-            if (pageOrd != ord)
-            {
-               throw new IllegalStateException("Unexpected pageOrd: " + pageOrd + " expected: " + ord);
-            }
-            
+
+            // Sanity check
+            if (pageOrd != ord) { throw new IllegalStateException(
+                  "Unexpected pageOrd: " + pageOrd + " expected: " + ord); }
+
             ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, sched);
-            
+
             refs.add(ri);
             ord++;
          }
-         
-         //Sanity check
-         if (ord != orderStart + number)
-         {
-            throw new IllegalStateException("Didn't load expected number of references, loaded: " + (ord - orderStart) +
-                                            " expected: " + number);
-         }
-         
+
+         // Sanity check
+         if (ord != orderStart + number) { throw new IllegalStateException(
+               "Didn't load expected number of references, loaded: "
+                     + (ord - orderStart) + " expected: " + number); }
+
          return refs;
       }
       catch (Exception e)
@@ -793,89 +889,135 @@
       }
       finally
       {
-      	closeResultSet(rs);
-      	closeStatement(ps);
-      	closeConnection(conn);       
+         closeResultSet(rs);
+         closeStatement(ps);
+         closeConnection(conn);
          wrap.end();
-      }      
-   }   
-   
+      }
+   }
+
    /*
     * Load the initial, non paged refs
     */
-   public InitialLoadInfo loadFromStart(final long channelID, final int number) throws Exception
+   public InitialLoadInfo loadFromStart(final long channelID, final int number)
+         throws Exception
    {
-      if (trace) { log.trace("loading initial reference infos for channel " + channelID);  }
-                    
+      if (trace)
+      {
+         log.trace("loading initial reference infos for channel " + channelID);
+      }
+
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;
       TransactionWrapper wrap = new TransactionWrapper();
-                                
+
       try
       {
-         conn = ds.getConnection();         
-         
-         //First we get the values for min() and max() page order
+         conn = ds.getConnection();
+
+         // First we get the values for min() and max() page order
          ps = conn.prepareStatement(getSQLStatement("SELECT_MIN_MAX_PAGE_ORD"));
-         
+
          ps.setLong(1, channelID);
-         
+
          rs = ps.executeQuery();
-                  
+
          rs.next();
-         
+
          Long minOrdering = new Long(rs.getLong(1));
-         
+
          if (rs.wasNull())
          {
             minOrdering = null;
          }
-         
+
          Long maxOrdering = new Long(rs.getLong(2));
-         
+
          if (rs.wasNull())
          {
             maxOrdering = null;
          }
-         
+
          ps.close();
-         
-         ps = null;
-         
+
          ps = conn.prepareStatement(getSQLStatement("LOAD_UNPAGED_REFS"));
-         
+
          ps.setLong(1, channelID);
-                 
+
          rs = ps.executeQuery();
-         
+
          List<ReferenceInfo> refs = new ArrayList<ReferenceInfo>();
-         
+
+         List<ReferenceInfo> refsToUpdate = new ArrayList<ReferenceInfo>();
+
          int count = 0;
          while (rs.next())
          {
-            long msgId = rs.getLong(1);            
+            long msgId = rs.getLong(1);
             int deliveryCount = rs.getInt(2);
             long sched = rs.getLong(3);
-            
+
             ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, sched);
-            
+
             if (count < number)
             {
                refs.add(ri);
-            }            
-            
+            }
+            else
+            {
+               refsToUpdate.add(ri);
+            }
+
             count++;
          }
-                  
-         //No refs paged
-            
-         if (count > number)
+
+         // No refs paged
+
+         if (!refsToUpdate.isEmpty())
          {
-            throw new IllegalStateException("Cannot load channel " + channelID + " since the fullSize parameter is too small to load " +
-                     " all the required references, fullSize needs to be at least " + count + " it is currently " + number);
+            // Take any overflow and convert them to paged refs
+
+            ps.close();
+            ps = conn.prepareStatement(getSQLStatement("UPDATE_PAGE_ORDER"));
+
+            Iterator<ReferenceInfo> iter = refsToUpdate.iterator();
+
+            long ordering = 0;
+
+            if (maxOrdering != null)
+            {
+               ordering = maxOrdering.longValue() + 1;
+            }
+
+            while (iter.hasNext())
+            {
+               ReferenceInfo ri = (ReferenceInfo) iter.next();
+
+               ps.setLong(1, ordering);
+
+               ps.setLong(2, ri.getMessageId());
+
+               ps.setLong(3, channelID);
+
+               int rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace("Updated " + rows + " rows");
+               }
+
+               ordering++;
+            }
+
+            if (minOrdering == null)
+            {
+               minOrdering = new Long(0);
+            }
+
+            maxOrdering = new Long(ordering - 1);
          }
-                         
+
          return new InitialLoadInfo(minOrdering, maxOrdering, refs);
       }
       catch (Exception e)
@@ -885,379 +1027,469 @@
       }
       finally
       {
-      	closeResultSet(rs);
-      	closeStatement(ps);      	
-      	closeConnection(conn);       
+         closeResultSet(rs);
+         closeStatement(ps);
+         closeConnection(conn);
          wrap.end();
-      }      
-   }   
-   
-   
+      }
+   }
+
    // Merging functionality
    // --------------------
-   
-   public void mergeTransactions(final long fromChannelID, final long toChannelID) throws Exception
+
+   public void mergeTransactions(final long fromChannelID,
+         final long toChannelID) throws Exception
    {
-      if (trace) { log.trace("Merging transactions from channel " + fromChannelID + " to " + toChannelID); }
-      
-      // Sanity check
-      
-      if (fromChannelID == toChannelID)
+      if (trace)
       {
-      	throw new IllegalArgumentException("Cannot merge transactions - they have the same channel id!!");
+         log.trace("Merging transactions from channel " + fromChannelID
+               + " to " + toChannelID);
       }
-      
+
+      // Sanity check
+
+      if (fromChannelID == toChannelID) { throw new IllegalArgumentException(
+            "Cannot merge transactions - they have the same channel id!!"); }
+
       class MergeTransactionsRunner extends JDBCTxRunner2
       {
-      	public Object doTransaction() throws Exception
-   		{
-		      PreparedStatement statement = null;
-		      try
-		      {
-		         statement = conn.prepareStatement(getSQLStatement("UPDATE_TX"));
-		         statement.setLong(1, toChannelID);
-		         statement.setLong(2, fromChannelID);
-		         int affected = statement.executeUpdate();
-		
-		         log.debug("Merged " + affected + " transactions from channel " + fromChannelID + " into node " + toChannelID);
-		         
-		         return null;
-		      }
-		      finally
-		      {
-		         closeStatement(statement);
-		      }
-   		}
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement statement = null;
+            try
+            {
+               statement = conn.prepareStatement(getSQLStatement("UPDATE_TX"));
+               statement.setLong(1, toChannelID);
+               statement.setLong(2, fromChannelID);
+               int affected = statement.executeUpdate();
+
+               log.debug("Merged " + affected + " transactions from channel "
+                     + fromChannelID + " into node " + toChannelID);
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(statement);
+            }
+         }
       }
-      
+
       new MergeTransactionsRunner().executeWithRetry();
    }
-   
-   public InitialLoadInfo mergeAndLoad(final long fromChannelID, final long toChannelID, final int numberToLoad, final long firstPagingOrder, final long nextPagingOrder) throws Exception
+
+   public InitialLoadInfo mergeAndLoad(final long fromChannelID,
+         final long toChannelID, final int numberToLoad,
+         final long firstPagingOrder, final long nextPagingOrder)
+         throws Exception
    {
-      if (trace) { log.trace("Merging channel from " + fromChannelID + " to " + toChannelID + " numberToLoad:" + numberToLoad + " firstPagingOrder:" + firstPagingOrder + " nextPagingOrder:" + nextPagingOrder); }
-      
-      //Sanity
-      
-      if (fromChannelID == toChannelID)
+      if (trace)
       {
-      	throw new IllegalArgumentException("Cannot merge queues - they have the same channel id!!");
+         log.trace("Merging channel from " + fromChannelID + " to "
+               + toChannelID + " numberToLoad:" + numberToLoad
+               + " firstPagingOrder:" + firstPagingOrder + " nextPagingOrder:"
+               + nextPagingOrder);
       }
 
+      // Sanity
+
+      if (fromChannelID == toChannelID) { throw new IllegalArgumentException(
+            "Cannot merge queues - they have the same channel id!!"); }
+
       class MergeAndLoadRunner extends JDBCTxRunner2
       {
-      	public Object doTransaction() throws Exception
-   		{      
-		      PreparedStatement ps = null;
-		      ResultSet rs = null;      
-		      PreparedStatement ps2 = null;
-		    
-		      try
-		      {
-		         /*
-		          * If channel is paging and has full size f
-		          * 
-		          * then we don't need to load any refs but we need to:
-		          * 
-		          * make sure the page ord is correct across the old paged and new refs
-		          * 
-		          * we know the max page ord (from the channel) for the old refs so we just need to:
-		          * 
-		          * 1) Iterate through the failed channel and update page_ord = max + 1, max + 2 etc
-		          * 
-		          * 2) update channel id
-		          * 
-		          * 
-		          * If channel is not paging and the total refs before and after <=f
-		          * 
-		          * 1) Load all refs from failed channel
-		          * 
-		          * 2) Update channel id
-		          * 
-		          * return those refs
-		          * 
-		          * 
-		          * If channel is not paging but total new refs > f
-		          * 
-		          * 1) Iterate through failed channel refs and take the first x to make the channel full
-		          * 
-		          * 2) Update the others with page_ord starting at zero 
-		          * 
-		          * 3) Update channel id
-		          * 
-		          * In general:
-		          * 
-		          * We have number to load n, max page size p
-		          * 
-		          * 1) Iterate through failed channel refs in page_ord order
-		          * 
-		          * 2) Put the first n in a List.
-		          * 
-		          * 3) Initialise page_ord_count to be p or 0 depending on whether it was specified
-		          * 
-		          * 4) Update the page_ord of the remaining refs accordiningly
-		          * 
-		          * 5) Update the channel id
-		          * 
-		          */
-		         
-		         //First load the refs from the failed channel
-		
-		         List<ReferenceInfo> refs = new ArrayList<ReferenceInfo>();
-		         
-		         ps = conn.prepareStatement(getSQLStatement("LOAD_REFS"));
-		         
-		         ps.setLong(1, fromChannelID);
-		                 
-		         rs = ps.executeQuery();
-		         
-		         int count = 0;
-		         
-		         boolean arePaged = false;
-		         
-		         long pageOrd = nextPagingOrder;
-		         
-		         while (rs.next())
-		         {
-		            long msgId = rs.getLong(1);            
-		            int deliveryCount = rs.getInt(2);
-		            long sched = rs.getLong(3);
-		            
-		            if (count < numberToLoad)
-		            {           
-		               ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, sched);
-		               
-		               refs.add(ri);
-		            }
-		            
-		            // Set page ord
-		            
-		            if (ps2 == null)
-		            {
-		               ps2 = conn.prepareStatement(getSQLStatement("UPDATE_PAGE_ORDER"));
-		            }
-		                
-		            if (count < numberToLoad)
-		            {
-		               ps2.setNull(1, Types.BIGINT);
-		               
-		               if (trace) { log.trace("Set page ord to null"); }
-		            }
-		            else
-		            {                                 
-		               ps2.setLong(1, pageOrd);
-		               
-		               if (trace) { log.trace("Set page ord to " + pageOrd); }
-		               
-		               arePaged = true; 
-		               
-		               pageOrd++;                      
-		            }
-		            
-		            ps2.setLong(2, msgId);
-		            
-		            ps2.setLong(3, fromChannelID);
-		            
-		            int rows = ps2.executeUpdate();
-		            
-		            if (trace) { log.trace("Update page ord updated " + rows + " rows"); }
-		
-		            count++;            
-		         }
-		         
-		         ps.close();
-		         
-		         ps = null;
-		         
-		         // Now swap the channel id
-		         
-		         ps = conn.prepareStatement(getSQLStatement("UPDATE_CHANNEL_ID"));
-		         
-		         ps.setLong(1, toChannelID);
-		         
-		         ps.setLong(2, fromChannelID);
-		         
-		         int rows = ps.executeUpdate();
-		         
-		         if (trace) { log.trace("Update channel id updated " + rows + " rows"); }
-		                           
-		         if (arePaged)
-		         {            
-		            return new InitialLoadInfo(new Long(firstPagingOrder), new Long(pageOrd - 1), refs);
-		         }
-		         else
-		         {
-		            return new InitialLoadInfo(null, null, refs);
-		         }         
-		      }
-		      finally
-		      {      
-		         closeResultSet(rs);
-		      	closeStatement(ps);
-		      	closeStatement(ps2);
-		      }
-   		}
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement ps = null;
+            ResultSet rs = null;
+            PreparedStatement ps2 = null;
+
+            try
+            {
+               /*
+                * If channel is paging and has full size f
+                * 
+                * then we don't need to load any refs but we need to:
+                * 
+                * make sure the page ord is correct across the old paged and new
+                * refs
+                * 
+                * we know the max page ord (from the channel) for the old refs
+                * so we just need to:
+                * 
+                * 1) Iterate through the failed channel and update page_ord =
+                * max + 1, max + 2 etc
+                * 
+                * 2) update channel id
+                * 
+                * 
+                * If channel is not paging and the total refs before and after
+                * <=f
+                * 
+                * 1) Load all refs from failed channel
+                * 
+                * 2) Update channel id
+                * 
+                * return those refs
+                * 
+                * 
+                * If channel is not paging but total new refs > f
+                * 
+                * 1) Iterate through failed channel refs and take the first x to
+                * make the channel full
+                * 
+                * 2) Update the others with page_ord starting at zero
+                * 
+                * 3) Update channel id
+                * 
+                * In general:
+                * 
+                * We have number to load n, max page size p
+                * 
+                * 1) Iterate through failed channel refs in page_ord order
+                * 
+                * 2) Put the first n in a List.
+                * 
+                * 3) Initialise page_ord_count to be p or 0 depending on whether
+                * it was specified
+                * 
+                * 4) Update the page_ord of the remaining refs accordiningly
+                * 
+                * 5) Update the channel id
+                * 
+                */
+
+               // First load the refs from the failed channel
+               List<ReferenceInfo> refs = new ArrayList<ReferenceInfo>();
+
+               ps = conn.prepareStatement(getSQLStatement("LOAD_REFS"));
+
+               ps.setLong(1, fromChannelID);
+
+               rs = ps.executeQuery();
+
+               int count = 0;
+
+               boolean arePaged = false;
+
+               long pageOrd = nextPagingOrder;
+
+               while (rs.next())
+               {
+                  long msgId = rs.getLong(1);
+                  int deliveryCount = rs.getInt(2);
+                  long sched = rs.getLong(3);
+
+                  if (count < numberToLoad)
+                  {
+                     ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount,
+                           sched);
+
+                     refs.add(ri);
+                  }
+
+                  // Set page ord
+
+                  if (ps2 == null)
+                  {
+                     ps2 = conn
+                           .prepareStatement(getSQLStatement("UPDATE_PAGE_ORDER"));
+                  }
+
+                  if (count < numberToLoad)
+                  {
+                     ps2.setNull(1, Types.BIGINT);
+
+                     if (trace)
+                     {
+                        log.trace("Set page ord to null");
+                     }
+                  }
+                  else
+                  {
+                     ps2.setLong(1, pageOrd);
+
+                     if (trace)
+                     {
+                        log.trace("Set page ord to " + pageOrd);
+                     }
+
+                     arePaged = true;
+
+                     pageOrd++;
+                  }
+
+                  ps2.setLong(2, msgId);
+
+                  ps2.setLong(3, fromChannelID);
+
+                  int rows = ps2.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Update page ord updated " + rows + " rows");
+                  }
+
+                  count++;
+               }
+
+               ps.close();
+
+               // Now swap the channel id
+
+               ps = conn.prepareStatement(getSQLStatement("UPDATE_CHANNEL_ID"));
+
+               ps.setLong(1, toChannelID);
+
+               ps.setLong(2, fromChannelID);
+
+               int rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace("Update channel id updated " + rows + " rows");
+               }
+
+               if (arePaged)
+               {
+                  return new InitialLoadInfo(new Long(firstPagingOrder),
+                        new Long(pageOrd - 1), refs);
+               }
+               else
+               {
+                  return new InitialLoadInfo(null, null, refs);
+               }
+            }
+            finally
+            {
+               closeResultSet(rs);
+               closeStatement(ps);
+               closeStatement(ps2);
+            }
+         }
       }
-      return (InitialLoadInfo)new MergeAndLoadRunner().executeWithRetry();      
+      return (InitialLoadInfo) new MergeAndLoadRunner().executeWithRetry();
    }
-   
+
    public void testSpeed() throws Exception
    {
-   	
+
    }
-   
+
    // End of paging functionality
    // ===========================
-   
-   public void addReference(final long channelID, final MessageReference ref, final Transaction tx) throws Exception
-   {         	
-   	class AddReferenceRunner extends JDBCTxRunner2
-   	{
-			public Object doTransaction() throws Exception
-			{
-	         PreparedStatement psReference = null;
+
+   public void addReference(final long channelID, final MessageReference ref,
+         final Transaction tx) throws Exception
+   {
+      if (trace) { log.trace("Adding reference " + ref + " in channel " + channelID + " tx " + tx); }
+      
+      class AddReferenceRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psReference = null;
             PreparedStatement psInsertMessage = null;
 
-	         Message m = ref.getMessage();     
-	         
-	         try
-	         {                          
-	            psReference = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
-	            
-	            // Add the reference
-	            addReference(channelID, ref, psReference, false);
-	            
-	            int rows = psReference.executeUpdate();  
-	            
-	            if (trace) { log.trace("Inserted " + rows + " rows"); }
-	              
-	            if (!m.isPersisted())
-	            {
-	               // First time so persist the message
-                  psInsertMessage = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE"));
+            Message m = ref.getMessage();
 
+            try
+            {
+               psReference = conn
+                     .prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
+
+               // Add the reference
+               addReference(channelID, ref, psReference, false);
+
+               int rows = psReference.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace("Inserted " + rows + " rows");
+               }
+
+               if (!m.isPersisted())
+               {
+                  // First time so persist the message
+                  psInsertMessage = conn
+                        .prepareStatement(getSQLStatement("INSERT_MESSAGE"));
+
                   storeMessage(m, psInsertMessage, true);
                   rows = psInsertMessage.executeUpdate();
-		            
-		            if (trace) { log.trace("Inserted/updated " + rows + " rows"); }     
-		            
-		            log.trace("message Inserted/updated " + rows + " rows");  
-		            
-		            //Needs to be at the end - in case an exception is thrown in which case retry will be attempted and we want to insert it again
-	               m.setPersisted(true);	                 
-	            }
-	            
-	            return null;
-	         }
-	         finally
-	         {
-	         	closeStatement(psReference);
+
+                  if (trace)
+                  {
+                     log.trace("Inserted/updated " + rows + " rows");
+                  }
+
+                  log.trace("message Inserted/updated " + rows + " rows");
+
+                  // Needs to be at the end - in case an exception is thrown in
+                  // which case retry will be attempted and we want to insert it
+                  // again
+                  m.setPersisted(true);
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psReference);
                closeStatement(psInsertMessage);
-	         }
-			}   		
-   	}
-   	   	
+            }
+         }
+      }
+
       if (tx != null)
       {
-         //In a tx so we just add the ref in the tx in memory for now
+         // In a tx so we just add the ref in the tx in memory for now
          TransactionCallback callback = getCallback(tx);
 
          callback.addReferenceToAdd(channelID, ref);
       }
       else
-      {         
-         //No tx so add the ref directly in the db
-         new AddReferenceRunner().executeWithRetry();         
+      {
+         // No tx so add the ref directly in the db
+         new AddReferenceRunner().executeWithRetry();
       }
    }
    
-   public void updateDeliveryCount(final long channelID, final MessageReference ref) throws Exception
+   public void moveReference(final long sourceChannelID, final long destChannelID, final MessageReference ref)
+      throws Exception
    {
-   	class UpdateDeliveryCountRunner extends JDBCTxRunner2
-   	{   		
-			public Object doTransaction() throws Exception
-			{   	
-		      PreparedStatement psReference = null;
-		       
-		      try
-		      {                                    
-		         psReference = conn.prepareStatement(getSQLStatement("UPDATE_DELIVERY_COUNT"));
-		         
-		         psReference.setInt(1, ref.getDeliveryCount());
-		         
-		         psReference.setLong(2, channelID);
-		         
-		         psReference.setLong(3, ref.getMessage().getMessageID());
-		         
-		         int rows = psReference.executeUpdate();
-		
-		         if (trace) { log.trace("Updated " + rows + " rows"); }
-		         
-		         return null;
-		      }
-		      finally
-		      {
-		      	closeStatement(psReference);                        
-		      }  
-			}
-   	}
-   	
-   	new UpdateDeliveryCountRunner().executeWithRetry();
+      if (trace) { log.trace("Moving reference " + ref + " from " + sourceChannelID + " to " + destChannelID); }
+      
+      class MoveReferenceRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psReference = null;
+            
+            try
+            {
+               psReference = conn.prepareStatement(getSQLStatement("MOVE_REFERENCE"));
+               
+               psReference.setLong(1, destChannelID);
+               psReference.setLong(2, sourceChannelID);
+               psReference.setLong(3, ref.getMessage().getMessageID());
+
+               int rows = psReference.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace("Updated " + rows + " rows");
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psReference);
+            }
+         }
+      }
+
+      new MoveReferenceRunner().executeWithRetry();      
    }
-   
-   public void removeReference(final long channelID, final MessageReference ref, final Transaction tx) throws Exception
-   {      
-   	class RemoveReferenceRunner extends JDBCTxRunner2
-   	{
-			public Object doTransaction() throws Exception
-			{  
-				PreparedStatement psReference = null;
-				     
-	         try
-	         {
-	            psReference = conn.prepareStatement(getSQLStatement("DELETE_MESSAGE_REF"));	           
-	            
-	            //Remove the message reference
-	            removeReference(channelID, ref, psReference);
-	             
-	            int rows = psReference.executeUpdate();
-	            
-	            if (rows != 1)
-	            {
-	               log.warn("Failed to remove row for: " + ref);
-	               return null;
-	            }
-	            
-	            if (trace) { log.trace("Deleted " + rows + " references"); }
-	                  	            
-	            return null;
-	         }
-	         finally
-	         {
-	         	closeStatement(psReference);
-	         }  
-			}
-   	}
-           
+
+   public void updateDeliveryCount(final long channelID,
+         final MessageReference ref) throws Exception
+   {
+      class UpdateDeliveryCountRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psReference = null;
+
+            try
+            {
+               psReference = conn
+                     .prepareStatement(getSQLStatement("UPDATE_DELIVERY_COUNT"));
+
+               psReference.setInt(1, ref.getDeliveryCount());
+
+               psReference.setLong(2, channelID);
+
+               psReference.setLong(3, ref.getMessage().getMessageID());
+
+               int rows = psReference.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace("Updated " + rows + " rows");
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psReference);
+            }
+         }
+      }
+
+      new UpdateDeliveryCountRunner().executeWithRetry();
+   }
+
+   public void removeReference(final long channelID,
+         final MessageReference ref, final Transaction tx) throws Exception
+   {
+      if (trace) { log.trace("Removing reference " + ref + " in channel " + channelID + " tx " + tx); }
+      
+      class RemoveReferenceRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement psReference = null;
+
+            try
+            {
+               psReference = conn
+                     .prepareStatement(getSQLStatement("DELETE_MESSAGE_REF"));
+
+               // Remove the message reference
+               removeReference(channelID, ref, psReference);
+
+               int rows = psReference.executeUpdate();
+
+               if (rows != 1)
+               {
+                  log.warn("Failed to remove row for: " + ref);
+                  return null;
+               }
+
+               if (trace)
+               {
+                  log.trace("Deleted " + rows + " references");
+               }
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(psReference);
+            }
+         }
+      }
+
       if (tx != null)
       {
-         //In a tx so we just add the ref in the tx in memory for now
+         // In a tx so we just add the ref in the tx in memory for now
 
          TransactionCallback callback = getCallback(tx);
 
          callback.addReferenceToRemove(channelID, ref);
       }
       else
-      {         
-         //No tx so we remove the reference directly from the db
+      {
+         // No tx so we remove the reference directly from the db
 
          new RemoveReferenceRunner().executeWithRetry();
 
          deleteMessage(ref.getMessage().getMessageID());
       }
    }
-   
-   
+
    public boolean referenceExists(long messageID) throws Exception
    {
       Connection conn = null;
@@ -1269,7 +1501,8 @@
       {
          conn = ds.getConnection();
 
-         st = conn.prepareStatement(getSQLStatement("SELECT_EXISTS_REF_MESSAGE_ID"));
+         st = conn
+               .prepareStatement(getSQLStatement("SELECT_EXISTS_REF_MESSAGE_ID"));
          st.setLong(1, messageID);
 
          rs = st.executeQuery();
@@ -1290,24 +1523,24 @@
       }
       finally
       {
-      	closeResultSet(rs);
-      	closeStatement(st);
-      	closeConnection(conn);
+         closeResultSet(rs);
+         closeStatement(st);
+         closeConnection(conn);
          wrap.end();
       }
    }
 
    // Public --------------------------------------------------------
-   
+
    public String toString()
    {
       return "JDBCPersistenceManager[" + Integer.toHexString(hashCode()) + "]";
-   }   
-   
+   }
+
    // Package protected ---------------------------------------------
-   
+
    // Protected -----------------------------------------------------
-      
+
    protected TransactionCallback getCallback(Transaction tx)
    {
       TransactionCallback callback = (TransactionCallback) tx.getCallback(this);
@@ -1321,332 +1554,391 @@
 
       return callback;
    }
-   
-   protected void handleBeforeCommit1PC(final List refsToAdd, final List refsToRemove, final Transaction tx)
-      throws Exception
+
+   protected void handleBeforeCommit1PC(final List refsToAdd,
+         final List refsToRemove, final Transaction tx) throws Exception
    {
-   	class HandleBeforeCommit1PCRunner extends JDBCTxRunner2
-   	{
-			public Object doTransaction() throws Exception
-			{
-				// For one phase we simply add rows corresponding to the refs and remove rows corresponding to
-		      // the deliveries in one jdbc tx. We also need to store messages as necessary,
-		      // depending on whether they've already been stored or still referenced by other channels.
-		         
-		      PreparedStatement psReference = null;
-		      PreparedStatement psInsertMessage = null;
+      class HandleBeforeCommit1PCRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            // For one phase we simply add rows corresponding to the refs and
+            // remove rows corresponding to
+            // the deliveries in one jdbc tx. We also need to store messages as
+            // necessary,
+            // depending on whether they've already been stored or still
+            // referenced by other channels.
+
+            PreparedStatement psReference = null;
+            PreparedStatement psInsertMessage = null;
             PreparedStatement psDeleteReference = null;
-      
-		      List<Message> messagesStored = new ArrayList<Message>();
 
-		      try
-		      {
-		         // First the adds
+            List<Message> messagesStored = new ArrayList<Message>();
 
-		         for (Iterator i = refsToAdd.iterator(); i.hasNext(); )
-		         {
-		            ChannelRefPair pair = (ChannelRefPair)i.next();
-		            MessageReference ref = pair.ref;
-		                                                
-		            psReference = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
-		            
-		            // Now store the reference
-		            addReference(pair.channelID, ref, psReference, false);
-		              
-		            int rows = psReference.executeUpdate();
-		               
-		            if (trace) { log.trace("Inserted " + rows + " rows"); }                              
-     
-		            Message m = ref.getMessage();    
-		            
-		            synchronized (m)
-		            {            
-			            if (!m.isPersisted())
-			            {   
-			            	if (psInsertMessage == null)
-			            	{
-                           psInsertMessage = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE"));
-			            	}
-			            	
-			               // First time so add message
-                        // And in case of clustered queues/topics, the message could possibly be already persisted on the different node
+            try
+            {
+               // First the adds
+
+               for (Iterator i = refsToAdd.iterator(); i.hasNext();)
+               {
+                  ChannelRefPair pair = (ChannelRefPair) i.next();
+                  MessageReference ref = pair.ref;
+
+                  psReference = conn
+                        .prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
+
+                  // Now store the reference
+                  addReference(pair.channelID, ref, psReference, false);
+
+                  int rows = psReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Inserted " + rows + " rows");
+                  }
+
+                  Message m = ref.getMessage();
+
+                  synchronized (m)
+                  {
+                     if (!m.isPersisted())
+                     {
+                        if (psInsertMessage == null)
+                        {
+                           psInsertMessage = conn
+                                 .prepareStatement(getSQLStatement("INSERT_MESSAGE"));
+                        }
+
+                        // First time so add message
+                        // And in case of clustered queues/topics, the message
+                        // could possibly be already persisted on the different
+                        // node
                         // so we persist also using the Conditional Update
-                        if (trace) { log.trace("Message does not already exist so inserting it"); }
+                        if (trace)
+                        {
+                           log
+                                 .trace("Message does not already exist so inserting it");
+                        }
                         storeMessage(m, psInsertMessage, true);
                         rows = psInsertMessage.executeUpdate();
-                        if (trace) { log.trace("Inserted " + rows + " rows"); }
+                        if (trace)
+                        {
+                           log.trace("Inserted " + rows + " rows");
+                        }
 
-			               m.setPersisted(true);
-			               
-			               messagesStored.add(m);
-			            }
-		            }
-		         }         
-		         
-		         // Now the removes
+                        m.setPersisted(true);
 
-		         for (Iterator i = refsToRemove.iterator(); i.hasNext(); )
-		         {
-		            ChannelRefPair pair = (ChannelRefPair)i.next();
-		            
-		            if (psDeleteReference == null)
-		            {
-		            	psDeleteReference = conn.prepareStatement(getSQLStatement("DELETE_MESSAGE_REF"));
-		            }
+                        messagesStored.add(m);
+                     }
+                  }
+               }
 
-		            removeReference(pair.channelID, pair.ref, psDeleteReference);
-		                        
-		            int rows = psDeleteReference.executeUpdate();
-		            
-		            if (trace) { log.trace("Deleted " + rows + " references"); }
-		            
-		         }
-		         
-		         return null;
-		      }
-		      catch (Exception e)
-		      {
-		      	for (Iterator i = messagesStored.iterator(); i.hasNext(); )
-		         {
-		      		Message msg = (Message)i.next();
-		      		
-		      		msg.setPersisted(false);
-		         }
-		      	throw e;
-		      }
-		      finally
-		      {
+               // Now the removes
+
+               for (Iterator i = refsToRemove.iterator(); i.hasNext();)
+               {
+                  ChannelRefPair pair = (ChannelRefPair) i.next();
+
+                  if (psDeleteReference == null)
+                  {
+                     psDeleteReference = conn
+                           .prepareStatement(getSQLStatement("DELETE_MESSAGE_REF"));
+                  }
+
+                  removeReference(pair.channelID, pair.ref, psDeleteReference);
+
+                  int rows = psDeleteReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Deleted " + rows + " references");
+                  }
+
+               }
+
+               return null;
+            }
+            catch (Exception e)
+            {
+               for (Iterator i = messagesStored.iterator(); i.hasNext();)
+               {
+                  Message msg = (Message) i.next();
+
+                  msg.setPersisted(false);
+               }
+               throw e;
+            }
+            finally
+            {
                closeStatement(psReference);
-		      	closeStatement(psDeleteReference);
-		      	closeStatement(psInsertMessage);
-		      }
-			}   		
-   	}   	      
-      
+               closeStatement(psDeleteReference);
+               closeStatement(psInsertMessage);
+            }
+         }
+      }
+
       new HandleBeforeCommit1PCRunner().executeWithRetry();
-      
+
       this.deleteMessages(refsToRemove);
    }
-   
-   protected void handleBeforeCommit2PC(final List refsToRemove, final Transaction tx) throws Exception
-   {          
-   	class HandleBeforeCommit2PCRunner extends JDBCTxRunner2
-   	{
-   		public Object doTransaction() throws Exception
-			{				   	
-		   	PreparedStatement ps = null;
-		      
-		      if (trace) { log.trace(this + " commitPreparedTransaction, tx= " + tx); }
-		        
-		      try
-		      {
-		         ps = conn.prepareStatement(getSQLStatement("COMMIT_MESSAGE_REF1"));
-		         
-		         ps.setLong(1, tx.getId());        
-		         
-		         int rows = ps.executeUpdate();
-		         
-		         if (trace) { log.trace(JDBCUtil.statementToString(getSQLStatement("COMMIT_MESSAGE_REF1"), new Long(tx.getId())) + " removed " + rows + " row(s)");  }
-		         
-		         ps.close();
-		         ps = null;
-		         		         
-		         ps = conn.prepareStatement(getSQLStatement("COMMIT_MESSAGE_REF2"));
-		         ps.setLong(1, tx.getId());         
-		         
-		         rows = ps.executeUpdate();
-		         
-		         if (trace) { log.trace(JDBCUtil.statementToString(getSQLStatement("COMMIT_MESSAGE_REF2"), new Long(tx.getId())) + " updated " + rows + " row(s)"); }
-		         
-		         removeTXRecord(conn, tx);
-		         
-		         return null;
-		      }
-		      finally
-		      {
-		      	closeStatement(ps);
-		      }
-			}
-   	}
-   	
+
+   protected void handleBeforeCommit2PC(final List refsToRemove,
+         final Transaction tx) throws Exception
+   {
+      class HandleBeforeCommit2PCRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement ps = null;
+
+            if (trace)
+            {
+               log.trace(this + " commitPreparedTransaction, tx= " + tx);
+            }
+
+            try
+            {
+               ps = conn
+                     .prepareStatement(getSQLStatement("COMMIT_MESSAGE_REF1"));
+
+               ps.setLong(1, tx.getId());
+
+               int rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace(JDBCUtil.statementToString(
+                        getSQLStatement("COMMIT_MESSAGE_REF1"), new Long(tx
+                              .getId()))
+                        + " removed " + rows + " row(s)");
+               }
+
+               ps.close();
+
+               ps = conn
+                     .prepareStatement(getSQLStatement("COMMIT_MESSAGE_REF2"));
+               ps.setLong(1, tx.getId());
+
+               rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace(JDBCUtil.statementToString(
+                        getSQLStatement("COMMIT_MESSAGE_REF2"), new Long(tx
+                              .getId()))
+                        + " updated " + rows + " row(s)");
+               }
+
+               removeTXRecord(conn, tx);
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(ps);
+            }
+         }
+      }
+
       new HandleBeforeCommit2PCRunner().executeWithRetry();
-      
-      this.deleteMessages(refsToRemove);        	
+
+      this.deleteMessages(refsToRemove);
    }
-   
-   protected void handleBeforePrepare(final List refsToAdd, final List refsToRemove, final Transaction tx) throws Exception
+
+   protected void handleBeforePrepare(final List refsToAdd,
+         final List refsToRemove, final Transaction tx) throws Exception
    {
-   	class HandleBeforePrepareRunner extends JDBCTxRunner2
-   	{
-			public Object doTransaction() throws Exception
-			{
-				//We insert a tx record and
-		      //a row for each ref with +
-		      //and update the row for each delivery with "-"
-		      
-		      PreparedStatement psReference = null;
-		      PreparedStatement psInsertMessage = null;
+      class HandleBeforePrepareRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            // We insert a tx record and
+            // a row for each ref with +
+            // and update the row for each delivery with "-"
+
+            PreparedStatement psReference = null;
+            PreparedStatement psInsertMessage = null;
             PreparedStatement psUpdateReference = null;
 
-		      List<Message> messagesStored = new ArrayList<Message>();
-		 
-		      try
-		      { 
-		         //Insert the tx record
-		         if (!refsToAdd.isEmpty() || !refsToRemove.isEmpty())
-		         {
-		            addTXRecord(conn, tx);
-		         }
-		         
-		         Iterator iter = refsToAdd.iterator();
+            List<Message> messagesStored = new ArrayList<Message>();
 
-		         while (iter.hasNext())
-		         {
-		            ChannelRefPair pair = (ChannelRefPair) iter.next();
-		            
-		            if (psReference == null)
-		            {
-		            	psReference = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
-		            }
-		            
-		            prepareToAddReference(pair.channelID, pair.ref, tx, psReference);
-		            
-		            int rows = psReference.executeUpdate();
-		               
-		            if (trace) { log.trace("Inserted " + rows + " rows"); }
-           
-		            Message m = pair.ref.getMessage(); 
-		            
-		            synchronized (m)
-		            {            
-			            if (!m.isPersisted())
-			            {	            	
-			            	if (psInsertMessage == null)
-			            	{
-                           psInsertMessage = conn.prepareStatement(getSQLStatement("INSERT_MESSAGE"));
-			            	}
+            try
+            {
+               // Insert the tx record
+               if (!refsToAdd.isEmpty() || !refsToRemove.isEmpty())
+               {
+                  addTXRecord(conn, tx);
+               }
 
+               Iterator iter = refsToAdd.iterator();
+
+               while (iter.hasNext())
+               {
+                  ChannelRefPair pair = (ChannelRefPair) iter.next();
+
+                  if (psReference == null)
+                  {
+                     psReference = conn
+                           .prepareStatement(getSQLStatement("INSERT_MESSAGE_REF"));
+                  }
+
+                  prepareToAddReference(pair.channelID, pair.ref, tx,
+                        psReference);
+
+                  int rows = psReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("Inserted " + rows + " rows");
+                  }
+
+                  Message m = pair.ref.getMessage();
+
+                  synchronized (m)
+                  {
+                     if (!m.isPersisted())
+                     {
+                        if (psInsertMessage == null)
+                        {
+                           psInsertMessage = conn
+                                 .prepareStatement(getSQLStatement("INSERT_MESSAGE"));
+                        }
+
                         storeMessage(m, psInsertMessage, true);
                         rows = psInsertMessage.executeUpdate();
-				            
-			            	if (trace) { log.trace("Inserted " + rows + " rows"); }
 
-				            m.setPersisted(true);				   			
-				            
-				            messagesStored.add(m);
-			            }
-		            }
-		         }         
-		                  
-		         //Now the removes
-		         
-		         iter = refsToRemove.iterator();
-		         
-		         while (iter.hasNext())
-		         {
-		         	if (psUpdateReference == null)
-		         	{
-				         psUpdateReference = conn.prepareStatement(getSQLStatement("UPDATE_MESSAGE_REF"));         
-		         	}
-		         	
-		            ChannelRefPair pair = (ChannelRefPair) iter.next();
-		            
-		            prepareToRemoveReference(pair.channelID, pair.ref, tx, psUpdateReference);
-		            
-		            int rows = psUpdateReference.executeUpdate();
-		               
-		            if (trace) { log.trace("updated " + rows + " rows"); }          
-		         }         
-		         
-		         return null;
-		      }
-		      catch (Exception e)
-		      {
-		      	for (Iterator i = messagesStored.iterator(); i.hasNext(); )
-		         {
-		      		Message msg = (Message)i.next();
-		      		
-		      		msg.setPersisted(false);
-		         }
-		      	throw e;
-		      }
-		      finally
-		      {
-		      	closeStatement(psReference);
-		      	closeStatement(psInsertMessage);  
-		      	closeStatement(psUpdateReference);
-		      }
-			}   		
-   	}
-   	
-   	new HandleBeforePrepareRunner().executeWithRetry();
+                        if (trace)
+                        {
+                           log.trace("Inserted " + rows + " rows");
+                        }
+
+                        m.setPersisted(true);
+
+                        messagesStored.add(m);
+                     }
+                  }
+               }
+
+               // Now the removes
+
+               iter = refsToRemove.iterator();
+
+               while (iter.hasNext())
+               {
+                  if (psUpdateReference == null)
+                  {
+                     psUpdateReference = conn
+                           .prepareStatement(getSQLStatement("UPDATE_MESSAGE_REF"));
+                  }
+
+                  ChannelRefPair pair = (ChannelRefPair) iter.next();
+
+                  prepareToRemoveReference(pair.channelID, pair.ref, tx,
+                        psUpdateReference);
+
+                  int rows = psUpdateReference.executeUpdate();
+
+                  if (trace)
+                  {
+                     log.trace("updated " + rows + " rows");
+                  }
+               }
+
+               return null;
+            }
+            catch (Exception e)
+            {
+               for (Iterator i = messagesStored.iterator(); i.hasNext();)
+               {
+                  Message msg = (Message) i.next();
+
+                  msg.setPersisted(false);
+               }
+               throw e;
+            }
+            finally
+            {
+               closeStatement(psReference);
+               closeStatement(psInsertMessage);
+               closeStatement(psUpdateReference);
+            }
+         }
+      }
+
+      new HandleBeforePrepareRunner().executeWithRetry();
    }
-   
-   protected void handleBeforeRollback(final List refsToAdd, final Transaction tx) throws Exception
+
+   protected void handleBeforeRollback(final List refsToAdd,
+         final Transaction tx) throws Exception
    {
-   	class HandleBeforeRollbackRunner extends JDBCTxRunner2
-   	{
-			public Object doTransaction() throws Exception
-			{
-				PreparedStatement ps = null;
-		      
-		      try
-		      {
-		         ps = conn.prepareStatement(getSQLStatement("ROLLBACK_MESSAGE_REF1"));
-		         
-		         ps.setLong(1, tx.getId());         
-		         
-		         int rows = ps.executeUpdate();
-		         
-		         if (trace)
-		         {
-		            log.trace(JDBCUtil.statementToString(getSQLStatement("ROLLBACK_MESSAGE_REF1"), new Long(tx.getId())) + " removed " + rows + " row(s)");
-		         }
-		         
-		         ps.close();
-		         ps = null;
-		         
-		         ps = conn.prepareStatement(getSQLStatement("ROLLBACK_MESSAGE_REF2"));
-		         ps.setLong(1, tx.getId());
-		         
-		         rows = ps.executeUpdate();
-		         
-		         if (trace)
-		         {
-		            log.trace(JDBCUtil.statementToString(getSQLStatement("ROLLBACK_MESSAGE_REF2"), new Long(tx.getId())) + " updated " + rows
-		                  + " row(s)");
-		         }
-		         
-		         removeTXRecord(conn, tx);
-		         
-		         return null;
-		      }
-		      finally
-		      {
-		      	closeStatement(ps);
-		      }
-			}   	
-   	}
-   	
+      class HandleBeforeRollbackRunner extends JDBCTxRunner2
+      {
+         public Object doTransaction() throws Exception
+         {
+            PreparedStatement ps = null;
+
+            try
+            {
+               ps = conn
+                     .prepareStatement(getSQLStatement("ROLLBACK_MESSAGE_REF1"));
+
+               ps.setLong(1, tx.getId());
+
+               int rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace(JDBCUtil.statementToString(
+                        getSQLStatement("ROLLBACK_MESSAGE_REF1"), new Long(tx
+                              .getId()))
+                        + " removed " + rows + " row(s)");
+               }
+
+               ps.close();
+ 
+               ps = conn
+                     .prepareStatement(getSQLStatement("ROLLBACK_MESSAGE_REF2"));
+               ps.setLong(1, tx.getId());
+
+               rows = ps.executeUpdate();
+
+               if (trace)
+               {
+                  log.trace(JDBCUtil.statementToString(
+                        getSQLStatement("ROLLBACK_MESSAGE_REF2"), new Long(tx
+                              .getId()))
+                        + " updated " + rows + " row(s)");
+               }
+
+               removeTXRecord(conn, tx);
+
+               return null;
+            }
+            finally
+            {
+               closeStatement(ps);
+            }
+         }
+      }
+
       new HandleBeforeRollbackRunner().executeWithRetry();
-      
-      this.deleteMessages(refsToAdd);      	     
+
+      this.deleteMessages(refsToAdd);
    }
-   
-   
+
    protected void addTXRecord(Connection conn, Transaction tx) throws Exception
    {
       if (trace)
       {
          log.trace("Inserting tx record for " + tx);
       }
-      
+
       if (!this.nodeIDSet)
       {
-      	//Sanity
-      	throw new IllegalStateException("Node id has not been set");
+         // Sanity
+         throw new IllegalStateException("Node id has not been set");
       }
-      
+
       PreparedStatement ps = null;
       String statement = "UNDEFINED";
       int rows = -1;
@@ -1654,72 +1946,83 @@
       try
       {
          statement = getSQLStatement("INSERT_TRANSACTION");
-         
+
          ps = conn.prepareStatement(statement);
-         
+
          ps.setInt(1, nodeID);
-         
+
          ps.setLong(2, tx.getId());
-         
+
          Xid xid = tx.getXid();
-         
+
          formatID = xid.getFormatId();
-         
+
          setVarBinaryColumn(3, ps, xid.getBranchQualifier());
-         
+
          ps.setInt(4, formatID);
-         
+
          setVarBinaryColumn(5, ps, xid.getGlobalTransactionId());
-         
-         rows = ps.executeUpdate();         
+
+         rows = ps.executeUpdate();
       }
       finally
       {
          if (trace)
          {
-            String s = JDBCUtil.statementToString(statement, new Integer(nodeID), new Long(tx.getId()), "<byte-array>",
+            String s = JDBCUtil.statementToString(statement,
+                  new Integer(nodeID), new Long(tx.getId()), "<byte-array>",
                   new Integer(formatID), "<byte-array>");
-            log.trace(s + (rows == -1 ? " failed!" : " inserted " + rows + " row(s)"));
+            log
+                  .trace(s
+                        + (rows == -1 ? " failed!" : " inserted " + rows
+                              + " row(s)"));
          }
-         closeStatement(ps);      
+         closeStatement(ps);
       }
    }
-   
-   protected void removeTXRecord(Connection conn, Transaction tx) throws Exception
+
+   protected void removeTXRecord(Connection conn, Transaction tx)
+         throws Exception
    {
       if (!this.nodeIDSet)
       {
-      	//Sanity
-      	throw new IllegalStateException("Node id has not been set");
+         // Sanity
+         throw new IllegalStateException("Node id has not been set");
       }
-   	
+
       PreparedStatement ps = null;
       try
       {
          ps = conn.prepareStatement(getSQLStatement("DELETE_TRANSACTION"));
-         
+
          ps.setInt(1, nodeID);
-         
+
          ps.setLong(2, tx.getId());
-         
+
          int rows = ps.executeUpdate();
-         
+
          if (trace)
          {
-            log.trace(JDBCUtil.statementToString(getSQLStatement("DELETE_TRANSACTION"), new Integer(nodeID), new Long(tx.getId())) + " removed " + rows + " row(s)");
+            log.trace(JDBCUtil.statementToString(
+                  getSQLStatement("DELETE_TRANSACTION"), new Integer(nodeID),
+                  new Long(tx.getId()))
+                  + " removed " + rows + " row(s)");
          }
       }
       finally
       {
-      	closeStatement(ps);    
+         closeStatement(ps);
       }
-   }  
-   
+   }
+
    protected void addReference(long channelID, MessageReference ref,
-                               PreparedStatement ps, boolean paged) throws Exception
+         PreparedStatement ps, boolean paged) throws Exception
    {
-      if (trace) { log.trace("adding " + ref + " to channel " + channelID); }
-      
+      if (trace)
+      {
+         log.trace("adding " + ref + " to channel " + channelID);
+      }
+
       ps.setLong(1, channelID);
       ps.setLong(2, ref.getMessage().getMessageID());
       ps.setNull(3, Types.BIGINT);
@@ -1736,88 +2039,98 @@
       ps.setInt(7, ref.getDeliveryCount());
       ps.setLong(8, ref.getScheduledDeliveryTime());
    }
-   
-   protected void removeReference(long channelID, MessageReference ref, PreparedStatement ps)
-      throws Exception
+
+   protected void removeReference(long channelID, MessageReference ref,
+         PreparedStatement ps) throws Exception
    {
-      if (trace) { log.trace("removing " + ref + " from channel " + channelID); }
-      
+      if (trace)
+      {
+         log.trace("removing " + ref + " from channel " + channelID);
+      }
+
       ps.setLong(1, ref.getMessage().getMessageID());
-      ps.setLong(2, channelID);      
+      ps.setLong(2, channelID);
    }
-   
-   protected void prepareToAddReference(long channelID, MessageReference ref, Transaction tx, PreparedStatement ps)
-     throws Exception
+
+   protected void prepareToAddReference(long channelID, MessageReference ref,
+         Transaction tx, PreparedStatement ps) throws Exception
    {
-      if (trace) { log.trace("adding " + ref + " to channel " + channelID + (tx == null ? " non-transactionally" : " on transaction: " + tx)); }
-      
+      if (trace)
+      {
+         log.trace("adding "
+               + ref
+               + " to channel "
+               + channelID
+               + (tx == null ? " non-transactionally" : " on transaction: "
+                     + tx));
+      }
+
       ps.setLong(1, channelID);
       ps.setLong(2, ref.getMessage().getMessageID());
       ps.setLong(3, tx.getId());
       ps.setString(4, "+");
       ps.setLong(5, getOrdering());
-      ps.setNull(6, Types.BIGINT);      
+      ps.setNull(6, Types.BIGINT);
       ps.setInt(7, ref.getDeliveryCount());
       ps.setLong(8, ref.getScheduledDeliveryTime());
    }
-   
-   protected void prepareToRemoveReference(long channelID, MessageReference ref, Transaction tx, PreparedStatement ps)
-      throws Exception
+
+   protected void prepareToRemoveReference(long channelID,
+         MessageReference ref, Transaction tx, PreparedStatement ps)
+         throws Exception
    {
       if (trace)
       {
-         log.trace("removing " + ref + " from channel " + channelID
-               + (tx == null ? " non-transactionally" : " on transaction: " + tx));
+         log.trace("removing "
+               + ref
+               + " from channel "
+               + channelID
+               + (tx == null ? " non-transactionally" : " on transaction: "
+                     + tx));
       }
-      
-      ps.setLong(1, tx.getId()); 
+
+      ps.setLong(1, tx.getId());
       ps.setLong(2, ref.getMessage().getMessageID());
-      ps.setLong(3, channelID);           
+      ps.setLong(3, channelID);
    }
-   
+
    protected byte[] mapToBytes(Map map) throws Exception
    {
-      if (map == null || map.isEmpty())
-      {
-         return null;
-      }
-      
+      if (map == null || map.isEmpty()) { return null; }
+
       final int BUFFER_SIZE = 1024;
-       
+
       ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_SIZE);
-      
+
       DataOutputStream oos = new DataOutputStream(bos);
-      
+
       StreamUtils.writeMap(oos, map, true);
-      
+
       oos.close();
-      
+
       return bos.toByteArray();
    }
-   
+
    protected HashMap bytesToMap(byte[] bytes) throws Exception
    {
-      if (bytes == null)
-      {
-         return new HashMap();
-      }
-       
+      if (bytes == null) { return new HashMap(); }
+
       ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
-      
+
       DataInputStream dais = new DataInputStream(bis);
-      
+
       HashMap map = StreamUtils.readMap(dais, true);
-      
+
       dais.close();
-            
+
       return map;
    }
-   
+
    /**
     * Stores the message in the MESSAGE table.
     */
    protected void storeMessage(Message m, PreparedStatement ps, boolean bindBlobs) throws Exception
-   {      
+   {
       // physically insert the row in the database
       // first set the fields from org.jboss.messaging.core.Routable
       ps.setLong(1, m.getMessageID());
@@ -1825,26 +2138,23 @@
       ps.setLong(3, m.getExpiration());
       ps.setLong(4, m.getTimestamp());
       ps.setByte(5, m.getPriority());
-      ps.setByte(6, m.getType());
-      ps.setLong(7, System.currentTimeMillis());
+      ps.setByte(6, m.getType());     
 
       if (bindBlobs)
       {
-         bindBlobs(m, ps, 8, 9);
-      }            
+         bindBlobs(m, ps, 7, 8);
+      }
    }
 
-
-   /** Stores the message using the Conditional update */
    protected int storeMessage(Message message, PreparedStatement psInsertMessage, PreparedStatement psUpdateMessage)
-      throws Exception
+                              throws Exception
    {
       int rows;
       if (!supportsBlobSelect)
       {
-      	//Need to store in two phases
+         // Need to store in two phases
          storeMessage(message, psInsertMessage, false);
-         psInsertMessage.setLong(8, message.getMessageID());
+         psInsertMessage.setLong(7, message.getMessageID());
          rows = psInsertMessage.executeUpdate();
 
          if (rows == 1)
@@ -1852,28 +2162,25 @@
             bindBlobs(message, psUpdateMessage, 1, 2);
             psUpdateMessage.setLong(3, message.getMessageID());
             rows = psUpdateMessage.executeUpdate();
-            if (rows != 1)
-            {
-               throw new IllegalStateException("Couldn't update messageId=" +
-                                               message.getMessageID() + " on paging");
-            }
+            if (rows != 1) { throw new IllegalStateException(
+                  "Couldn't update messageId=" + message.getMessageID()
+                        + " on paging"); }
          }
       }
       else
       {
-      	//Can store in one go
+         // Can store in one go
          storeMessage(message, psInsertMessage, true);
-         psInsertMessage.setLong(10, message.getMessageID());
+         psInsertMessage.setLong(9, message.getMessageID());
          rows = psInsertMessage.executeUpdate();
       }
       return rows;
    }
 
-
-   private void bindBlobs(Message m, PreparedStatement ps, int headerPosition, int payloadPosition)
-      throws Exception
+   private void bindBlobs(Message m, PreparedStatement ps, int headerPosition,
+         int payloadPosition) throws Exception
    {
-      //headers
+      // headers
       byte[] bytes = mapToBytes(((MessageSupport) m).getHeaders());
       if (bytes != null)
       {
@@ -1884,7 +2191,6 @@
          ps.setNull(headerPosition, Types.LONGVARBINARY);
       }
 
-
       byte[] payload = m.getPayloadAsByteArray();
       if (payload != null)
       {
@@ -1896,63 +2202,71 @@
       }
    }
 
-   protected void setVarBinaryColumn(int column, PreparedStatement ps, byte[] bytes) throws Exception
+   protected void setVarBinaryColumn(int column, PreparedStatement ps,
+         byte[] bytes) throws Exception
    {
       if (usingTrailingByte)
       {
-         // Sybase has the stupid characteristic of truncating all trailing in zeros
+         // Sybase has the stupid characteristic of truncating all trailing in
+         // zeros
          // in varbinary columns
          // So we add an extra byte on the end when we store the varbinary data
          // otherwise we might lose data
          // http://jira.jboss.org/jira/browse/JBMESSAGING-825
-         
+
          byte[] res = new byte[bytes.length + 1];
-         
+
          System.arraycopy(bytes, 0, res, 0, bytes.length);
-         
+
          res[bytes.length] = 127;
 
          bytes = res;
       }
-      
-      ps.setBytes(column, bytes);            
-      
-      if (trace) { log.trace("Setting varbinary column of length: " + bytes.length); }
+
+      ps.setBytes(column, bytes);
+
+      if (trace)
+      {
+         log.trace("Setting varbinary column of length: " + bytes.length);
+      }
    }
-   
-   protected byte[] getVarBinaryColumn(ResultSet rs, int columnIndex) throws Exception
+
+   protected byte[] getVarBinaryColumn(ResultSet rs, int columnIndex)
+         throws Exception
    {
       byte[] bytes = rs.getBytes(columnIndex);
-      
+
       if (usingTrailingByte)
       {
          // Get rid of the trailing byte
-         
+
          // http://jira.jboss.org/jira/browse/JBMESSAGING-825
-         
+
          byte[] newBytes = new byte[bytes.length - 1];
-         
+
          System.arraycopy(bytes, 0, newBytes, 0, bytes.length - 1);
-         
+
          bytes = newBytes;
       }
-      
+
       return bytes;
    }
-     
+
    // Used for storing message headers and bodies
-   protected void setBytes(PreparedStatement ps, int columnIndex, byte[] bytes) throws Exception
+   protected void setBytes(PreparedStatement ps, int columnIndex, byte[] bytes)
+         throws Exception
    {
       if (usingBinaryStream)
       {
-         //Set the bytes using a binary stream - likely to be better for large byte[]
-         
+         // Set the bytes using a binary stream - likely to be better for large
+         // byte[]
+
          InputStream is = null;
-         
+
          try
          {
             is = new ByteArrayInputStream(bytes);
-            
+
             ps.setBinaryStream(columnIndex, is, bytes.length);
          }
          finally
@@ -1965,42 +2279,42 @@
       }
       else
       {
-         //Set the bytes using setBytes() - likely to be better for smaller byte[]
-         
+         // Set the bytes using setBytes() - likely to be better for smaller
+         // byte[]
+
          setVarBinaryColumn(columnIndex, ps, bytes);
       }
    }
-   
+
    protected byte[] getBytes(ResultSet rs, int columnIndex) throws Exception
    {
       if (usingBinaryStream)
       {
-         //Get the bytes using a binary stream - likely to be better for large byte[]
-         
+         // Get the bytes using a binary stream - likely to be better for large
+         // byte[]
+
          InputStream is = null;
          ByteArrayOutputStream os = null;
-         
+
          final int BUFFER_SIZE = 4096;
-         
+
          try
          {
             InputStream i = rs.getBinaryStream(columnIndex);
-            
-            if (i == null)
-            {
-               return null;
-            }
-            
-            is = new BufferedInputStream(rs.getBinaryStream(columnIndex), BUFFER_SIZE);
-            
+
+            if (i == null) { return null; }
+
+            is = new BufferedInputStream(rs.getBinaryStream(columnIndex),
+                  BUFFER_SIZE);
+
             os = new ByteArrayOutputStream(BUFFER_SIZE);
-            
+
             int b;
             while ((b = is.read()) != -1)
             {
                os.write(b);
             }
-            
+
             return os.toByteArray();
          }
          finally
@@ -2017,11 +2331,11 @@
       }
       else
       {
-         //Get the bytes using getBytes() - better for smaller byte[]
+         // Get the bytes using getBytes() - better for smaller byte[]
          return getVarBinaryColumn(rs, columnIndex);
       }
    }
-   
+
    protected void logBatchUpdate(String name, int[] rows, String action)
    {
       int count = 0;
@@ -2029,133 +2343,159 @@
       {
          count += rows[i];
       }
-      log.trace("Batch update " + name + ", " + action + " total of " + count + " rows");
+      log.trace("Batch update " + name + ", " + action + " total of " + count
+            + " rows");
    }
 
-   //PersistentServiceSupport overrides ----------------------------
-   
+   // PersistentServiceSupport overrides ----------------------------
+
    protected Map getDefaultDDLStatements()
    {
       Map<String, String> map = new LinkedHashMap<String, String>();
       map.put("CREATE_DUAL", "CREATE TABLE JBM_DUAL (DUMMY INTEGER)");
-      //Message reference
+      // Message reference
       map.put("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))");
-      map.put("CREATE_IDX_MESSAGE_REF_TX", "CREATE INDEX JBM_MSG_REF_TX ON JBM_MSG_REF (TRANSACTION_ID)");
-      map.put("CREATE_IDX_MESSAGE_REF_ORD", "CREATE INDEX JBM_MSG_REF_ORD ON JBM_MSG_REF (ORD)");
-      map.put("CREATE_IDX_MESSAGE_REF_PAGE_ORD", "CREATE INDEX JBM_MSG_REF__PAGE_ORD ON JBM_MSG_REF (PAGE_ORD)");
-      map.put("CREATE_IDX_MESSAGE_REF_MESSAGE_ID", "CREATE INDEX JBM_MSG_REF_MESSAGE_ID ON JBM_MSG_REF (MESSAGE_ID)");      
-      map.put("CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY", "CREATE INDEX JBM_MSG_REF_SCHED_DELIVERY ON JBM_MSG_REF (SCHED_DELIVERY)");      
-      //Message
+              "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))");
+      map.put("CREATE_IDX_MESSAGE_REF_TX",
+              "CREATE INDEX JBM_MSG_REF_TX ON JBM_MSG_REF (TRANSACTION_ID)");
+      map.put("CREATE_IDX_MESSAGE_REF_ORD",
+              "CREATE INDEX JBM_MSG_REF_ORD ON JBM_MSG_REF (ORD)");
+      map.put("CREATE_IDX_MESSAGE_REF_PAGE_ORD",
+              "CREATE INDEX JBM_MSG_REF__PAGE_ORD ON JBM_MSG_REF (PAGE_ORD)");
+      map.put("CREATE_IDX_MESSAGE_REF_MESSAGE_ID",
+              "CREATE INDEX JBM_MSG_REF_MESSAGE_ID ON JBM_MSG_REF (MESSAGE_ID)");
+      map.put("CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY",
+              "CREATE INDEX JBM_MSG_REF_SCHED_DELIVERY ON JBM_MSG_REF (SCHED_DELIVERY)");
+      // Message
       map.put("CREATE_MESSAGE",
-              "CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), " +
-              "EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, TYPE TINYINT, INS_TIME BIGINT, HEADERS LONGVARBINARY, " +
-              "PAYLOAD LONGVARBINARY, " +
-              "PRIMARY KEY (MESSAGE_ID))"); 
-      map.put("CREATE_IDX_MESSAGE_TIMESTAMP", "CREATE INDEX JBM_MSG_REF_TIMESTAMP ON JBM_MSG (TIMESTAMP)");
-      //Transaction
+              "CREATE TABLE JBM_MSG (MESSAGE_ID BIGINT, RELIABLE CHAR(1), "
+            + "EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, TYPE TINYINT, HEADERS LONGVARBINARY, "
+            + "PAYLOAD LONGVARBINARY, "
+            + "PRIMARY KEY (MESSAGE_ID))");
+      // Transaction
       map.put("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))");
-      //Counter
+              "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))");
+      // Counter
       map.put("CREATE_COUNTER",
               "CREATE TABLE JBM_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME))");
       return map;
    }
-      
+
    protected Map getDefaultDMLStatements()
-   {                
+   {
       Map<String, String> map = new LinkedHashMap<String, String>();
       map.put("INSERT_DUAL", "INSERT INTO JBM_DUAL VALUES (1)");
       map.put("CHECK_DUAL", "SELECT 1 FROM JBM_DUAL");
-      //Message reference
+      // Message reference
       map.put("INSERT_MESSAGE_REF",
-              "INSERT INTO JBM_MSG_REF (CHANNEL_ID, MESSAGE_ID, TRANSACTION_ID, STATE, ORD, PAGE_ORD, DELIVERY_COUNT, SCHED_DELIVERY) " +
-              "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
-      map.put("DELETE_MESSAGE_REF", "DELETE FROM JBM_MSG_REF WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'");
+              "INSERT INTO JBM_MSG_REF (CHANNEL_ID, MESSAGE_ID, TRANSACTION_ID, STATE, ORD, PAGE_ORD, DELIVERY_COUNT, SCHED_DELIVERY) "
+            + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+      map.put("DELETE_MESSAGE_REF",
+              "DELETE FROM JBM_MSG_REF WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'");
       map.put("UPDATE_MESSAGE_REF",
-              "UPDATE JBM_MSG_REF SET TRANSACTION_ID=?, STATE='-' " +
-              "WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'");
-      map.put("UPDATE_PAGE_ORDER", "UPDATE JBM_MSG_REF SET PAGE_ORD = ? WHERE MESSAGE_ID=? AND CHANNEL_ID=?");
-      map.put("COMMIT_MESSAGE_REF1", "UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='+'");
-      map.put("COMMIT_MESSAGE_REF2", "DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='-'");
-      map.put("ROLLBACK_MESSAGE_REF1", "DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='+'");
-      map.put("ROLLBACK_MESSAGE_REF2", "UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='-'");
+              "UPDATE JBM_MSG_REF SET TRANSACTION_ID=?, STATE='-' "
+            + "WHERE MESSAGE_ID=? AND CHANNEL_ID=? AND STATE='C'");
+      map.put("UPDATE_PAGE_ORDER",
+              "UPDATE JBM_MSG_REF SET PAGE_ORD = ? WHERE MESSAGE_ID=? AND CHANNEL_ID=?");
+      map.put("COMMIT_MESSAGE_REF1",
+              "UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='+'");
+      map.put("COMMIT_MESSAGE_REF2",
+              "DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='-'");
+      map.put("ROLLBACK_MESSAGE_REF1",
+              "DELETE FROM JBM_MSG_REF WHERE TRANSACTION_ID=? AND STATE='+'");
+      map.put("ROLLBACK_MESSAGE_REF2",
+             "UPDATE JBM_MSG_REF SET STATE='C', TRANSACTION_ID = NULL WHERE TRANSACTION_ID=? AND STATE='-'");
       map.put("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");
+              "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");
       map.put("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");
+              "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");
       map.put("LOAD_REFS",
-              "SELECT MESSAGE_ID, DELIVERY_COUNT, SCHED_DELIVERY FROM JBM_MSG_REF WHERE STATE = 'C' " +
-              "AND CHANNEL_ID = ? ORDER BY ORD");      
-      
-      map.put("UPDATE_REFS_NOT_PAGED", "UPDATE JBM_MSG_REF SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNEL_ID=?");       
-      map.put("SELECT_MIN_MAX_PAGE_ORD", "SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JBM_MSG_REF WHERE CHANNEL_ID = ?");     
-      map.put("SELECT_EXISTS_REF_MESSAGE_ID", "SELECT MESSAGE_ID FROM JBM_MSG_REF WHERE MESSAGE_ID = ?");
-      map.put("UPDATE_DELIVERY_COUNT", "UPDATE JBM_MSG_REF SET DELIVERY_COUNT = ? WHERE CHANNEL_ID = ? AND MESSAGE_ID = ?");
-      map.put("UPDATE_CHANNEL_ID", "UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ?");
-      
-      //Message
+              "SELECT MESSAGE_ID, DELIVERY_COUNT, SCHED_DELIVERY FROM JBM_MSG_REF WHERE STATE = 'C' "
+            + "AND CHANNEL_ID = ? ORDER BY ORD");
+      map.put("UPDATE_REFS_NOT_PAGED",
+              "UPDATE JBM_MSG_REF SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNEL_ID=?");
+      map.put("SELECT_MIN_MAX_PAGE_ORD",
+              "SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JBM_MSG_REF WHERE CHANNEL_ID = ?");
+      map.put("SELECT_EXISTS_REF_MESSAGE_ID",
+              "SELECT MESSAGE_ID FROM JBM_MSG_REF WHERE MESSAGE_ID = ?");
+      map.put("UPDATE_DELIVERY_COUNT",
+              "UPDATE JBM_MSG_REF SET DELIVERY_COUNT = ? WHERE CHANNEL_ID = ? AND MESSAGE_ID = ?");
+      map.put("UPDATE_CHANNEL_ID",
+              "UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ?");
+      map.put("MOVE_REFERENCE",
+              "UPDATE JBM_MSG_REF SET CHANNEL_ID = ? WHERE CHANNEL_ID = ? AND MESSAGE_ID = ?");
+
+      // Message
       map.put("LOAD_MESSAGES",
-              "SELECT MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, " +
-              "PRIORITY, HEADERS, PAYLOAD, TYPE " +
-              "FROM JBM_MSG");
+              "SELECT MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, "
+            + "PRIORITY, HEADERS, PAYLOAD, TYPE " + "FROM JBM_MSG");
       map.put("INSERT_MESSAGE",
-              "INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, " +
-              "TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) " +           
-              "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" );
+              "INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, "
+            + "TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) "
+            + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
       map.put("INSERT_MESSAGE_CONDITIONAL",
-      		  "INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, " +
-              "TIMESTAMP, PRIORITY, TYPE, INS_TIME) " +
-              "SELECT ?, ?, ?, ?, ?, ?, ? " + 
-              "FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)");
-      map.put("INSERT_MESSAGE_CONDITIONAL_FULL", "INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, INS_TIME, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)");
-      map.put("UPDATE_MESSAGE_4CONDITIONAL", "UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?");
+              "INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, "
+         +    "TIMESTAMP, PRIORITY, TYPE) "
+            + "SELECT ?, ?, ?, ?, ?, ? "
+            + "FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)");
+      map.put("INSERT_MESSAGE_CONDITIONAL_FULL",
+              "INSERT INTO JBM_MSG (MESSAGE_ID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, TYPE, HEADERS, PAYLOAD) SELECT ?, ?, ?, ?, ?, ?, ?, ? FROM JBM_DUAL WHERE NOT EXISTS (SELECT MESSAGE_ID FROM JBM_MSG WHERE MESSAGE_ID = ?)");
+      map.put("UPDATE_MESSAGE_4CONDITIONAL",
+              "UPDATE JBM_MSG SET HEADERS=?, PAYLOAD=? WHERE MESSAGE_ID=?");
       map.put("MESSAGE_ID_COLUMN", "MESSAGE_ID");
-      map.put("REAP_MESSAGES", "DELETE FROM JBM_MSG WHERE INS_TIME <= ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = JBM_MSG.MESSAGE_ID)");
-      map.put("DELETE_MESSAGE", "DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)");
-      //Transaction
+      map.put("DELETE_MESSAGE",
+              "DELETE FROM JBM_MSG WHERE MESSAGE_ID = ? AND NOT EXISTS (SELECT * FROM JBM_MSG_REF WHERE JBM_MSG_REF.MESSAGE_ID = ?)");
+      // Transaction
       map.put("INSERT_TRANSACTION",
-              "INSERT INTO JBM_TX (NODE_ID, TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID) " +
-              "VALUES(?, ?, ?, ?, ?)");
-      map.put("DELETE_TRANSACTION", "DELETE FROM JBM_TX WHERE NODE_ID = ? AND TRANSACTION_ID = ?");
-      map.put("SELECT_PREPARED_TRANSACTIONS", "SELECT TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID FROM JBM_TX WHERE NODE_ID = ?");
-      map.put("SELECT_MESSAGE_ID_FOR_REF", "SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '+' ORDER BY ORD");
-      map.put("SELECT_MESSAGE_ID_FOR_ACK", "SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '-' ORDER BY ORD");
+              "INSERT INTO JBM_TX (NODE_ID, TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID) "
+          +   "VALUES(?, ?, ?, ?, ?)");
+      map.put("DELETE_TRANSACTION",
+              "DELETE FROM JBM_TX WHERE NODE_ID = ? AND TRANSACTION_ID = ?");
+      map.put("SELECT_PREPARED_TRANSACTIONS",
+              "SELECT TRANSACTION_ID, BRANCH_QUAL, FORMAT_ID, GLOBAL_TXID FROM JBM_TX WHERE NODE_ID = ?");
+      map.put("SELECT_MESSAGE_ID_FOR_REF",
+              "SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '+' ORDER BY ORD");
+      map.put("SELECT_MESSAGE_ID_FOR_ACK",
+              "SELECT MESSAGE_ID, CHANNEL_ID FROM JBM_MSG_REF WHERE TRANSACTION_ID = ? AND STATE = '-' ORDER BY ORD");
       map.put("UPDATE_TX", "UPDATE JBM_TX SET NODE_ID=? WHERE NODE_ID=?");
-      
-      //Counter
-      map.put("UPDATE_COUNTER", "UPDATE JBM_COUNTER SET NEXT_ID = ? WHERE NAME=?");
+
+      // Counter
+      map.put("UPDATE_COUNTER",
+             "UPDATE JBM_COUNTER SET NEXT_ID = ? WHERE NAME=?");
       map.put("SELECT_COUNTER", "SELECT NEXT_ID FROM JBM_COUNTER WHERE NAME=?");
-      map.put("INSERT_COUNTER", "INSERT INTO JBM_COUNTER (NAME, NEXT_ID) VALUES (?, ?)");
-      //Other
-      map.put("SELECT_ALL_CHANNELS", "SELECT DISTINCT(CHANNEL_ID) FROM JBM_MSG_REF");
+      map.put("INSERT_COUNTER",
+              "INSERT INTO JBM_COUNTER (NAME, NEXT_ID) VALUES (?, ?)");
+      // Other
+      map.put("SELECT_ALL_CHANNELS",
+              "SELECT DISTINCT(CHANNEL_ID) FROM JBM_MSG_REF");
 
       return map;
    }
-   
+
    // Private -------------------------------------------------------
-   
+
    private void deleteMessages(final List references) throws Exception
    {
       class DeleteMessagesRunner extends JDBCTxRunner2
       {
          public Object doTransaction() throws Exception
-         {  
+         {
 
             PreparedStatement psMessage = null;
 
             try
             {
-               psMessage = conn.prepareStatement(getSQLStatement("DELETE_MESSAGE"));
-               
+               psMessage = conn
+                     .prepareStatement(getSQLStatement("DELETE_MESSAGE"));
+
                Iterator iter = references.iterator();
-               
+
                while (iter.hasNext())
                {
                   Object obj = iter.next();
@@ -2163,161 +2503,172 @@
                   MessageReference ref;
                   if (obj instanceof MessageReference)
                   {
-                     ref = (MessageReference)obj;
+                     ref = (MessageReference) obj;
                   }
                   else
                   {
-                     ref = ((ChannelRefPair)obj).ref;
-                  }                  
+                     ref = ((ChannelRefPair) obj).ref;
+                  }
 
                   psMessage.setLong(1, ref.getMessage().getMessageID());
                   psMessage.setLong(2, ref.getMessage().getMessageID());
-   
+
                   int rows = psMessage.executeUpdate();
-                  
-                  if (trace) { log.trace("Deleted " + rows + " messages"); }             
 
+                  if (trace)
+                  {
+                     log.trace("Deleted " + rows + " messages");
+                  }
+
                }
-               
+
                return null;
             }
             finally
             {
                closeStatement(psMessage);
-            }  
+            }
          }
       }
-      
-      //Order to avoid deadlock
+
+      // Order to avoid deadlock
       orderReferences(references);
-      
+
       new DeleteMessagesRunner().executeWithRetry();
    }
-   
-   
+
    private void deleteMessage(final long messageID) throws Exception
    {
       class DeleteMessageRunner extends JDBCTxRunner2
       {
          public Object doTransaction() throws Exception
-         {  
+         {
 
             PreparedStatement psMessage = null;
 
             try
             {
-               psMessage = conn.prepareStatement(getSQLStatement("DELETE_MESSAGE"));
+               psMessage = conn
+                     .prepareStatement(getSQLStatement("DELETE_MESSAGE"));
 
                psMessage.setLong(1, messageID);
                psMessage.setLong(2, messageID);
 
                int rows = psMessage.executeUpdate();
 
-               if (trace) { log.trace("Deleted " + rows + " messages"); }             
+               if (trace)
+               {
+                  log.trace("Deleted " + rows + " messages");
+               }
 
                return null;
             }
             finally
             {
                closeStatement(psMessage);
-            }  
+            }
          }
       }
-      
+
       new DeleteMessageRunner().executeWithRetry();
    }
-   
-   
-   private List getMessageChannelPair(String sqlQuery, long transactionId) throws Exception
+
+   private List getMessageChannelPair(String sqlQuery, long transactionId)
+         throws Exception
    {
-      if (trace) log.trace("loading message and channel ids for tx [" + transactionId + "]");
-      
+      if (trace) log.trace("loading message and channel ids for tx ["
+            + transactionId + "]");
+
       if (!this.nodeIDSet)
       {
-      	//Sanity
-      	throw new IllegalStateException("Node id has not been set");
+         // Sanity
+         throw new IllegalStateException("Node id has not been set");
       }
-      
+
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;
       TransactionWrapper wrap = new TransactionWrapper();
-      
+
       try
       {
          conn = ds.getConnection();
-         
+
          ps = conn.prepareStatement(sqlQuery);
-         
+
          ps.setLong(1, transactionId);
-           
+
          rs = ps.executeQuery();
-         
-         //Don't use a Map. A message could be in multiple channels in a tx, so if you use a map
-         //when you put the same message again it's going to overwrite the previous put!!
-         
+
+         // Don't use a Map. A message could be in multiple channels in a tx, so
+         // if you use a map
+         // when you put the same message again it's going to overwrite the
+         // previous put!!
+
          class Holder
          {
             long messageId;
             long channelId;
+
             Holder(long messageId, long channelId)
             {
                this.messageId = messageId;
                this.channelId = channelId;
             }
          }
-         
+
          List<Holder> holders = new ArrayList<Holder>();
-         
-         //Unique set of messages
+
+         // Unique set of messages
          Set<Long> msgIds = new HashSet<Long>();
-         
-         //TODO it would probably have been simpler just to have done all this in a SQL JOIN rather
-         //than do the join in memory.....        
-                  
-         while(rs.next())
-         {            
+
+         // TODO it would probably have been simpler just to have done all this
+         // in a SQL JOIN rather
+         // than do the join in memory.....
+
+         while (rs.next())
+         {
             long messageId = rs.getLong(1);
             long channelId = rs.getLong(2);
-            
+
             Holder holder = new Holder(messageId, channelId);
-            
+
             holders.add(holder);
-                        
+
             msgIds.add(messageId);
-            
-            if (trace) log.trace("Loaded MsgID: " + messageId + " and ChannelID: " + channelId);
+
+            if (trace) log.trace("Loaded MsgID: " + messageId
+                  + " and ChannelID: " + channelId);
          }
-         
+
          Map messageMap = new HashMap();
-         
+
          List messages = getMessages(new ArrayList(msgIds));
-         
-         for (Iterator iter = messages.iterator(); iter.hasNext(); )
+
+         for (Iterator iter = messages.iterator(); iter.hasNext();)
          {
-            Message msg = (Message)iter.next();
-            
-            messageMap.put(new Long(msg.getMessageID()), msg);            
+            Message msg = (Message) iter.next();
+
+            messageMap.put(new Long(msg.getMessageID()), msg);
          }
-         
+
          List returnList = new ArrayList();
-         
-         for (Iterator iter = holders.iterator(); iter.hasNext(); )
+
+         for (Iterator iter = holders.iterator(); iter.hasNext();)
          {
-            Holder holder = (Holder)iter.next();
-            
-            Message msg = (Message)messageMap.get(new Long(holder.messageId));
-            
-            if (msg == null)
-            {
-               throw new IllegalStateException("Cannot find message " + holder.messageId);
-            }
-            
-            MessageChannelPair pair = new MessageChannelPair(msg, holder.channelId);
-            
+            Holder holder = (Holder) iter.next();
+
+            Message msg = (Message) messageMap.get(new Long(holder.messageId));
+
+            if (msg == null) { throw new IllegalStateException(
+                  "Cannot find message " + holder.messageId); }
+
+            MessageChannelPair pair = new MessageChannelPair(msg,
+                  holder.channelId);
+
             returnList.add(pair);
          }
-         
+
          return returnList;
       }
       catch (Exception e)
@@ -2327,35 +2678,43 @@
       }
       finally
       {
-      	closeResultSet(rs);
-      	closeStatement(ps);
-      	closeConnection(conn);
+         closeResultSet(rs);
+         closeStatement(ps);
+         closeConnection(conn);
          wrap.end();
       }
    }
-   
+
    private synchronized long getOrdering()
    {
-      //We generate the ordering for the message reference by taking the lowest 48 bits of the current time and
-      //concatenating with a 15 bit rotating counter to form a string of 63 bits which we then place
-      //in the right most bits of a long, giving a positive signed 63 bit integer.
-      
-      //Having a time element in the ordering means we don't have to maintain a counter in the database
-      //It also helps with failover since if two queues merge after failover then, the ordering will mean
-      //their orderings interleave nicely and they still get consumed in pretty much time order
-      
-      //We only have to guarantee ordering per session, so having slight differences of time on different nodes is
-      //not a problem
-      
-      //The time element is good for about 8919 years - if you're still running JBoss Messaging then, I suggest you need an
-      //upgrade!
-      
+      // We generate the ordering for the message reference by taking the lowest
+      // 48 bits of the current time and
+      // concatenating with a 15 bit rotating counter to form a string of 63
+      // bits which we then place
+      // in the right most bits of a long, giving a positive signed 63 bit
+      // integer.
+
+      // Having a time element in the ordering means we don't have to maintain a
+      // counter in the database
+      // It also helps with failover since if two queues merge after failover
+      // then, the ordering will mean
+      // their orderings interleave nicely and they still get consumed in pretty
+      // much time order
+
+      // We only have to guarantee ordering per session, so having slight
+      // differences of time on different nodes is
+      // not a problem
+
+      // The time element is good for about 8919 years - if you're still running
+      // JBoss Messaging then, I suggest you need an
+      // upgrade!
+
       long order = System.currentTimeMillis();
-      
+
       order = order << 15;
-      
+
       order = order | orderCount;
-      
+
       if (orderCount == Short.MAX_VALUE)
       {
          orderCount = 0;
@@ -2364,66 +2723,66 @@
       {
          orderCount++;
       }
-      
+
       return order;
    }
-         
+
    // Inner classes -------------------------------------------------
-            
+
    private static class ChannelRefPair
    {
       private long channelID;
       private MessageReference ref;
-      
+
       private ChannelRefPair(long channelID, MessageReference ref)
       {
          this.channelID = channelID;
          this.ref = ref;
       }
    }
-   
+
    private class TransactionCallback implements TxCallback
    {
       private Transaction tx;
-      
+
       private List refsToAdd;
-      
+
       private List refsToRemove;
-      
+
       private TransactionCallback(Transaction tx)
       {
          this.tx = tx;
-         
+
          refsToAdd = new ArrayList();
-         
+
          refsToRemove = new ArrayList();
       }
-      
+
       private void addReferenceToAdd(long channelId, MessageReference ref)
       {
          refsToAdd.add(new ChannelRefPair(channelId, ref));
       }
-      
+
       private void addReferenceToRemove(long channelId, MessageReference ref)
       {
          refsToRemove.add(new ChannelRefPair(channelId, ref));
       }
-      
+
       public void afterCommit(boolean onePhase)
       {
-         //NOOP
+         // NOOP
       }
-      
+
       public void afterPrepare()
       {
-         //NOOP
+         // NOOP
       }
-      
+
       public void afterRollback(boolean onePhase)
       {
-         //NOOP
+         // NOOP
       }
-      
+
       public void beforeCommit(boolean onePhase) throws Exception
       {
          if (onePhase)
@@ -2435,17 +2794,17 @@
             handleBeforeCommit2PC(refsToRemove, tx);
          }
       }
-      
+
       public void beforePrepare() throws Exception
       {
          handleBeforePrepare(refsToAdd, refsToRemove, tx);
       }
-      
+
       public void beforeRollback(boolean onePhase) throws Exception
       {
          if (onePhase)
          {
-            //NOOP - nothing in db
+            // NOOP - nothing in db
          }
          else
          {
@@ -2453,37 +2812,37 @@
          }
       }
    }
-   
+
    private void orderReferences(List references)
-   {      
+   {
       Collections.sort(references, MessageOrderComparator.instance);
    }
-      
+
    private static class MessageOrderComparator implements Comparator
    {
       static MessageOrderComparator instance = new MessageOrderComparator();
-      
+
       public int compare(Object o1, Object o2)
-      {        
+      {
          MessageReference ref1;
          MessageReference ref2;
-         
+
          if (o1 instanceof MessageReference)
          {
-            ref1 = (MessageReference)o1;
-            ref2 = (MessageReference)o2;
+            ref1 = (MessageReference) o1;
+            ref2 = (MessageReference) o2;
          }
          else
          {
-            ref1 = ((ChannelRefPair)o1).ref;
-            ref2 = ((ChannelRefPair)o2).ref;
+            ref1 = ((ChannelRefPair) o1).ref;
+            ref2 = ((ChannelRefPair) o2).ref;
          }
-         
-         long id1 = ref1.getMessage().getMessageID();         
-         long id2 = ref2.getMessage().getMessageID(); 
-         
+
+         long id1 = ref1.getMessage().getMessageID();
+         long id2 = ref2.getMessage().getMessageID();
+
          return (id1 < id2 ? -1 : (id1 == id2 ? 0 : 1));
-      }      
+      }
    }
-   
+
 }

Modified: trunk/src/main/org/jboss/messaging/core/impl/JDBCSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/JDBCSupport.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/JDBCSupport.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -38,6 +38,7 @@
 
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.MessagingComponent;
+import org.jboss.util.NestedSQLException;
 
 /**
  * Common functionality for messaging components that need to access a database.
@@ -439,17 +440,28 @@
       private static final int MAX_TRIES = 25;
 
       protected Connection conn;
+      
+      private boolean getConnectionFailed;
 
       public T execute() throws Exception
-      {  
+      {                    
          Transaction tx = tm.suspend();
 
          try
          {
-            conn = ds.getConnection();
+            try
+            {
+               conn = ds.getConnection();
             
-            conn.setAutoCommit(false);
-
+               conn.setAutoCommit(false);
+            }
+            catch (Exception e)
+            {
+               getConnectionFailed = true;
+               
+               throw e;
+            }
+            
             T res = doTransaction();
             
             conn.commit();
@@ -498,13 +510,19 @@
             }
             catch (SQLException  e)
             {
+               if (getConnectionFailed)
+               {
+                  //Do not retry - just throw the exception up
+                  throw e;
+               }
+               
                log.warn("SQLException caught, SQLState " + e.getSQLState() + " code:" + e.getErrorCode() + "- assuming deadlock detected, try:" + (tries + 1), e);
 
                tries++;
                if (tries == MAX_TRIES)
                {
                   log.error("Retried " + tries + " times, now giving up");
-                  throw new IllegalStateException("Failed to excecute transaction");
+                  throw new IllegalStateException("Failed to execute transaction");
                }
                log.warn("Trying again after a pause");
                //Now we wait for a random amount of time to minimise risk of deadlock

Modified: trunk/src/main/org/jboss/messaging/core/impl/PagingChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/PagingChannelSupport.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/PagingChannelSupport.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -210,7 +210,8 @@
          
          doLoad(ili);
          
-         //Maybe we need to load some paged refs
+         //Maybe we need to load some paged refs too since we might not be full (fullSize might have been increased from last
+         //load)
          
          while (checkLoad()) {}
       }

Modified: trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/ClusterConnectionManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/ClusterConnectionManager.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/ClusterConnectionManager.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -470,7 +470,25 @@
 			
 			if (localQueue.isClustered())
 			{				
-				MessageSucker sucker = new MessageSucker(localQueue, info.connection, localInfo.connection, xa, preserveOrdering);
+			   //Find channel id for remote queue - we need this for doing shared DB optimisation
+			   Collection coll = this.postOffice.getAllBindingsForQueueName(queueName);
+			   Iterator iter = coll.iterator();
+			   long sourceChannelID = -1;
+			   while (iter.hasNext())
+			   {
+			      Binding b = (Binding)iter.next();
+			      if (b.queue.getNodeID() == nodeID)
+			      {
+			         sourceChannelID = b.queue.getChannelID();
+			      }
+			   }
+			   if (sourceChannelID == -1)
+			   {
+			      throw new IllegalArgumentException("Cannot find source channel id");
+			   }
+			   			   
+				MessageSucker sucker = new MessageSucker(localQueue, info.connection, localInfo.connection,
+				                                         xa, preserveOrdering, sourceChannelID);
 	
 				info.addSucker(sucker);
 				

Modified: trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/clusterconnection/MessageSucker.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -80,13 +80,15 @@
 	
 	private boolean preserveOrdering;
 	
+	private long sourceChannelID;
+	
 	public String toString()
 	{
 		return "MessageSucker:" + System.identityHashCode(this) + " queue:" + localQueue.getName();
 	}
 			
 	MessageSucker(Queue localQueue, JBossConnection sourceConnection, JBossConnection localConnection,
-			        boolean xa, boolean preserveOrdering)
+			        boolean xa, boolean preserveOrdering, long sourceChannelID)
 	{	
 		if (trace) { log.trace("Creating message sucker, localQueue:" + localQueue + " xa:" + xa + " preserveOrdering:" + preserveOrdering); }
 		
@@ -96,10 +98,16 @@
 		
 		this.localConnection = localConnection;
 		
-		this.xa = xa;
+		//this.xa = xa;
 		
+		//XA is currently disabled for message sucking - this is because JBM 1.4.0 uses shared database so XA is
+		//unnecesary - we can move the ref from one channel to another with a database update
+		this.xa = false;
+		
 		this.preserveOrdering = preserveOrdering;
 		
+		this.sourceChannelID = sourceChannelID;
+		
 		if (xa)
 		{
 			tm = TransactionManagerLocator.getInstance().locate();
@@ -125,8 +133,7 @@
 			JBossSession sess = (JBossSession)sourceConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
 		
 			sourceSession = (SessionDelegate)sess.getDelegate();
-			
-			
+						
 			sess = (JBossSession)localConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 			
 			localSession = (SessionDelegate)sess.getDelegate();
@@ -244,6 +251,9 @@
 		
 		try
 		{
+		   /*
+		   Commented out until JBM 2.0 
+		    
 			boolean startTx = xa && msg.getJMSDeliveryMode() == DeliveryMode.PERSISTENT;
 			
 			if (startTx)
@@ -263,12 +273,18 @@
 				if (trace) { log.trace("Started JTA transaction"); }
 			}
 			
+         org.jboss.messaging.core.contract.Message coreMessage = ((MessageProxy)msg).getMessage();
+         			
 			if (preserveOrdering)
 			{
 				//Add a header saying we have sucked the message
-				((MessageProxy)msg).getMessage().putHeader(org.jboss.messaging.core.contract.Message.CLUSTER_SUCKED, "x");
+				coreMessage.putHeader(org.jboss.messaging.core.contract.Message.CLUSTER_SUCKED, "x");
 			}
 			
+			//Add a header with the node id of the node we sucked from - this is used on the sending end to do
+			//the move optimisation
+			coreMessage.putHeader(org.jboss.messaging.core.contract.Message.SOURCE_CHANNEL_ID, sourceChannelID);
+
 			long timeToLive = msg.getJMSExpiration();
 			if (timeToLive != 0)
 			{
@@ -301,6 +317,39 @@
 				
 				if (trace) { log.trace("Acknowledged message"); }
 			}
+			*/
+
+         org.jboss.messaging.core.contract.Message coreMessage = ((MessageProxy)msg).getMessage();
+                  
+         if (preserveOrdering)
+         {
+            //Add a header saying we have sucked the message
+            coreMessage.putHeader(org.jboss.messaging.core.contract.Message.CLUSTER_SUCKED, "x");
+         }
+         
+         //Add a header with the node id of the node we sucked from - this is used on the sending end to do
+         //the move optimisation
+         coreMessage.putHeader(org.jboss.messaging.core.contract.Message.SOURCE_CHANNEL_ID, sourceChannelID);
+
+         long timeToLive = msg.getJMSExpiration();
+         if (timeToLive != 0)
+         {
+            timeToLive -=  System.currentTimeMillis();
+            if (timeToLive <= 0)
+            {
+               timeToLive = 1; //Should have already expired - set to 1 so it expires when it is consumed or delivered
+            }
+         }
+         
+         //First we ack it - this ack only occurs in memory even if it is a persistent message
+         msg.acknowledge();
+         
+         if (trace) { log.trace("Acknowledged message"); }     
+         
+         //Then we send - this causes the ref to be moved (SQL UPDATE) in the database        
+         producer.send(null, msg, msg.getJMSDeliveryMode(), msg.getJMSPriority(), timeToLive, true);
+         
+         if (trace) { log.trace(this + " forwarded message to queue"); }                      
 		}
 		catch (Exception e)
 		{

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/GroupMember.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -29,6 +29,9 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.contract.ChannelFactory;
@@ -83,18 +86,12 @@
    
    private Object waitLock = new Object();
    
-   private static final int STOPPED = 1;
-
-   private static final int WAITING_FOR_FIRST_VIEW = 2;
+   private AtomicBoolean ready = new AtomicBoolean(false);
    
-   private static final int WAITING_FOR_STATE = 3;
+   private CountDownLatch latch;
    
-   private static final int STARTED = 4;
+   private volatile boolean starting;
    
-   private volatile int startedState;
-   
-   private volatile Thread viewThread;
-   
    //We need to process view changes on a different thread, since if we have more than one node running
    //in the same VM then the thread that sends the leave message ends up executing the view change on the other node
    //We probably don't need this if all nodes are in different VMs
@@ -122,8 +119,6 @@
    	
       this.dataChannel = jChannelFactory.createDataChannel();
       
-      this.startedState = STOPPED;
-      
       // We don't want to receive local messages on any of the channels
       controlChannel.setOpt(Channel.LOCAL, Boolean.FALSE);
 
@@ -141,8 +136,8 @@
       
       dataChannel.setReceiver(dataReceiver);
       
-      this.startedState = WAITING_FOR_FIRST_VIEW;
-
+      starting = true;
+         
       controlChannel.connect(groupName);
          
       //The first thing that happens after connect is a view change arrives
@@ -150,30 +145,31 @@
       //Then the control messages will start arriving.
       //We can guarantee that messages won't arrive until after the state is set because we use 
       //the FLUSH protocol on the control channel
+          
+      boolean first =  !(controlChannel.getState(null, stateTimeout));
       
-      //First wait for view
-      waitForStateChange(WAITING_FOR_STATE);
-      
-      log.debug("First view arrived");
-      
-      //Now wait for state if we are not the first member
-      
-      if (controlChannel.getState(null, stateTimeout))
+      if (first)
+      {
+         //First member of the group
+         
+         //Can now start accepting messages
+         
+         ready.set(true);
+         
+         latch.countDown();
+         
+         starting = false;
+         
+         log.debug("We are the first member of the group so no need to wait for state");
+      }
+      else
    	{
    		//We are not the first member of the group, so let's wait for state to be got and processed
    		
-   		waitForStateChange(STARTED);
+   		waitForState();
    		
    		log.debug("State arrived");
-   	}
-   	else
-   	{
-   		//We are the first member, no need to wait
-   		
-   		startedState = STARTED;
-   		
-   		log.debug("We are the first member of the group so no need to wait for state");
-   	}
+   	}   	
       
       //Now connect the data channel.
    	
@@ -182,11 +178,8 @@
    
    public void stop() throws Exception
    {	
-   	if (startedState == STOPPED)
-   	{
-   		throw new IllegalStateException("Is already stopped");
-   	}
-   	
+      ready.set(false);
+      
    	try
    	{
    		dataChannel.close();
@@ -211,16 +204,16 @@
    	
    	currentView = null;
 
-      // Workaround for JGroups
+      // FIXME - Workaround for JGroups FLUSH protocol - it needs time
       Thread.sleep(1000);
    }
    
-   public Address getSyncAddress()
+   public Address getControlChannelAddress()
    {
    	return controlChannel.getLocalAddress();
    }
    
-   public Address getAsyncAddress()
+   public Address getDataChannelAddress()
    {
    	return dataChannel.getLocalAddress();
    }
@@ -237,7 +230,7 @@
    
    public void multicastControl(ClusterRequest request, boolean sync) throws Exception
    {
-   	if (startedState == STARTED)
+   	if (ready.get())
    	{   		
 	   	if (trace) { log.trace(this + " multicasting " + request + " to control channel, sync=" + sync); }
 	
@@ -265,7 +258,7 @@
    
    public void unicastControl(ClusterRequest request, Address address, boolean sync) throws Exception
    {
-   	if (startedState == STARTED)
+   	if (ready.get())
    	{   		
 	   	if (trace) { log.trace(this + " multicasting " + request + " to control channel, sync=" + sync); }
 	
@@ -296,7 +289,7 @@
    
    public void multicastData(ClusterRequest request) throws Exception
    {
-   	if (startedState == STARTED)
+   	if (ready.get())
    	{   		
 	   	if (trace) { log.trace(this + " multicasting " + request + " to data channel"); }
 	
@@ -308,7 +301,7 @@
    
    public void unicastData(ClusterRequest request, Address address) throws Exception
    {
-   	if (startedState == STARTED)
+   	if (ready.get())
    	{
 	   	if (trace) { log.trace(this + " unicasting " + request + " to address " + address); }
 	
@@ -318,40 +311,19 @@
    	}
    }
    
-      
-   public boolean getState() throws Exception
+   private void waitForState() throws Exception
    {
-   	boolean retrievedState = false;
-   	
-   	if (controlChannel.getState(null, stateTimeout))
-   	{
-   		//We are not the first member of the group, so let's wait for state to be got and processed
-   		
-   		waitForStateChange(STARTED);
-   		
-   		retrievedState = true;
-   	}
-   	else
-   	{
-   		this.startedState = STARTED;
-   	}
-
-   	return retrievedState;
-   }
-   
-   private void waitForStateChange(int newState) throws Exception
-   {
    	synchronized (waitLock)
    	{ 
 			long timeRemaining = stateTimeout;
 			
 			long start = System.currentTimeMillis();
 			
-   		while (startedState != newState && timeRemaining > 0)
+   		while (!ready.get() && timeRemaining > 0)
    		{
    			waitLock.wait(stateTimeout);
    			
-   			if (startedState != newState)
+   			if (!ready.get())
    			{
    				long waited = System.currentTimeMillis() - start;
    				
@@ -359,7 +331,7 @@
    			}
    		}
    		
-   		if (startedState != newState)
+   		if (!ready.get())
    		{
    			throw new IllegalStateException("Timed out waiting for state to change");
    		}
@@ -403,9 +375,9 @@
       {
          try
          {     	
-	      	if (startedState != STARTED)
+	      	if (!ready.get())
 	      	{
-	      		throw new IllegalStateException("Received control message but group member is not started: " + startedState);
+	      		throw new IllegalStateException("Received control message but group member is not ready");
 	      	}
       		
 	         if (trace) { log.trace(this + ".ControlMessageListener got state"); }		         
@@ -430,11 +402,6 @@
       {
          synchronized (waitLock)
          {
-         	if (startedState != WAITING_FOR_STATE)
-         	{
-         		throw new IllegalStateException("Received state but started state is " + startedState);
-         	}
-         	
          	try
          	{
          		groupListener.setState(bytes);
@@ -444,7 +411,7 @@
          		log.error("Failed to set state", e);
          	}
          	
-         	startedState = STARTED;
+         	ready.set(true);
          	
             waitLock.notify();
          }
@@ -458,7 +425,26 @@
    {
       public void block()
       {
-         // NOOP
+         /*
+         Note - we must wait on this latch to prevent the following unlikely but possible race condition:
+         Node 1 starts (first member)
+         Node1 calls getState - this returns false
+         Node2 starts, getstate and sends message to group
+         Node 1 receives message and discards it - but it should have kept it
+         Node 1 sets ready = true
+         The latch blocks any other nodes being able to send messages before it is released
+         */
+         try
+         {
+            if (latch != null && !latch.await(stateTimeout, TimeUnit.MILLISECONDS))
+            {
+               log.warn("Timed out waiting for latch to be released");
+            }
+         }
+         catch (InterruptedException e)
+         {
+            log.warn("Thread interrupted");
+         }
       }
 
       public void suspect(Address address)
@@ -469,103 +455,69 @@
       public void viewAccepted(final View newView)
       {     	
       	log.debug(this  + " got new view " + newView + ", old view is " + currentView);
-		      
-      	if (currentView == null)
-      	{
-      		//The first view is arriving
-      		
-      		if (startedState != WAITING_FOR_FIRST_VIEW)
-      		{
-      			throw new IllegalStateException("Got first view but started state is " + startedState);
-      		}
-      	}
-      	else
-      	{
-      		if (startedState != STARTED)
-      		{
-      			return;
-      		}
-      	}
-      	
-      	class ViewChangeRunnable implements Runnable
-      	{	
-      		public void run()
-      		{      		
-   	         // JGroups will make sure this method is never called by more than one thread concurrently
-   	
-   	         View oldView = currentView;
-   	         
-   	         currentView = newView;
-   	
-   	         try
-   	         {
-   	            // Act on membership change, on both cases when an old member left or a new member joined
-   	
-   	            if (oldView != null)
-   	            {
-   	            	List leftNodes = new ArrayList();
-   	               for (Iterator i = oldView.getMembers().iterator(); i.hasNext(); )
-   	               {
-   	                  Address address = (Address)i.next();
-   	                  if (!newView.containsMember(address))
-   	                  {
-   	                  	leftNodes.add(address);
-   	                  }
-   	               }
-   	               if (!leftNodes.isEmpty())
-   	               {
-   	               	groupListener.nodesLeft(leftNodes);
-   	               }
-   	            }
-   	
-   	            for (Iterator i = newView.getMembers().iterator(); i.hasNext(); )
-   	            {
-   	               Address address = (Address)i.next();
-   	               if (oldView == null || !oldView.containsMember(address))
-   	               {
-   	                  groupListener.nodeJoined(address);
-   	               }
-   	            }
-   	         }
-   	         catch (Throwable e)
-   	         {
-   	            log.error("Caught Exception in MembershipListener", e);
-   	            IllegalStateException e2 = new IllegalStateException(e.getMessage());
-   	            e2.setStackTrace(e.getStackTrace());
-   	            throw e2;
-   	         }
-   	         
-   	         if (startedState == WAITING_FOR_FIRST_VIEW)
-   	   		{
-   	         	synchronized (waitLock)
-   	         	{         	
-   		   			startedState = WAITING_FOR_STATE;
-   		   			
-   		   			waitLock.notify();
-   	         	}
-   	   		}
-      		}
-      	}
-      	
-      	//Needs to be executed on different thread to avoid deadlock when running invm
-      	viewThread = new Thread(new ViewChangeRunnable());
-	      	
-	      viewThread.start();      	
+		      	
+         // JGroups will make sure this method is never called by more than one thread concurrently
+
+         View oldView = currentView;
+         
+         currentView = newView;
+         
+         //If the first view shows we are the co-ordinator i.e. first node then we can create a latch
+         //But only the first time and we don't want to do this after ready had been set to true
+         //Otherwise it will never get released!
+         if (newView.size() == 1 && starting &&
+             newView.getMembers().get(0).equals(controlChannel.getLocalAddress()) &&
+             !ready.get())
+         {
+            latch = new CountDownLatch(1);            
+         }
+
+         try
+         {
+            // Act on membership change, on both cases when an old member left or a new member joined
+
+            if (oldView != null)
+            {
+            	List leftNodes = new ArrayList();
+               for (Iterator i = oldView.getMembers().iterator(); i.hasNext(); )
+               {
+                  Address address = (Address)i.next();
+                  if (!newView.containsMember(address))
+                  {
+                  	leftNodes.add(address);
+                  }
+               }
+               if (!leftNodes.isEmpty())
+               {
+               	groupListener.nodesLeft(leftNodes);
+               }
+            }
+
+            for (Iterator i = newView.getMembers().iterator(); i.hasNext(); )
+            {
+               Address address = (Address)i.next();
+               if (oldView == null || !oldView.containsMember(address))
+               {
+                  groupListener.nodeJoined(address);
+               }
+            }
+         }
+         catch (Throwable e)
+         {
+            log.error("Caught Exception in MembershipListener", e);
+            IllegalStateException e2 = new IllegalStateException(e.getMessage());
+            e2.setStackTrace(e.getStackTrace());
+            throw e2;
+         }           	
       }
       	
-
       public byte[] getState()
       {
          // NOOP
          return null;
       }
    }
-   
-      
-      
-   	
-   	
-      
+       
    /*
     * This class is used to listen for messages on the async channel
     */
@@ -598,9 +550,10 @@
 
          try
          {
-      		if (startedState != STARTED)
+      		if (!ready.get())
       		{
-      			throw new IllegalStateException("Received data message but member is not started " + startedState);
+      			//Ignore
+      		   return;
       		}
       		
             byte[] bytes = message.getBuffer();
@@ -624,7 +577,6 @@
       }
    }
    
-
    /*
     * This class is used to handle control channel requests
     */
@@ -636,9 +588,11 @@
 
          try
          {
-      		if (startedState != STARTED)
+      		if (!ready.get())
       		{
-      			throw new IllegalStateException("Received control message but member is not started " + startedState);
+      			//Ignore - it's valid that messages might arrive before state is got - in this case it is safe to ignore
+      		   //those messages
+      		   return null;
       		}
       		         		
             byte[] bytes = message.getBuffer();
@@ -655,7 +609,5 @@
             throw e2;
          }
       }
-   }
-   
-
+   }  
 }

Modified: trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/src/main/org/jboss/messaging/core/impl/postoffice/MessagingPostOffice.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -354,7 +354,7 @@
 	      			"Are you sure you have given each node a unique node id during installation?");
 	      }
 	
-	      PostOfficeAddressInfo info = new PostOfficeAddressInfo(groupMember.getSyncAddress(), groupMember.getAsyncAddress());
+	      PostOfficeAddressInfo info = new PostOfficeAddressInfo(groupMember.getControlChannelAddress(), groupMember.getDataChannelAddress());
 	      
 	      nodeIDAddressMap.put(new Integer(thisNodeID), info);	     
 	      
@@ -1430,7 +1430,7 @@
       {
          Map m = (Map)replicatedData.get(key);
 
-         return m == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(m);
+         return m == null ? Collections.EMPTY_MAP : new HashMap(m);
       }
    }
 
@@ -1933,7 +1933,7 @@
 
       return removed;
    }
-
+   
    private synchronized void calculateFailoverMap()
    {
    	failoverMap.clear();
@@ -1941,55 +1941,63 @@
    	View view = groupMember.getCurrentView();
    	
    	Vector members = view.getMembers();
-   	
+   		
    	for (int i = 0; i < members.size(); i++)
    	{
-   		Address address = (Address)members.get(i);
+   	   Address address = (Address)members.get(i);
+         
+         Integer theNodeID = findNodeIDForAddress(address);
+         
+         if (theNodeID == null)
+         {
+            continue;
+         }
+               
+         Integer fnodeID;
+         int fi = i;
+         do
+         {
+            fi++;
+            
+            if (fi == members.size())
+            {
+               fi = 0;
+            }
+         
+            Address failoverAddress = (Address)members.get(fi);
+            
+            fnodeID = findNodeIDForAddress(failoverAddress);
+         }
+         while (fnodeID == null);
    		
-   		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);	   			   		   
+   		failoverMap.put(theNodeID, fnodeID);	   			   		   
    	}   	
    	
-   	int fid = ((Integer)failoverMap.get(new Integer(thisNodeID))).intValue();
+   	Integer i = (Integer)failoverMap.get(new Integer(thisNodeID));
    	
-   	//if we are the first node in the cluster we don't want to be our own failover node!
-   	
-   	if (fid == thisNodeID)
-   	{
-   		firstNode = true;
-   		failoverNodeID = -1;
+   	if (i != null)
+   	{      	
+      	int fid = i.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;
+      		failoverNodeID = -1;
+      	}
+      	else
+      	{
+      		failoverNodeID = fid;
+      		firstNode = false;	   		
+      	}	  
    	}
    	else
    	{
-   		failoverNodeID = fid;
-   		firstNode = false;	   		
-   	}	   	   	 
+   	   //This can occur if this node joins the group, then another node joins in quick succession before this node
+   	   //has had time to add its nodeid-address mapping.
+   	   //This is ok - it wil be shortly followed by another calculation of the map
+   	}
    	
       log.debug("Updated failover map:\n" + dumpFailoverMap(failoverMap));   	      
    }
@@ -2521,6 +2529,8 @@
    {   	
       Iterator iter = loadedBindings.values().iterator();
       
+      log.trace("Loading bindings");
+      
       while (iter.hasNext())
       {
       	Binding binding = (Binding)iter.next();
@@ -2543,6 +2553,7 @@
          	
             ClusterRequest request = new BindRequest(info, binding.allNodes);
 
+            log.trace("Multicasting bind all");
             groupMember.multicastControl(request, false);         
          }      	
          

Modified: trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -113,7 +113,14 @@
    {
       throw new NotYetImplementedException();
    }
+   
 
+   public void acknowledgeNoPersist(Delivery d) throws Throwable
+   {
+      throw new NotYetImplementedException();
+   }
+
+
    public void cancel(Delivery d) throws Exception
    {
       throw new NotYetImplementedException();

Modified: trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryObserver.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryObserver.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryObserver.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -56,6 +56,11 @@
          notifyAll();
       }
    }
+   
+   public void acknowledgeNoPersist(Delivery d) throws Throwable
+   {
+      // TODO Auto-generated method stub      
+   }
 
    public synchronized void cancel(Delivery d)
    {

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-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -303,5 +303,68 @@
       assertEquals(0, queue.getMessageCount());
    }
    
+   //http://jira.jboss.org/jira/browse/JBMESSAGING-1139
+   //If the downcache is not full when we stop the server, we need to test that when we start it again
+   //it loads ok (previously it wasn't)
+   
+   //First test with downcach never flushed
+   public void testRecoverableQueueRestartWithDownCache() throws Throwable
+   {
+      testRecoverableQueueRestartWithDownCache(110);
+   }
+   
+   //Then with down cache flushed once 
+   public void testRecoverableQueueRestartWithDownCacheAlreadyFlushed() throws Throwable
+   {
+      testRecoverableQueueRestartWithDownCache(130);
+   }
+   
+   private void testRecoverableQueueRestartWithDownCache(int num) throws Throwable
+   {
+      MessagingQueue queue =
+         new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 20, false, 300000);
+      queue.activate();
+      
+      Message[] msgs = new Message[num];
+      
+      MessageReference[] refs = new MessageReference[num];
+            
+      for (int i = 0; i < num; i++)
+      {
+         msgs[i] = CoreMessageFactory.createCoreMessage(i, true, null);
+         
+         refs[i] = msgs[i].createReference();
+                
+         queue.handle(null, refs[i], null); 
+      }
+      
+            
+      pm.stop();
+      tr.stop();
+      ms.stop();
+      
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(),
+                  sc.getPersistenceManagerSQLProperties(),
+                  true, true, true, false, 100, !sc.getDatabaseName().equals("oracle"));   
+      ((JDBCPersistenceManager)pm).injectNodeID(1);
+      pm.start();
+      
+      ms = new SimpleMessageStore();
+      ms.start();
+      
+      tr = new TransactionRepository(pm, ms, idm);
 
+      tr.start();
+         
+      MessagingQueue queue2 =
+         new MessagingQueue(1, "queue1", 1, ms, pm, true, -1, null, 100, 20, 20, false, 300000);
+    
+      queue2.load();
+      queue2.activate();
+                              
+      this.consume(queue2, 0, refs, num);            
+   }
+     
+  
 }

Modified: trunk/tests/src/org/jboss/test/messaging/jms/BrowserTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/BrowserTest.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/BrowserTest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -24,9 +24,11 @@
 import java.util.Enumeration;
 
 import javax.jms.Connection;
+import javax.jms.DeliveryMode;
 import javax.jms.InvalidDestinationException;
 import javax.jms.Message;
 import javax.jms.MessageConsumer;
+import javax.jms.MessageFormatException;
 import javax.jms.MessageProducer;
 import javax.jms.QueueBrowser;
 import javax.jms.Session;
@@ -291,8 +293,8 @@
 			
 			removeAllMessages(queue1.getQueueName(), true, 0);
 		}
-   }
-
+   }   
+   
    // Package protected ----------------------------------------------------------------------------
 	
 	// Protected ------------------------------------------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/jms/SecurityTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/SecurityTest.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/SecurityTest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -173,9 +173,9 @@
       Connection conn = null;
       try
       {
-         conn = cf.createConnection("dilbert", "dogbert");
+         conn = cf.createConnection("john", "needle");
          String clientID = conn.getClientID();
-         assertEquals("Invalid ClientID", "dilbert-id", clientID);
+         assertEquals("Invalid ClientID", "DurableSubscriberExample", clientID);
       }
       finally
       {
@@ -211,7 +211,7 @@
       Connection conn = null;
       try
       {
-         conn = cf.createConnection("dilbert", "dogbert");
+         conn = cf.createConnection("john", "needle");
          conn.setClientID("myID");
          fail();
       }
@@ -434,7 +434,7 @@
       Connection conn = null;
       try
       {
-         conn = cf.createConnection("dilbert", "dogbert");
+         conn = cf.createConnection("john", "needle");
          assertTrue(this.canCreateDurableSub(conn, topic1, "sub2"));
       }
       finally
@@ -453,7 +453,7 @@
       Connection conn = null;
       try
       {
-         conn = cf.createConnection("dilbert", "dogbert");
+         conn = cf.createConnection("john", "needle");
          assertFalse(this.canCreateDurableSub(conn, topic2, "sub3"));
       }
       finally
@@ -504,7 +504,7 @@
       Connection conn = null;
       try
       {
-         conn = cf.createConnection("john", "needle");
+         conn = cf.createConnection("dilbert", "dogbert");
          conn.setClientID("myID5");
          assertTrue(this.canReadDestination(conn, topic3));
          assertTrue(this.canWriteDestination(conn, topic3));

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusterConnectionManagerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusterConnectionManagerTest.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/ClusterConnectionManagerTest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -278,6 +278,119 @@
    	deployCFLocal();
    	suck();
    }
+   
+   // http://jira.jboss.org/jira/browse/JBMESSAGING-1136
+   public void testCreateConsumerBeforeRemoteDeployment() throws Exception
+   {      
+      final int NUM_MESSAGES = 20;      
+      
+      deployCFLocal();      
+      deployLocal();
+      
+      //Send some messages
+      
+      Queue queue0 = (Queue)ic[0].lookup("/queue/suckQueue");
+      
+      Connection conn0 = null;
+      
+      try
+      {
+         conn0 = this.createConnectionOnServer(cf, 0);
+         
+         assertEquals(0, getServerId(conn0));
+         
+         //Send some messages on node 0
+         
+         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sess0.createProducer(queue0);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess0.createTextMessage("message" + i);
+            
+            prod.send(tm);
+         }
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+      }
+      
+      log.info("Sent messages");
+      
+      //Undeploy
+      this.undeployAll();
+      
+      log.info("Undeployed");
+      
+      deployCFRemote();
+      deployRemote();
+      
+      Queue queue1 = (Queue)ic[1].lookup("/queue/suckQueue");
+            
+      //Create the consumer - but the messages will be stranded on other node
+      //Until we deploy - we do this on another thread
+      
+      Thread t = new Thread(new Runnable() {
+         public void run()
+         {
+            try
+            {
+               Thread.sleep(5000);
+               deployCFLocal();
+               deployLocal();
+            }
+            catch (Exception e)
+            {
+               log.error("Failed to deploy", e);
+            }
+         }
+      });
+      
+      t.start();
+      
+      Connection conn1 = null;
+      
+      try
+      {         
+         //Consume them on node 1
+         
+         conn1 = this.createConnectionOnServer(cf, 1);
+         
+         assertEquals(1, getServerId(conn1));
+         
+         Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons1 = sess1.createConsumer(queue1);
+         
+         conn1.start();
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons1.receive(30000);
+            
+            assertNotNull(tm);
+            
+            log.info("Got message " + tm.getText());
+            
+            assertEquals("message" + i, tm.getText());
+         } 
+      }
+      finally
+      {
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+      }
+      
+      t.join();
+      
+   }
    // Package protected ----------------------------------------------------------------------------
 
    // Protected ------------------------------------------------------------------------------------
@@ -298,9 +411,21 @@
 
    private void undeployAll() throws Exception
    {
-   	ServerManagement.undeployQueue("suckQueue", 0);
+      try
+      {
+         ServerManagement.undeployQueue("suckQueue", 0);
+      }
+      catch (Exception ignore)
+      {
+      }
 
-   	ServerManagement.undeployQueue("suckQueue", 1);
+      try
+      {
+         ServerManagement.undeployQueue("suckQueue", 1);
+      }
+      catch (Exception ignore)
+      {
+      }
    	
       String cfName =
    		(String)ServerManagement.getServer(1).getAttribute(ServerManagement.getServerPeerObjectName(), "ClusterPullConnectionFactoryName");
@@ -379,13 +504,6 @@
       	
       	MessageProducer prod = sess0.createProducer(queue0);
       	
-      	//Note! The message must be sent as non persistent for this test
-      	//Since we have not deployed suckQueue on all nodes of the cluster
-      	//this would cause persistent messages to not be delivered since they would
-      	//fail to replicate to their backup (since suckQueue is not deployed on it)
-      	
-      	prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
-      	
       	for (int i = 0; i < NUM_MESSAGES; i++)
       	{
       		TextMessage tm = sess0.createTextMessage("message" + i);

Deleted: trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueDontUseXATest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueDontUseXATest.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueDontUseXATest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1,73 +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.test.messaging.jms.clustering;
-
-import org.jboss.test.messaging.tools.container.ServiceAttributeOverrides;
-import org.jboss.test.messaging.tools.container.ServiceContainer;
-
-
-/**
- * 
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: $</tt>10 Jul 2007
- *
- * $Id: $
- *
- */
-public class DistributedQueueDontUseXATest extends DistributedQueueTestBase
-{
-
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public DistributedQueueDontUseXATest(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-   
-   // Package private ---------------------------------------------
-   
-   // protected ----------------------------------------------------
-   
-   protected void setUp() throws Exception
-   {
-      this.overrides = new ServiceAttributeOverrides();
-      
-      overrides.put(ServiceContainer.SERVER_PEER_OBJECT_NAME, "UseXAForMessagePull", "false");
-   	
-      super.setUp();
-   }
-   
-   // private -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-   
-}

Copied: trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java (from rev 3340, branches/Branch_Stable/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java)
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java	                        (rev 0)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -0,0 +1,1199 @@
+/*
+ * 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.DeliveryMode;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.jboss.test.messaging.tools.ServerManagement;
+
+/**
+ * 
+ * A DistributedQueueTest
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 2796 $</tt>
+ *
+ * $Id: DistributedDestinationsTest.java 2796 2007-06-25 22:24:41Z timfox $
+ *
+ */
+public class DistributedQueueTest extends ClusteringTestBase
+{
+
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public DistributedQueueTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+   
+   public void testMessagePropertiesPreservedOnSuckPersistent() throws Exception
+   {
+   	this.messagePropertiesPreservedOnSuck(true);
+   }
+   
+   public void testMessagePropertiesPreservedOnSuckNonPersistent() throws Exception
+   {
+   	this.messagePropertiesPreservedOnSuck(false);
+   }
+
+   public void testClusteredQueueNonPersistent() throws Exception
+   {
+      clusteredQueue(false);
+   }
+
+   public void testClusteredQueuePersistent() throws Exception
+   {
+      clusteredQueue(true);
+   }
+   
+   public void testLocalNonPersistent() throws Exception
+   {
+      localQueue(false);
+   }
+
+   public void testLocalPersistent() throws Exception
+   {
+      localQueue(true);
+   }   
+   
+   public void testWithConnectionsOnAllNodesClientAck() throws Exception
+   {
+      Connection conn0 = createConnectionOnServer(cf, 0);
+      
+      Connection conn1 = createConnectionOnServer(cf, 1);
+      
+      Connection conn2 = createConnectionOnServer(cf, 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(5000);
+      		
+      		assertNotNull(tm0_1);
+      		
+      		msgIds.add(tm0_1.getText());
+      	}
+      	
+      	tm0_1.acknowledge();
+      	
+      	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(5000);
+      		
+      		assertNotNull(tm0_2);
+      		
+      		msgIds.add(tm0_2.getText());
+      	}
+      	
+      	tm0_2.acknowledge();
+      	
+      	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(5000);
+      		
+      		assertNotNull(tm1_1);
+      		
+      		msgIds.add(tm1_1.getText());
+      	}
+      	
+      	tm1_1.acknowledge();
+      	
+      	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(5000);
+      		      		      		
+      		assertNotNull(tm1_2);
+      		
+      		msgIds.add(tm1_2.getText());
+      	}
+      	
+      	tm1_2.acknowledge();
+      	
+      	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(5000);
+      		
+      		assertNotNull(tm2_1);
+      		
+      		msgIds.add(tm2_1.getText());
+      	}
+      	
+      	tm2_1.acknowledge();
+      	
+      	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(5000);
+      		
+      		assertNotNull(tm2_2);
+      		
+      		msgIds.add(tm2_2.getText());
+      	}
+      	
+      	tm2_2.acknowledge();
+      	
+      	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();
+         }
+      }
+   }
+   
+   public void testMixedSuck() throws Exception
+   {
+      Connection conn0 = null;
+      Connection conn1 = null;
+      Connection conn2 = null;
+
+      try
+      {
+
+         conn0 = this.createConnectionOnServer(cf, 0);
+         conn1 = this.createConnectionOnServer(cf, 1);
+         conn2 = this.createConnectionOnServer(cf, 2);
+         
+         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
+
+         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons2 = sess2.createConsumer(queue[2]);
+         
+         conn0.start();
+         conn2.start();
+
+         final int NUM_MESSAGES = 300;
+
+         
+         // Send at node 0
+
+         MessageProducer prod0 = sess0.createProducer(queue[0]);
+
+         MessageProducer prod2 = sess2.createProducer(queue[2]);
+
+         //Send more messages at node 0 and node 2
+         
+         boolean persistent = false;
+         for (int i = 0; i < NUM_MESSAGES / 2 ; i++)
+         {
+            TextMessage tm = sess0.createTextMessage("message4-" + i);
+
+            prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+            
+            prod0.send(tm);
+            
+            persistent = !persistent;
+         }
+         
+         for (int i = NUM_MESSAGES / 2; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess2.createTextMessage("message4-" + i);
+
+            prod2.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+                        
+            prod2.send(tm);
+            
+            persistent = !persistent;
+         }
+         
+         //consume them on node 2 - we will get messages from both nodes so the order is undefined
+         
+         Set msgs = new HashSet();
+         
+         TextMessage tm = null;
+         
+         do
+         {
+            tm = (TextMessage)cons2.receive(5000);
+            
+            if (tm != null)
+            {                     
+	            msgs.add(tm.getText());
+            }
+         }           
+         while (tm != null);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+         	assertTrue(msgs.contains("message4-" + i));
+         }
+         
+         assertEquals(NUM_MESSAGES, msgs.size());
+                
+         cons2.close();
+         
+         sess2.close();
+         
+         sess2 = conn2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+         
+         cons2 = sess2.createConsumer(queue[2]);
+                  
+         Message msg = cons2.receive(5000);
+         
+         assertNull(msg);                            
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+      }
+   }
+
+   // Package private ---------------------------------------------
+   
+   // protected ----------------------------------------------------
+   
+   protected void setUp() throws Exception
+   {
+      nodeCount = 3;
+
+      super.setUp();
+   }
+
+   // private -----------------------------------------------------
+
+
+   private void clusteredQueue(boolean persistent) throws Exception
+   {
+      Connection conn0 = null;
+      Connection conn1 = null;
+      Connection conn2 = null;
+
+      try
+      {
+         //This will create 3 different connection on 3 different nodes, since
+         //the cf is clustered
+         conn0 = this.createConnectionOnServer(cf, 0);
+         conn1 = this.createConnectionOnServer(cf, 1);
+         conn2 = this.createConnectionOnServer(cf, 2);
+         
+         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
+
+         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons0 = sess0.createConsumer(queue[0]);
+         MessageConsumer cons1 = sess1.createConsumer(queue[1]);
+         MessageConsumer cons2 = sess2.createConsumer(queue[2]);
+         
+         conn0.start();
+         conn1.start();
+         conn2.start();
+
+         // Send at node 0
+
+         MessageProducer prod0 = sess0.createProducer(queue[0]);
+
+         prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+         final int NUM_MESSAGES = 100;
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess0.createTextMessage("message0-" + i);
+
+            prod0.send(tm);
+         }
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons0.receive(1000);
+
+            assertNotNull(tm);
+            
+            assertEquals("message0-" + i, tm.getText());
+         }                 
+
+         Message m = cons0.receive(2000);
+
+         assertNull(m);
+         
+         m = cons1.receive(2000);
+
+         assertNull(m);
+
+         m = cons2.receive(2000);
+
+         assertNull(m);
+
+         // Send at node 1
+
+         MessageProducer prod1 = sess1.createProducer(queue[1]);
+
+         prod1.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess1.createTextMessage("message1-" + i);
+
+            prod1.send(tm);
+         }
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons1.receive(1000);
+
+            assertNotNull(tm);
+
+            assertEquals("message1-" + i, tm.getText());
+         }
+
+         m = cons0.receive(2000);
+
+         assertNull(m);
+         
+         m = cons1.receive(2000);
+
+         assertNull(m);
+
+         m = cons2.receive(2000);
+
+         assertNull(m);
+
+         // Send at node 2
+         
+         MessageProducer prod2 = sess2.createProducer(queue[2]);
+
+         prod2.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess2.createTextMessage("message2-" + i);
+
+            prod2.send(tm);
+         }
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons2.receive(1000);
+
+            assertNotNull(tm);
+
+            assertEquals("message2-" + i, tm.getText());
+         }
+
+         m = cons0.receive(2000);
+
+         assertNull(m);
+         
+         m = cons1.receive(2000);
+
+         assertNull(m);
+
+         m = cons2.receive(2000);
+
+         assertNull(m);
+         
+         
+         //Now close the consumers at node 0 and node 1
+         
+         cons0.close();
+         
+         cons1.close();
+         
+         //Send more messages at node 0
+
+         String messageIdCorrelate[] = new String[NUM_MESSAGES];
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess0.createTextMessage("message3-" + i);
+
+            prod0.send(tm);
+
+            messageIdCorrelate[i] = tm.getJMSMessageID();
+
+            log.info("SetID[" + i + "]=" + tm.getJMSMessageID());
+
+         }
+              
+         // consume them on node2
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons2.receive(1000);
+
+            assertNotNull(tm);
+            assertEquals(messageIdCorrelate[i], tm.getJMSMessageID());
+
+            assertEquals("message3-" + i, tm.getText());
+         }                 
+
+         m = cons2.receive(2000);
+
+         assertNull(m);
+         
+         //Send more messages at node 0 and node 1
+         
+         for (int i = 0; i < NUM_MESSAGES / 2; i++)
+         {
+            TextMessage tm = sess0.createTextMessage("message4-" + i);
+
+            prod0.send(tm);
+         }
+         
+         for (int i = NUM_MESSAGES / 2; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess2.createTextMessage("message4-" + i);
+
+            prod2.send(tm);
+         }
+         
+         //consume them on node 2 - we will get messages from both nodes so the order is undefined
+         
+         Set msgs = new HashSet();
+         
+         TextMessage tm = null;
+         
+         do
+         {
+            tm = (TextMessage)cons2.receive(1000);
+            
+            if (tm != null)
+            {                     
+	            msgs.add(tm.getText());
+            }
+         }           
+         while (tm != null);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+         	assertTrue(msgs.contains("message4-" + i));
+         }
+         
+         assertEquals(NUM_MESSAGES, msgs.size());
+         
+         msgs.clear();
+         
+         // Now repeat but this time creating the consumer after send
+         
+         cons2.close();
+         
+         //	Send more messages at node 0 and node 1
+         
+         for (int i = 0; i < NUM_MESSAGES / 2; i++)
+         {
+            tm = sess0.createTextMessage("message5-" + i);
+
+            prod0.send(tm);
+         }
+         
+         for (int i = NUM_MESSAGES / 2; i < NUM_MESSAGES; i++)
+         {
+            tm = sess1.createTextMessage("message5-" + i);
+
+            prod2.send(tm);
+         }
+         
+         cons2 = sess2.createConsumer(queue[2]);
+         
+         //consume them on node 2 - we will get messages from both nodes so the order is undefined
+         
+         msgs = new HashSet();
+         
+         do
+         {
+            tm = (TextMessage)cons2.receive(1000);
+            
+            if (tm != null)
+            {            
+	            msgs.add(tm.getText());
+            }
+         }     
+         while (tm != null);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+         	assertTrue(msgs.contains("message5-" + i));
+         }
+         
+         assertEquals(NUM_MESSAGES, msgs.size());
+         
+         msgs.clear();
+         
+         
+         //Now send messages at node 0 - but consume from node 1 AND node 2
+         
+         //order is undefined
+         
+         cons2.close();
+         
+         cons1 = sess1.createConsumer(queue[1]);
+         
+         cons2 = sess2.createConsumer(queue[2]);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            tm = sess0.createTextMessage("message6-" + i);
+
+            prod0.send(tm);
+         }
+         
+         msgs = new HashSet();
+         
+         int count = 0;
+         
+         do
+         {
+            tm = (TextMessage)cons1.receive(1000);
+            
+            if (tm != null)
+            {                
+	            msgs.add(tm.getText());
+	            
+	            count++;
+            }
+         }
+         while (tm != null);
+         
+         do
+         {
+            tm = (TextMessage)cons2.receive(1000);
+            
+            if (tm != null)
+            {            
+	            msgs.add(tm.getText());
+	            
+	            count++;
+            }
+         } 
+         while (tm != null);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+         	assertTrue(msgs.contains("message6-" + i));
+         }
+         
+         assertEquals(NUM_MESSAGES, count);
+         
+         msgs.clear();
+         
+         //as above but start consumers AFTER sending
+         
+         cons1.close();
+         
+         cons2.close();
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            tm = sess0.createTextMessage("message7-" + i);
+
+            prod0.send(tm);
+         }
+         
+         cons1 = sess1.createConsumer(queue[1]);
+         
+         cons2 = sess2.createConsumer(queue[2]);
+         
+         
+         msgs = new HashSet();
+         
+         count = 0;
+         
+         do
+         {
+            tm = (TextMessage)cons1.receive(1000);
+            
+            if (tm != null)
+            {            
+	            msgs.add(tm.getText());
+	            
+	            count++;
+            }
+         }
+         while (tm != null);
+         
+         do
+         {
+            tm = (TextMessage)cons2.receive(1000);
+            
+            if (tm != null)
+            {
+	            msgs.add(tm.getText());
+	            
+	            count++;
+            }
+         } 
+         while (tm != null);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+         	assertTrue(msgs.contains("message7-" + i));
+         }
+         
+         assertEquals(NUM_MESSAGES, count);         
+         
+         msgs.clear();
+         
+         
+         // Now send message on node 0, consume on node2, then cancel, consume on node1, cancel, consume on node 0
+         
+         cons1.close();
+         
+         cons2.close();
+         
+         sess2.close();
+         
+         sess2 = conn2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+         
+         cons2 = sess2.createConsumer(queue[2]);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            tm = sess0.createTextMessage("message8-" + i);
+
+            prod0.send(tm);
+         }
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            tm = (TextMessage)cons2.receive(1000);
+            
+            assertNotNull(tm);
+               
+            assertEquals("message8-" + i, tm.getText());
+         } 
+         
+         sess2.close(); // messages should go back on queue
+         
+         //Now try on node 1
+         
+         sess1.close();
+         
+         sess1 = conn1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+         
+         cons1 = sess1.createConsumer(queue[1]);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            tm = (TextMessage)cons1.receive(1000);
+            
+            assertNotNull(tm);
+               
+            assertEquals("message8-" + i, tm.getText());
+         } 
+         
+         sess1.close(); // messages should go back on queue
+         
+         //Now try on node 0
+         
+         cons0 = sess0.createConsumer(queue[0]);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            tm = (TextMessage)cons0.receive(1000);
+            
+            assertNotNull(tm);
+               
+            assertEquals("message8-" + i, tm.getText());
+         }     
+         
+         Message msg = cons0.receive(5000);
+         
+         assertNull(msg);                          
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+      }
+   }
+   
+   private void messagePropertiesPreservedOnSuck(boolean persistent) throws Exception
+   {
+      Connection conn0 = null;
+      Connection conn1 = null;
+      Connection conn2 = null;
+
+      try
+      {
+
+         conn0 = this.createConnectionOnServer(cf, 0);
+         conn1 = this.createConnectionOnServer(cf, 1);
+         conn2 = this.createConnectionOnServer(cf, 2);
+         
+         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
+
+         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons2 = sess2.createConsumer(queue[2]);
+         
+         conn0.start();
+         conn2.start();
+
+         // Send at node 0
+
+         MessageProducer prod0 = sess0.createProducer(queue[0]);
+
+         prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+         
+
+
+         TextMessage tm = sess0.createTextMessage("blahmessage");
+            
+         prod0.setPriority(7);
+         
+         prod0.setTimeToLive(1 * 60 * 60 * 1000);
+
+         prod0.send(tm);
+         
+         long expiration = tm.getJMSExpiration();
+         
+         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+         
+                         
+
+         tm = (TextMessage)cons2.receive(1000);
+         
+         assertNotNull(tm);
+         
+         assertEquals("blahmessage", tm.getText());
+
+         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+         
+         assertEquals(7, tm.getJMSPriority());
+        
+         assertTrue(Math.abs(expiration - tm.getJMSExpiration()) < 100);
+                  
+         Message m = cons2.receive(5000);
+         
+         assertNull(m);
+         
+         
+         //Now do one with expiration = 0
+         
+         
+         tm = sess0.createTextMessage("blahmessage2");
+         
+         prod0.setPriority(7);
+         
+         prod0.setTimeToLive(0);
+
+         prod0.send(tm);
+         
+         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+         
+                         
+
+         tm = (TextMessage)cons2.receive(1000);
+         
+         assertNotNull(tm);
+         
+         assertEquals("blahmessage2", tm.getText());
+
+         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
+         
+         assertEquals(7, tm.getJMSPriority());
+        
+         assertEquals(0, tm.getJMSExpiration());
+                  
+         m = cons2.receive(5000);
+         
+         assertNull(m);                          
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+      }
+   }
+   
+   
+   /* Check that non clustered queues behave properly when deployed on a cluster */
+   private void localQueue(boolean persistent) throws Exception
+   {
+   	Connection conn0 = null;
+      Connection conn1 = null;
+      Connection conn2 = null;
+      
+      //Deploy three non clustered queues with same name on different nodes
+          
+      try
+      {
+         ServerManagement.deployQueue("nonClusteredQueue", "nonClusteredQueue", 200000, 2000, 2000, 0, false);
+         
+         ServerManagement.deployQueue("nonClusteredQueue", "nonClusteredQueue", 200000, 2000, 2000, 1, false);
+         
+         ServerManagement.deployQueue("nonClusteredQueue", "nonClusteredQueue", 200000, 2000, 2000, 2, false);
+         
+         Queue queue0 = (Queue)ic[0].lookup("/nonClusteredQueue");
+         Queue queue1 = (Queue)ic[1].lookup("/nonClusteredQueue");
+         Queue queue2 = (Queue)ic[2].lookup("/nonClusteredQueue");
+      	
+         //This will create 3 different connection on 3 different nodes, since
+         //the cf is clustered
+         conn0 = this.createConnectionOnServer(cf, 0);
+         conn1 = this.createConnectionOnServer(cf, 1);
+         conn2 = this.createConnectionOnServer(cf, 2);
+         
+         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
+
+         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         conn0.start();
+         conn1.start();
+         conn2.start();
+
+         // ==============
+         // Send at node 0
+
+         MessageProducer prod0 = sess0.createProducer(queue0);
+
+         prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+         final int NUM_MESSAGES = 100;
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess0.createTextMessage("message" + i);
+
+            prod0.send(tm);
+         }
+         
+         // Try and consume at node 1
+         
+         MessageConsumer cons1 = sess1.createConsumer(queue1);
+         
+         Message m = cons1.receive(2000);
+
+         assertNull(m);
+         
+         cons1.close();
+         
+         //And at node 2
+         
+         MessageConsumer cons2 = sess2.createConsumer(queue2);
+         
+         m = cons2.receive(2000);
+
+         assertNull(m);
+         
+         cons2.close();
+         
+         // Now consume at node 0
+         
+         MessageConsumer cons0 = sess0.createConsumer(queue0);
+          
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons0.receive(1000);
+
+            assertNotNull(tm);
+            
+            assertEquals("message" + i, tm.getText());
+         }                 
+
+         m = cons0.receive(2000);
+
+         assertNull(m);
+         
+         cons0.close();
+         
+         // ==============
+         // Send at node 1
+
+         MessageProducer prod1 = sess1.createProducer(queue1);
+
+         prod1.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess1.createTextMessage("message" + i);
+
+            prod1.send(tm);
+         }
+         
+         // Try and consume at node 0
+         
+         cons0 = sess0.createConsumer(queue0);
+         
+         m = cons0.receive(2000);
+
+         assertNull(m);
+         
+         cons0.close();
+         
+         //And at node 2
+         
+         cons2 = sess2.createConsumer(queue2);
+         
+         m = cons2.receive(2000);
+
+         assertNull(m);
+         
+         cons2.close();
+         
+         // Now consume at node 1
+         
+         cons1 = sess1.createConsumer(queue1);
+          
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons1.receive(1000);
+
+            assertNotNull(tm);
+            
+            assertEquals("message" + i, tm.getText());
+         }                 
+
+         m = cons1.receive(2000);
+
+         assertNull(m);
+         
+         cons1.close();
+         
+         // ==============
+         // Send at node 2
+
+         MessageProducer prod2 = sess2.createProducer(queue2);
+
+         prod2.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess2.createTextMessage("message" + i);
+
+            prod2.send(tm);
+         }
+         
+         // Try and consume at node 0
+         
+         cons0 = sess0.createConsumer(queue0);
+         
+         m = cons0.receive(2000);
+
+         assertNull(m);
+         
+         cons0.close();
+         
+         //And at node 1
+         
+         cons1 = sess1.createConsumer(queue1);
+         
+         m = cons1.receive(2000);
+
+         assertNull(m);
+         
+         cons1.close();
+         
+         // Now consume at node 2
+         
+         cons2 = sess2.createConsumer(queue2);
+          
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons2.receive(1000);
+
+            assertNotNull(tm);
+            
+            assertEquals("message" + i, tm.getText());
+         }                 
+
+         m = cons2.receive(2000);
+
+         assertNull(m);
+         
+         cons2.close();
+           
+      }
+      finally
+      {
+         if (conn0 != null)
+         {
+            conn0.close();
+         }
+
+         if (conn1 != null)
+         {
+            conn1.close();
+         }
+
+         if (conn2 != null)
+         {
+            conn2.close();
+         }
+         
+         ServerManagement.undeployQueue("nonClusteredQueue", 0);
+         
+         ServerManagement.undeployQueue("nonClusteredQueue", 1);
+         
+         ServerManagement.undeployQueue("nonClusteredQueue", 2);
+      }
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+   
+}

Deleted: trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTestBase.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueTestBase.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1,1202 +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.test.messaging.jms.clustering;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.jms.Connection;
-import javax.jms.DeliveryMode;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-import org.jboss.test.messaging.tools.ServerManagement;
-import org.jboss.jms.message.JBossMessage;
-import org.jboss.jms.message.TextMessageProxy;
-
-
-/**
- * 
- * A DistributedQueueTest
- * 
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 2796 $</tt>
- *
- * $Id: DistributedDestinationsTest.java 2796 2007-06-25 22:24:41Z timfox $
- *
- */
-public abstract class DistributedQueueTestBase extends ClusteringTestBase
-{
-
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public DistributedQueueTestBase(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-   
-   public void testMessagePropertiesPreservedOnSuckPersistent() throws Exception
-   {
-   	this.messagePropertiesPreservedOnSuck(true);
-   }
-   
-   public void testMessagePropertiesPreservedOnSuckNonPersistent() throws Exception
-   {
-   	this.messagePropertiesPreservedOnSuck(false);
-   }
-
-   public void testClusteredQueueNonPersistent() throws Exception
-   {
-      clusteredQueue(false);
-   }
-
-   public void testClusteredQueuePersistent() throws Exception
-   {
-      clusteredQueue(true);
-   }
-   
-   public void testLocalNonPersistent() throws Exception
-   {
-      localQueue(false);
-   }
-
-   public void testLocalPersistent() throws Exception
-   {
-      localQueue(true);
-   }   
-   
-   public void testWithConnectionsOnAllNodesClientAck() throws Exception
-   {
-      Connection conn0 = createConnectionOnServer(cf, 0);
-      
-      Connection conn1 = createConnectionOnServer(cf, 1);
-      
-      Connection conn2 = createConnectionOnServer(cf, 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(5000);
-      		
-      		assertNotNull(tm0_1);
-      		
-      		msgIds.add(tm0_1.getText());
-      	}
-      	
-      	tm0_1.acknowledge();
-      	
-      	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(5000);
-      		
-      		assertNotNull(tm0_2);
-      		
-      		msgIds.add(tm0_2.getText());
-      	}
-      	
-      	tm0_2.acknowledge();
-      	
-      	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(5000);
-      		
-      		assertNotNull(tm1_1);
-      		
-      		msgIds.add(tm1_1.getText());
-      	}
-      	
-      	tm1_1.acknowledge();
-      	
-      	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(5000);
-      		      		      		
-      		assertNotNull(tm1_2);
-      		
-      		msgIds.add(tm1_2.getText());
-      	}
-      	
-      	tm1_2.acknowledge();
-      	
-      	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(5000);
-      		
-      		assertNotNull(tm2_1);
-      		
-      		msgIds.add(tm2_1.getText());
-      	}
-      	
-      	tm2_1.acknowledge();
-      	
-      	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(5000);
-      		
-      		assertNotNull(tm2_2);
-      		
-      		msgIds.add(tm2_2.getText());
-      	}
-      	
-      	tm2_2.acknowledge();
-      	
-      	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();
-         }
-      }
-   }
-   
-   public void testMixedSuck() throws Exception
-   {
-      Connection conn0 = null;
-      Connection conn1 = null;
-      Connection conn2 = null;
-
-      try
-      {
-
-         conn0 = this.createConnectionOnServer(cf, 0);
-         conn1 = this.createConnectionOnServer(cf, 1);
-         conn2 = this.createConnectionOnServer(cf, 2);
-         
-         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
-
-         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         
-         MessageConsumer cons2 = sess2.createConsumer(queue[2]);
-         
-         conn0.start();
-         conn2.start();
-
-         final int NUM_MESSAGES = 300;
-
-         
-         // Send at node 0
-
-         MessageProducer prod0 = sess0.createProducer(queue[0]);
-
-         MessageProducer prod2 = sess2.createProducer(queue[2]);
-
-         //Send more messages at node 0 and node 2
-         
-         boolean persistent = false;
-         for (int i = 0; i < NUM_MESSAGES / 2 ; i++)
-         {
-            TextMessage tm = sess0.createTextMessage("message4-" + i);
-
-            prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-            
-            prod0.send(tm);
-            
-            persistent = !persistent;
-         }
-         
-         for (int i = NUM_MESSAGES / 2; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess2.createTextMessage("message4-" + i);
-
-            prod2.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-                        
-            prod2.send(tm);
-            
-            persistent = !persistent;
-         }
-         
-         //consume them on node 2 - we will get messages from both nodes so the order is undefined
-         
-         Set msgs = new HashSet();
-         
-         TextMessage tm = null;
-         
-         do
-         {
-            tm = (TextMessage)cons2.receive(5000);
-            
-            if (tm != null)
-            {                     
-	            msgs.add(tm.getText());
-            }
-         }           
-         while (tm != null);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-         	assertTrue(msgs.contains("message4-" + i));
-         }
-         
-         assertEquals(NUM_MESSAGES, msgs.size());
-                
-         cons2.close();
-         
-         sess2.close();
-         
-         sess2 = conn2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-         
-         cons2 = sess2.createConsumer(queue[2]);
-                  
-         Message msg = cons2.receive(5000);
-         
-         assertNull(msg);                            
-      }
-      finally
-      {
-         if (conn0 != null)
-         {
-            conn0.close();
-         }
-
-         if (conn1 != null)
-         {
-            conn1.close();
-         }
-
-         if (conn2 != null)
-         {
-            conn2.close();
-         }
-      }
-   }
-
-   // Package private ---------------------------------------------
-   
-   // protected ----------------------------------------------------
-   
-   protected void setUp() throws Exception
-   {
-      nodeCount = 3;
-
-      super.setUp();
-   }
-
-   // private -----------------------------------------------------
-
-
-   private void clusteredQueue(boolean persistent) throws Exception
-   {
-      Connection conn0 = null;
-      Connection conn1 = null;
-      Connection conn2 = null;
-
-      try
-      {
-         //This will create 3 different connection on 3 different nodes, since
-         //the cf is clustered
-         conn0 = this.createConnectionOnServer(cf, 0);
-         conn1 = this.createConnectionOnServer(cf, 1);
-         conn2 = this.createConnectionOnServer(cf, 2);
-         
-         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
-
-         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         
-         MessageConsumer cons0 = sess0.createConsumer(queue[0]);
-         MessageConsumer cons1 = sess1.createConsumer(queue[1]);
-         MessageConsumer cons2 = sess2.createConsumer(queue[2]);
-         
-         conn0.start();
-         conn1.start();
-         conn2.start();
-
-         // Send at node 0
-
-         MessageProducer prod0 = sess0.createProducer(queue[0]);
-
-         prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-         final int NUM_MESSAGES = 100;
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess0.createTextMessage("message0-" + i);
-
-            prod0.send(tm);
-         }
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons0.receive(1000);
-
-            assertNotNull(tm);
-            
-            assertEquals("message0-" + i, tm.getText());
-         }                 
-
-         Message m = cons0.receive(2000);
-
-         assertNull(m);
-         
-         m = cons1.receive(2000);
-
-         assertNull(m);
-
-         m = cons2.receive(2000);
-
-         assertNull(m);
-
-         // Send at node 1
-
-         MessageProducer prod1 = sess1.createProducer(queue[1]);
-
-         prod1.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess1.createTextMessage("message1-" + i);
-
-            prod1.send(tm);
-         }
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons1.receive(1000);
-
-            assertNotNull(tm);
-
-            assertEquals("message1-" + i, tm.getText());
-         }
-
-         m = cons0.receive(2000);
-
-         assertNull(m);
-         
-         m = cons1.receive(2000);
-
-         assertNull(m);
-
-         m = cons2.receive(2000);
-
-         assertNull(m);
-
-         // Send at node 2
-         
-         MessageProducer prod2 = sess2.createProducer(queue[2]);
-
-         prod2.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess2.createTextMessage("message2-" + i);
-
-            prod2.send(tm);
-         }
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons2.receive(1000);
-
-            assertNotNull(tm);
-
-            assertEquals("message2-" + i, tm.getText());
-         }
-
-         m = cons0.receive(2000);
-
-         assertNull(m);
-         
-         m = cons1.receive(2000);
-
-         assertNull(m);
-
-         m = cons2.receive(2000);
-
-         assertNull(m);
-         
-         
-         //Now close the consumers at node 0 and node 1
-         
-         cons0.close();
-         
-         cons1.close();
-         
-         //Send more messages at node 0
-
-         String messageIdCorrelate[] = new String[NUM_MESSAGES];
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess0.createTextMessage("message3-" + i);
-
-            prod0.send(tm);
-
-            messageIdCorrelate[i] = tm.getJMSMessageID();
-
-            log.info("SetID[" + i + "]=" + tm.getJMSMessageID());
-
-         }
-              
-         // consume them on node2
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons2.receive(1000);
-
-            assertNotNull(tm);
-            assertEquals(messageIdCorrelate[i], tm.getJMSMessageID());
-
-            assertEquals("message3-" + i, tm.getText());
-         }                 
-
-         m = cons2.receive(2000);
-
-         assertNull(m);
-         
-         //Send more messages at node 0 and node 1
-         
-         for (int i = 0; i < NUM_MESSAGES / 2; i++)
-         {
-            TextMessage tm = sess0.createTextMessage("message4-" + i);
-
-            prod0.send(tm);
-         }
-         
-         for (int i = NUM_MESSAGES / 2; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess2.createTextMessage("message4-" + i);
-
-            prod2.send(tm);
-         }
-         
-         //consume them on node 2 - we will get messages from both nodes so the order is undefined
-         
-         Set msgs = new HashSet();
-         
-         TextMessage tm = null;
-         
-         do
-         {
-            tm = (TextMessage)cons2.receive(1000);
-            
-            if (tm != null)
-            {                     
-	            msgs.add(tm.getText());
-            }
-         }           
-         while (tm != null);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-         	assertTrue(msgs.contains("message4-" + i));
-         }
-         
-         assertEquals(NUM_MESSAGES, msgs.size());
-         
-         msgs.clear();
-         
-         // Now repeat but this time creating the consumer after send
-         
-         cons2.close();
-         
-         //	Send more messages at node 0 and node 1
-         
-         for (int i = 0; i < NUM_MESSAGES / 2; i++)
-         {
-            tm = sess0.createTextMessage("message5-" + i);
-
-            prod0.send(tm);
-         }
-         
-         for (int i = NUM_MESSAGES / 2; i < NUM_MESSAGES; i++)
-         {
-            tm = sess1.createTextMessage("message5-" + i);
-
-            prod2.send(tm);
-         }
-         
-         cons2 = sess2.createConsumer(queue[2]);
-         
-         //consume them on node 2 - we will get messages from both nodes so the order is undefined
-         
-         msgs = new HashSet();
-         
-         do
-         {
-            tm = (TextMessage)cons2.receive(1000);
-            
-            if (tm != null)
-            {            
-	            msgs.add(tm.getText());
-            }
-         }     
-         while (tm != null);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-         	assertTrue(msgs.contains("message5-" + i));
-         }
-         
-         assertEquals(NUM_MESSAGES, msgs.size());
-         
-         msgs.clear();
-         
-         
-         //Now send messages at node 0 - but consume from node 1 AND node 2
-         
-         //order is undefined
-         
-         cons2.close();
-         
-         cons1 = sess1.createConsumer(queue[1]);
-         
-         cons2 = sess2.createConsumer(queue[2]);
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            tm = sess0.createTextMessage("message6-" + i);
-
-            prod0.send(tm);
-         }
-         
-         msgs = new HashSet();
-         
-         int count = 0;
-         
-         do
-         {
-            tm = (TextMessage)cons1.receive(1000);
-            
-            if (tm != null)
-            {                
-	            msgs.add(tm.getText());
-	            
-	            count++;
-            }
-         }
-         while (tm != null);
-         
-         do
-         {
-            tm = (TextMessage)cons2.receive(1000);
-            
-            if (tm != null)
-            {            
-	            msgs.add(tm.getText());
-	            
-	            count++;
-            }
-         } 
-         while (tm != null);
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-         	assertTrue(msgs.contains("message6-" + i));
-         }
-         
-         assertEquals(NUM_MESSAGES, count);
-         
-         msgs.clear();
-         
-         //as above but start consumers AFTER sending
-         
-         cons1.close();
-         
-         cons2.close();
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            tm = sess0.createTextMessage("message7-" + i);
-
-            prod0.send(tm);
-         }
-         
-         cons1 = sess1.createConsumer(queue[1]);
-         
-         cons2 = sess2.createConsumer(queue[2]);
-         
-         
-         msgs = new HashSet();
-         
-         count = 0;
-         
-         do
-         {
-            tm = (TextMessage)cons1.receive(1000);
-            
-            if (tm != null)
-            {            
-	            msgs.add(tm.getText());
-	            
-	            count++;
-            }
-         }
-         while (tm != null);
-         
-         do
-         {
-            tm = (TextMessage)cons2.receive(1000);
-            
-            if (tm != null)
-            {
-	            msgs.add(tm.getText());
-	            
-	            count++;
-            }
-         } 
-         while (tm != null);
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-         	assertTrue(msgs.contains("message7-" + i));
-         }
-         
-         assertEquals(NUM_MESSAGES, count);         
-         
-         msgs.clear();
-         
-         
-         // Now send message on node 0, consume on node2, then cancel, consume on node1, cancel, consume on node 0
-         
-         cons1.close();
-         
-         cons2.close();
-         
-         sess2.close();
-         
-         sess2 = conn2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-         
-         cons2 = sess2.createConsumer(queue[2]);
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            tm = sess0.createTextMessage("message8-" + i);
-
-            prod0.send(tm);
-         }
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            tm = (TextMessage)cons2.receive(1000);
-            
-            assertNotNull(tm);
-               
-            assertEquals("message8-" + i, tm.getText());
-         } 
-         
-         sess2.close(); // messages should go back on queue
-         
-         //Now try on node 1
-         
-         sess1.close();
-         
-         sess1 = conn1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-         
-         cons1 = sess1.createConsumer(queue[1]);
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            tm = (TextMessage)cons1.receive(1000);
-            
-            assertNotNull(tm);
-               
-            assertEquals("message8-" + i, tm.getText());
-         } 
-         
-         sess1.close(); // messages should go back on queue
-         
-         //Now try on node 0
-         
-         cons0 = sess0.createConsumer(queue[0]);
-         
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            tm = (TextMessage)cons0.receive(1000);
-            
-            assertNotNull(tm);
-               
-            assertEquals("message8-" + i, tm.getText());
-         }     
-         
-         Message msg = cons0.receive(5000);
-         
-         assertNull(msg);                          
-      }
-      finally
-      {
-         if (conn0 != null)
-         {
-            conn0.close();
-         }
-
-         if (conn1 != null)
-         {
-            conn1.close();
-         }
-
-         if (conn2 != null)
-         {
-            conn2.close();
-         }
-      }
-   }
-   
-   private void messagePropertiesPreservedOnSuck(boolean persistent) throws Exception
-   {
-      Connection conn0 = null;
-      Connection conn1 = null;
-      Connection conn2 = null;
-
-      try
-      {
-
-         conn0 = this.createConnectionOnServer(cf, 0);
-         conn1 = this.createConnectionOnServer(cf, 1);
-         conn2 = this.createConnectionOnServer(cf, 2);
-         
-         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
-
-         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         
-         MessageConsumer cons2 = sess2.createConsumer(queue[2]);
-         
-         conn0.start();
-         conn2.start();
-
-         // Send at node 0
-
-         MessageProducer prod0 = sess0.createProducer(queue[0]);
-
-         prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-         
-
-
-         TextMessage tm = sess0.createTextMessage("blahmessage");
-            
-         prod0.setPriority(7);
-         
-         prod0.setTimeToLive(1 * 60 * 60 * 1000);
-
-         prod0.send(tm);
-         
-         long expiration = tm.getJMSExpiration();
-         
-         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-         
-                         
-
-         tm = (TextMessage)cons2.receive(1000);
-         
-         assertNotNull(tm);
-         
-         assertEquals("blahmessage", tm.getText());
-
-         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-         
-         assertEquals(7, tm.getJMSPriority());
-        
-         assertTrue(Math.abs(expiration - tm.getJMSExpiration()) < 100);
-                  
-         Message m = cons2.receive(5000);
-         
-         assertNull(m);
-         
-         
-         //Now do one with expiration = 0
-         
-         
-         tm = sess0.createTextMessage("blahmessage2");
-         
-         prod0.setPriority(7);
-         
-         prod0.setTimeToLive(0);
-
-         prod0.send(tm);
-         
-         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-         
-                         
-
-         tm = (TextMessage)cons2.receive(1000);
-         
-         assertNotNull(tm);
-         
-         assertEquals("blahmessage2", tm.getText());
-
-         assertEquals(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT, tm.getJMSDeliveryMode());
-         
-         assertEquals(7, tm.getJMSPriority());
-        
-         assertEquals(0, tm.getJMSExpiration());
-                  
-         m = cons2.receive(5000);
-         
-         assertNull(m);                          
-      }
-      finally
-      {
-         if (conn0 != null)
-         {
-            conn0.close();
-         }
-
-         if (conn1 != null)
-         {
-            conn1.close();
-         }
-
-         if (conn2 != null)
-         {
-            conn2.close();
-         }
-      }
-   }
-   
-   
-   /* Check that non clustered queues behave properly when deployed on a cluster */
-   private void localQueue(boolean persistent) throws Exception
-   {
-   	Connection conn0 = null;
-      Connection conn1 = null;
-      Connection conn2 = null;
-      
-      //Deploy three non clustered queues with same name on different nodes
-          
-      try
-      {
-         ServerManagement.deployQueue("nonClusteredQueue", "nonClusteredQueue", 200000, 2000, 2000, 0, false);
-         
-         ServerManagement.deployQueue("nonClusteredQueue", "nonClusteredQueue", 200000, 2000, 2000, 1, false);
-         
-         ServerManagement.deployQueue("nonClusteredQueue", "nonClusteredQueue", 200000, 2000, 2000, 2, false);
-         
-         Queue queue0 = (Queue)ic[0].lookup("/nonClusteredQueue");
-         Queue queue1 = (Queue)ic[1].lookup("/nonClusteredQueue");
-         Queue queue2 = (Queue)ic[2].lookup("/nonClusteredQueue");
-      	
-         //This will create 3 different connection on 3 different nodes, since
-         //the cf is clustered
-         conn0 = this.createConnectionOnServer(cf, 0);
-         conn1 = this.createConnectionOnServer(cf, 1);
-         conn2 = this.createConnectionOnServer(cf, 2);
-         
-         checkConnectionsDifferentServers(new Connection[] {conn0, conn1, conn2});
-
-         Session sess0 = conn0.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         
-         conn0.start();
-         conn1.start();
-         conn2.start();
-
-         // ==============
-         // Send at node 0
-
-         MessageProducer prod0 = sess0.createProducer(queue0);
-
-         prod0.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-         final int NUM_MESSAGES = 100;
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess0.createTextMessage("message" + i);
-
-            prod0.send(tm);
-         }
-         
-         // Try and consume at node 1
-         
-         MessageConsumer cons1 = sess1.createConsumer(queue1);
-         
-         Message m = cons1.receive(2000);
-
-         assertNull(m);
-         
-         cons1.close();
-         
-         //And at node 2
-         
-         MessageConsumer cons2 = sess2.createConsumer(queue2);
-         
-         m = cons2.receive(2000);
-
-         assertNull(m);
-         
-         cons2.close();
-         
-         // Now consume at node 0
-         
-         MessageConsumer cons0 = sess0.createConsumer(queue0);
-          
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons0.receive(1000);
-
-            assertNotNull(tm);
-            
-            assertEquals("message" + i, tm.getText());
-         }                 
-
-         m = cons0.receive(2000);
-
-         assertNull(m);
-         
-         cons0.close();
-         
-         // ==============
-         // Send at node 1
-
-         MessageProducer prod1 = sess1.createProducer(queue1);
-
-         prod1.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess1.createTextMessage("message" + i);
-
-            prod1.send(tm);
-         }
-         
-         // Try and consume at node 0
-         
-         cons0 = sess0.createConsumer(queue0);
-         
-         m = cons0.receive(2000);
-
-         assertNull(m);
-         
-         cons0.close();
-         
-         //And at node 2
-         
-         cons2 = sess2.createConsumer(queue2);
-         
-         m = cons2.receive(2000);
-
-         assertNull(m);
-         
-         cons2.close();
-         
-         // Now consume at node 1
-         
-         cons1 = sess1.createConsumer(queue1);
-          
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons1.receive(1000);
-
-            assertNotNull(tm);
-            
-            assertEquals("message" + i, tm.getText());
-         }                 
-
-         m = cons1.receive(2000);
-
-         assertNull(m);
-         
-         cons1.close();
-         
-         // ==============
-         // Send at node 2
-
-         MessageProducer prod2 = sess2.createProducer(queue2);
-
-         prod2.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = sess2.createTextMessage("message" + i);
-
-            prod2.send(tm);
-         }
-         
-         // Try and consume at node 0
-         
-         cons0 = sess0.createConsumer(queue0);
-         
-         m = cons0.receive(2000);
-
-         assertNull(m);
-         
-         cons0.close();
-         
-         //And at node 1
-         
-         cons1 = sess1.createConsumer(queue1);
-         
-         m = cons1.receive(2000);
-
-         assertNull(m);
-         
-         cons1.close();
-         
-         // Now consume at node 2
-         
-         cons2 = sess2.createConsumer(queue2);
-          
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            TextMessage tm = (TextMessage)cons2.receive(1000);
-
-            assertNotNull(tm);
-            
-            assertEquals("message" + i, tm.getText());
-         }                 
-
-         m = cons2.receive(2000);
-
-         assertNull(m);
-         
-         cons2.close();
-           
-      }
-      finally
-      {
-         if (conn0 != null)
-         {
-            conn0.close();
-         }
-
-         if (conn1 != null)
-         {
-            conn1.close();
-         }
-
-         if (conn2 != null)
-         {
-            conn2.close();
-         }
-         
-         ServerManagement.undeployQueue("nonClusteredQueue", 0);
-         
-         ServerManagement.undeployQueue("nonClusteredQueue", 1);
-         
-         ServerManagement.undeployQueue("nonClusteredQueue", 2);
-      }
-   }
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-   
-}

Deleted: trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueUseXATest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueUseXATest.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/DistributedQueueUseXATest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -1,73 +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.test.messaging.jms.clustering;
-
-import org.jboss.test.messaging.tools.container.ServiceAttributeOverrides;
-import org.jboss.test.messaging.tools.container.ServiceContainer;
-
-/**
- * 
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: $</tt>10 Jul 2007
- *
- * $Id: $
- *
- */
-public class DistributedQueueUseXATest extends DistributedQueueTestBase
-{
-
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public DistributedQueueUseXATest(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-   
-
-   // Package private ---------------------------------------------
-   
-   // protected ----------------------------------------------------
-   
-   protected void setUp() throws Exception
-   {
-      this.overrides = new ServiceAttributeOverrides();
-      
-      overrides.put(ServiceContainer.SERVER_PEER_OBJECT_NAME, "UseXAForMessagePull", "true");
-   	   	
-      super.setUp();
-   }
-
-   // private -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-   
-}

Modified: trunk/tests/src/org/jboss/test/messaging/jms/clustering/GroupManagementTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/clustering/GroupManagementTest.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/jms/clustering/GroupManagementTest.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -40,7 +40,7 @@
    {
       try
       {
-         ServerManagement.start(0, "all");
+         ServerManagement.start(0, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(1, view.size());
@@ -59,13 +59,13 @@
 
       try
       {
-         ServerManagement.start(0, "all");
+         ServerManagement.start(0, "all", false);
          
          log.info("Started server 0");
 
          ServerManagement.addNotificationListener(0, postOfficeObjectName, listener);
 
-         ServerManagement.start(1, "all");
+         ServerManagement.start(1, "all", false);
 
          log.info("Blocking to receive notification ...");
 
@@ -91,13 +91,13 @@
    {
       try
       {
-         ServerManagement.start(0, "all");
+         ServerManagement.start(0, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(1, view.size());
          assertTrue(view.contains(new Integer(0)));
 
-         ServerManagement.start(1, "all");
+         ServerManagement.start(1, "all", false);
 
          view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(2, view.size());
@@ -121,13 +121,13 @@
    {
       try
       {
-         ServerManagement.start(0, "all");
+         ServerManagement.start(0, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(1, view.size());
          assertTrue(view.contains(new Integer(0)));
 
-         ServerManagement.start(1, "all");
+         ServerManagement.start(1, "all", false);
 
          view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(2, view.size());
@@ -139,7 +139,7 @@
          assertTrue(view.contains(new Integer(0)));
          assertTrue(view.contains(new Integer(1)));
 
-         ServerManagement.start(3, "all");
+         ServerManagement.start(3, "all", false);
 
          view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(3, view.size());
@@ -172,9 +172,9 @@
    {
       try
       {
-         ServerManagement.start(0, "all");
-         ServerManagement.start(1, "all");
-         ServerManagement.start(2, "all");
+         ServerManagement.start(0, "all", false);
+         ServerManagement.start(1, "all", false);
+         ServerManagement.start(2, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(3, view.size());
@@ -201,7 +201,7 @@
 
          // Reuse the "hollow" RMI server 0 to start another cluster node
 
-         ServerManagement.start(0, "all");
+         ServerManagement.start(0, "all", false);
 
          view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(2, view.size());
@@ -211,7 +211,7 @@
 
          // Reuse the "hollow" RMI server 2 to start another cluster node
 
-         ServerManagement.start(2, "all");
+         ServerManagement.start(2, "all", false);
 
          view = ServerManagement.getServer(2).getNodeIDView();
          assertEquals(3, view.size());
@@ -237,8 +237,8 @@
       {
          // Start with a 2 node cluster
 
-         ServerManagement.start(0, "all");
-         ServerManagement.start(1, "all");
+         ServerManagement.start(0, "all", false);
+         ServerManagement.start(1, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(2, view.size());
@@ -283,9 +283,9 @@
       {
          // Start with a 3 node cluster
 
-         ServerManagement.start(0, "all");
-         ServerManagement.start(1, "all");
-         ServerManagement.start(2, "all");
+         ServerManagement.start(0, "all", false);
+         ServerManagement.start(1, "all", false);
+         ServerManagement.start(2, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(3, view.size());
@@ -358,7 +358,7 @@
       {
          // Start with a 1 node cluster
 
-         ServerManagement.start(0, "all");
+         ServerManagement.start(0, "all", false);
 
          Set view = ServerManagement.getServer(0).getNodeIDView();
          assertEquals(1, view.size());
@@ -367,7 +367,7 @@
          ServerManagement.addNotificationListener(0, postOfficeObjectName, clusterEvent);
 
          // start the ninth node, as there is no chance to be started by scripts
-         ServerManagement.start(9, "all");
+         ServerManagement.start(9, "all", false);
 
          if (!clusterEvent.viewChanged(30000))
          {
@@ -387,7 +387,84 @@
          ServerManagement.kill(9);
       }
    }
+   
+   public void testStartServersSimultaneously() throws Exception
+   {
+      final int numServers = 5;
+      
+      try
+      {
+         class ServerStarter extends Thread
+         {
+            int nodeID;
+            boolean failed;
+            ServerStarter(int nodeID)
+            {
+               this.nodeID = nodeID;
+            }
+            
+            public void run()
+            {
+               try
+               {
+                  log.info("Starting " + nodeID);
+                  ServerManagement.start(nodeID, "all", false);
+                  
+                  ServerManagement.deployQueue("testDistributedQueue1", nodeID);
+                  ServerManagement.deployTopic("testDistributedTopic1", nodeID);
+                  
+                  ServerManagement.deployQueue("testDistributedQueue2", nodeID);
+                  ServerManagement.deployTopic("testDistributedTopic2", nodeID);
+                  
+                  ServerManagement.deployQueue("testDistributedQueue3", nodeID);
+                  ServerManagement.deployTopic("testDistributedTopic3", nodeID);
+                  log.info("Done start");
+               }
+               catch (Throwable t)
+               {
+                  log.error("Failed to start server", t);
+                  failed = true;
+               }
+            }
+         }
+         
+         ServerStarter[] starters = new ServerStarter[numServers];         
+         for (int i = 0; i < 5; i++)
+         {
+            starters[i] = new ServerStarter(i);
+            starters[i].start();
+         }
+         
+         boolean failed = false;
+         for (int i = 0; i < 5; i++)
+         {          
+            starters[i].join();
+            if (starters[i].failed)
+            {
+               failed = true;
+            }
+         }
+         
+         assertFalse(failed);
 
+         Set view = ServerManagement.getServer(0).getNodeIDView();
+         assertEquals(numServers, view.size());
+      }
+      finally
+      {
+         for (int i = numServers - 1; i >=0; i--)
+         {
+            try
+            {
+               ServerManagement.stop(i);
+            }
+            catch (Exception ignore)
+            {               
+            }
+         }
+      }
+   }
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/tools/ServerManagement.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/ServerManagement.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/tools/ServerManagement.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -192,10 +192,10 @@
     * When this method correctly completes, the server (local or remote) is started and fully
     * operational (the service container and the server peer are created and started).
     */
-   public static synchronized void start(int i, String config,
-                                         ServiceAttributeOverrides attrOverrides,
-                                         boolean clearDatabase,
-                                         boolean startMessagingServer) throws Exception
+   public static void start(int i, String config,
+                             ServiceAttributeOverrides attrOverrides,
+                             boolean clearDatabase,
+                             boolean startMessagingServer) throws Exception
    {
       log.info("Attempting to start server " + i);
    	
@@ -219,7 +219,7 @@
       }
    }
 
-   public static synchronized void stop() throws Exception
+   public static void stop() throws Exception
    {
       stop(0);
    }
@@ -230,7 +230,7 @@
     * @return true if the server was effectively stopped, or false if the server was alreayd stopped
     *         when the method was invoked.
     */
-   public static synchronized boolean stop(int i) throws Exception
+   public static boolean stop(int i) throws Exception
    {
       if (servers[i] == null)
       {

Modified: trunk/tests/src/org/jboss/test/messaging/tools/container/InVMInitialContextFactory.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/container/InVMInitialContextFactory.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/tools/container/InVMInitialContextFactory.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -47,7 +47,7 @@
 
    static
    {
-      initialContexts = new HashMap();
+      reset();
    }
 
    public static Hashtable getJNDIEnvironment()
@@ -120,6 +120,11 @@
 	      return ic;
    	}
    }
+   
+   public static void reset()
+   {
+       initialContexts = new HashMap();
+   }
 
    // Package protected ---------------------------------------------
 

Modified: trunk/tests/src/org/jboss/test/messaging/tools/container/MockJBossSecurityManager.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/container/MockJBossSecurityManager.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/tools/container/MockJBossSecurityManager.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -248,7 +248,9 @@
          }
          else if ("dilbert".equals(username))
          {
-            return containsRole("durpublisher", roles);
+            return containsRole("publisher", roles) ||
+               containsRole("durpublisher", roles) ||
+               containsRole("def", roles);
          }
          else
          {

Modified: trunk/tests/src/org/jboss/test/messaging/tools/container/RMINamingDelegate.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/container/RMINamingDelegate.java	2007-11-19 11:37:39 UTC (rev 3340)
+++ trunk/tests/src/org/jboss/test/messaging/tools/container/RMINamingDelegate.java	2007-11-19 14:34:57 UTC (rev 3341)
@@ -104,6 +104,8 @@
       public void reset()
       {
          ic = null;
+         
+         InVMInitialContextFactory.reset();
       }
    }
 }




More information about the jboss-cvs-commits mailing list